1
0
mirror of https://github.com/cc65/cc65.git synced 2026-04-20 02:17:07 +00:00

Merge branch 'master' into sane_makefile_output

This commit is contained in:
Gorilla Sapiens
2025-06-18 06:26:58 +00:00
102 changed files with 3395 additions and 265 deletions
+11 -2
View File
@@ -5,14 +5,18 @@ endif
ifdef CMD_EXE
.PHONY: checkstyle
.PHONY: checkstyle sorted
checkstyle:
$(info INFO: style checks require bash.)
sorted:
$(info INFO: table checks require bash.)
else
.PHONY: checkstyle lineendings tabs lastline spaces noexec
.PHONY: checkstyle lineendings tabs lastline spaces noexec sorted
all: checkstyle sorted
checkstyle: lineendings tabs lastline spaces noexec
@@ -31,4 +35,9 @@ spaces: spaces.sh
noexec: noexec.sh
@./noexec.sh
sorted: sorted.sh sorted_codeopt.sh sorted_opcodes.sh
@./sorted.sh
@./sorted_codeopt.sh
@./sorted_opcodes.sh
endif
+38
View File
@@ -0,0 +1,38 @@
#! /bin/bash
OLDCWD=`pwd`
SCRIPT_PATH=`dirname $0`
CHECK_DIR=../../src
SORT_OPT="-u -c"
# $1: filename
function checkarray_quoted_name
{
CHECK_FILE="$1"
START="\\/\\* BEGIN SORTED.SH \\*\\/"
END="\\/\\* END SORTED.SH \\*\\/"
awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \
sed -e 's:\(.*\)##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp
if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then
echo "error: "$1" table is empty"
rm -rf .a.tmp
exit -1
fi
if `LC_COLLATE=C sort $SORT_OPT .a.tmp`; then
echo ""$1" tables OK"
else
echo "error: "$1" tables are not sorted."
rm -rf .a.tmp
exit -1
fi
rm -rf .a.tmp
}
for N in `grep -rl "BEGIN SORTED.SH" "$CHECK_DIR"`; do
checkarray_quoted_name $N
done
+68
View File
@@ -0,0 +1,68 @@
#! /bin/bash
OLDCWD=`pwd`
SCRIPT_PATH=`dirname $0`
CHECK_DIR=../../src
SORT_OPT="-u -c"
# $1: filename
function checkarray
{
CHECK_FILE="$1"
START="\\/\\* BEGIN DECL SORTED_CODEOPT.SH \\*\\/"
END="\\/\\* END DECL SORTED_CODEOPT.SH \\*\\/"
awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \
sed -e 's:\(.*##\).*"\(.*\)",.*:\1\2:g' > .a.tmp
if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then
echo "error: "$1" table is empty"
rm -rf .a.tmp
exit -1
fi
if `LC_COLLATE=C sort $SORT_OPT .a.tmp`; then
echo ""$1" decls sorted."
else
echo "error: "$1" decls are not sorted."
rm -rf .a.tmp
exit -1
fi
START="\\/\\* BEGIN SORTED_CODEOPT.SH \\*\\/"
END="\\/\\* END SORTED_CODEOPT.SH \\*\\/"
awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \
sed -e 's:\(.*##\).*&D\(.*\),.*:\1\2:g' > .b.tmp
if [[ -z $(grep '[^[:space:]]' .b.tmp) ]] ; then
echo "error: "$1" table is empty"
rm -rf .a.tmp .b.tmp
exit -1
fi
if `LC_COLLATE=C sort $SORT_OPT .b.tmp`; then
echo ""$1" tables sorted."
else
echo "error: "$1" tables are not sorted."
rm -rf .a.tmp .b.tmp
exit -1
fi
if cmp --silent -- .a.tmp .b.tmp; then
echo ""$1" tables OK"
else
echo "error: "$1" tables are different."
diff -y .a.tmp .b.tmp
rm -rf .a.tmp .b.tmp
exit -1
fi
rm -rf .a.tmp .b.tmp
}
for N in `grep -rl "BEGIN DECL SORTED_CODEOPT.SH" "$CHECK_DIR"`; do
checkarray $N
done
+40
View File
@@ -0,0 +1,40 @@
#! /bin/bash
OLDCWD=`pwd`
SCRIPT_PATH=`dirname $0`
CHECK_DIR=../../src
SORT_OPT="-u -c"
# $1: filename
function checkarray_quoted_name
{
CHECK_FILE="$1"
START="\\/\\* BEGIN SORTED_OPCODES.SH \\*\\/"
END="\\/\\* END SORTED_OPCODES.SH \\*\\/"
awk '/'"$START"'/{flag=1; count++; next} /'"$END"'/{flag=0;} flag {printf("%04d##%s\n", count, $0)}' "$CHECK_FILE" | \
sed 's:/\*.*::g' | \
grep '".*",' | \
sed -e 's:\(.*\)##.*\"\(.*\)\".*:\1##\2:g' > .a.tmp
if [[ -z $(grep '[^[:space:]]' .a.tmp) ]] ; then
echo "error: "$1" table is empty"
rm -rf .a.tmp
exit -1
fi
if `LC_COLLATE=C sort $SORT_OPT .a.tmp`; then
echo ""$1" tables OK"
else
echo "error: "$1" tables are not sorted."
rm -rf .a.tmp
exit -1
fi
rm -rf .a.tmp
}
for N in `grep -rl "BEGIN SORTED_OPCODES.SH" "$CHECK_DIR"`; do
checkarray_quoted_name $N
done
@@ -24,9 +24,15 @@ jobs:
- name: Do some simple style checks
shell: bash
run: make -j2 checkstyle
- name: Check bsearch tables
shell: bash
run: make -j2 sorted
- name: Build the tools.
shell: bash
run: make -j2 bin USER_CFLAGS=-Werror
- name: Build the dbginfo example
shell: bash
run: make -j2 -C src test
- name: Build the utilities.
shell: bash
run: make -j2 util
@@ -49,6 +49,9 @@ jobs:
- name: Do some simple style checks
shell: bash
run: make -j2 checkstyle
- name: Check bsearch tables
shell: bash
run: make -j2 sorted
- name: Build the tools.
shell: bash
run: |
+7 -1
View File
@@ -51,7 +51,11 @@ util:
# check the code style
checkstyle:
@$(MAKE) -C .github/checks --no-print-directory $@
@$(MAKE) -C .github/checks --no-print-directory $@
# check bsearch tables
sorted:
@$(MAKE) -C .github/checks --no-print-directory $@
# runs regression tests, requires libtest target libraries
test:
@@ -60,6 +64,8 @@ test:
# GNU "check" target, which runs all tests
check:
@$(MAKE) -C .github/checks checkstyle --no-print-directory
@$(MAKE) -C .github/checks sorted --no-print-directory
@$(MAKE) -C src test --no-print-directory
@$(MAKE) test
@$(MAKE) -C targettest platforms --no-print-directory
@$(MAKE) -C samples platforms --no-print-directory
+1
View File
@@ -39,6 +39,7 @@ the [cc65 web site](https://cc65.github.io):
| Dr. Jozo Dujmović | Picocomputer (RP6502) |
| Watara | Watura/QuickShot Supervision |
| Synertek | SYM-1 |
| USSR | Agat-7/9 |
A generic configuration to adapt cc65 to new targets is also around.
+39
View File
@@ -0,0 +1,39 @@
;-----------------------------------------------------------------------------
; 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
CURSOR := $2D ; Cursor character
TATTR := $32 ; Text attributes
PROMPT := $33 ; Used by GETLN
VCOUT := $36 ; COUT Subroutine Vector
VCIN := $38 ; CIN Subroutine Vector
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
; Game controller
BUTN0 := $C061 ; Open-Apple Key
BUTN1 := $C062 ; Closed-Apple Key
+2
View File
@@ -24,6 +24,8 @@ 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
ROM_RST := $FFFC ; 6502 reset vector
ROM_IRQ := $FFFE ; 6502 IRQ vector
;-----------------------------------------------------------------------------
; 80 column firmware
+44
View File
@@ -0,0 +1,44 @@
# Default configuration
FEATURES {
STARTADDRESS: default = $1903;
}
SYMBOLS {
__EXEHDR__: type = import;
__FILETYPE__: type = weak, value = $0006; # file type
__STACKSIZE__: type = weak, value = $0400; # 1k stack
__HIMEM__: type = weak, value = $C000; # Presumed RAM end
}
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__;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXEHDR: load = HEADER, type = ro, optional = yes;
STARTUP: load = MAIN, type = ro, optional = 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, optional = yes;
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__;
}
+56
View File
@@ -0,0 +1,56 @@
# Linker configuration that allows for a hi-res bitmap at $C000-$DF3F, but
# puts the stack (and a "HIBSS" segment) in the remaining RAM at $DF40-$FD00.
FEATURES {
STARTADDRESS: default = $1001;
}
SYMBOLS {
__LOADADDR__: type = import;
__EXEHDR__: type = import;
__STACKSIZE__: type = weak, value = $0800; # 2k stack
__HIMEM__: type = weak, value = $FD00;
}
MEMORY {
# Reserve 8000 bytes at $C000 for 320x200 bitmap
RESERVED: file = "", define = yes, start = $C000, size = 8000;
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 = __RESERVED_START__ - __MAIN_START__;
# Space between bitmap and top of memory
HIRAM: file = "", define = yes, start = __RESERVED_LAST__, size = __HIMEM__ - __HIRAM_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;
# Allow data between bitmap and top of memory to be used as a second BSS
# space. Define symbols for it so that it can be supplied to _heapadd().
HIBSS: load = HIRAM, type = bss, optional = yes, 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__;
}
+79
View File
@@ -0,0 +1,79 @@
<!doctype linuxdoc system>
<article>
<title>Agat-7/9 - specific information for cc65
<author><url url="https://sourceforge.net/u/olegodintsov/profile/" name="Oleg A. Odintsov">,<newline>
<url url="mailto:sintechs@gmail.com" name="Konstantin Fedorov">
<abstract>
An overview over the Agat-7 and Agat-9 and theirs interfaces to the cc65 C
compiler.
</abstract>
<!-- Table of contents -->
<toc>
<!-- Begin the document -->
<sect>Overview
<p>The Agat was a series of 8-bit computers produced in the Soviet Union from 1983 to 1993.
It was based on Apple II architecture with all electronic components made in the Soviet Union except for 6502 microprocessors supplied by UMC (UM6502A).
<p>If compared to Apple II, Agat had many improvements such as color text mode, additional graphic modes and flexible memory controller.
Agat-7 had an Apple II compatibility card called "Module 121", while Agat-9 had a built-in Apple II+ mode activated by soft-switch.
<p>All mass-produced Agat models were disk-based systems, 2K ROM contained only basic machine language monitor and disassembler.
Agat-7 had 140K floppy-drive based on Apple DISK II, while Agat-9 was supplied with 840K drive having its own sector format and controller.
<sect>Binary format<p>
The standard binary file format generated by the linker for the Agat target is
an AppleSingle file to be compatible with AppleCommander <url url="https://applecommander.github.io/">.
The default load address is &dollar;1903.
<sect>Platform-specific header files<p>
Programs containing Agat-specific code may use the <tt/agat.h/ or
<tt/agat.inc/ include files.
<sect>Usefull info<p>
<sect1>Emulation<p>
<enum>
<item> Oleg Odintsov's Agat Emulator - <url url="https://agatemulator.sourceforge.net/english.html">
<item> MAME - <url url="https://www.mamedev.org/">
</enum>
<sect1>Links<p>
<enum>
<item> Most informative source on Agat (in russian) - <url url="https://agatcomp.ru">
<item> Wikipedia - <url url="https://en.wikipedia.org/wiki/Agat_(computer)">
<item> Controversial article on Agat from <url name="BYTE Magazine November 1984 Vol. 9, No. 12" url="https://archive.org/details/byte-magazine-1984-11/page/n135/mode/2up?view=theater">.
The author reviewed custom-build mockup Agat bearing little relation to even the early Agat systems.
</enum>
<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>
+1 -1
View File
@@ -87,7 +87,7 @@ several useful settings:
exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank
2 at all.
<tag>LC address: &dollar;D000, LC size: &dollar;3000</tag>
<tag>LC address: &dollar;D000, LC size: &dollar;2FFC</tag>
For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all.
</descrip><p>
+1 -1
View File
@@ -88,7 +88,7 @@ several useful settings:
exit then a plain vanilla ProDOS 8 doesn't make use of the Language Card bank
2 at all.
<tag>LC address: &dollar;D000, LC size: &dollar;3000</tag>
<tag>LC address: &dollar;D000, LC size: &dollar;2FFC</tag>
For plain vanilla DOS 3.3 which doesn't make use of the Language Card at all.
</descrip><p>
+18
View File
@@ -3234,6 +3234,12 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".CHARMAP" name=".CH
(see <tt><ref id=".P02" name=".P02"></tt> command).
<sect1><tt>.IFP02X</tt><label id=".IFP02X"><p>
Conditional assembly: Check if the assembler is currently in 6502X mode
(see <tt><ref id=".P02X" name=".P02X"></tt> command).
<sect1><tt>.IFP4510</tt><label id=".IFP4510"><p>
Conditional assembly: Check if the assembler is currently in 4510 mode
@@ -3621,6 +3627,16 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
<tt><ref id=".P4510" name=".P4510"></tt>
<sect1><tt>.P02X</tt><label id=".P02X"><p>
Enable the 6502X instruction set, disable 65SC02, 65C02 and 65816
instructions.
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
@@ -4016,11 +4032,13 @@ See: <tt><ref id=".ASCIIZ" name=".ASCIIZ"></tt>,<tt><ref id=".BYTE" name=".BYTE"
See: <tt><ref id=".CPU" name=".CPU"></tt>,
<tt><ref id=".IFP02" name=".IFP02"></tt>,
<tt><ref id=".IFP02X" name=".IFP02X"></tt>,
<tt><ref id=".IFPDTV" name=".IFPDTV"></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=".P02X" name=".P02X"></tt>,
<tt><ref id=".P816" name=".P816"></tt>,
<tt><ref id=".P4510" name=".P4510"></tt>,
<tt><ref id=".PC02" name=".PC02"></tt>,
+114
View File
@@ -63,6 +63,8 @@ Short options:
-V Print the compiler version number
-W [-+]warning[,...] Control warnings ('-' disables, '+' enables)
-d Debug mode
-dM Output all user macros (needs -E)
-dP Output all predefined macros (needs -E)
-g Add debug info to object file
-h Help (this text)
-j Default characters are signed
@@ -199,6 +201,28 @@ Here is a description of all the command line options:
Enables debug mode, for debugging the behavior of cc65.
<label id="option-dM">
<tag><tt>-dM</tt></tag>
When used with -E, will output <tt>#define</tt> directives for all the user
macros defined during execution of the preprocessor. This does not include
macros defined by the compiler.
Note: Can be combined with <tt/<ref id="option-dP" name="-dP">/ by using
<tt/-dMP/.
<label id="option-dP">
<tag><tt>-dP</tt></tag>
When used with -E, will output <tt>#define</tt> directives for all the macros
defined by the compiler itself. This does not include any user defined macros.
Note: Can be combined with <tt/<ref id="option-dM" name="-dM">/ by using
<tt/-dMP/.
<tag><tt>--debug-tables name</tt></tag>
Writes symbol table information to a file, which includes details on structs, unions
@@ -1154,6 +1178,96 @@ The compiler defines several macros at startup:
<item><tt/__CC65_STD_CC65__/
</itemize>
<label id="macro-CPU">
<tag><tt>__CPU__</tt></tag>
This macro contains a bitset that allows to check if a specific instruction
set is supported. For example, the 65C02 CPU supports all instructions of the
65SC02. So testing for the instruction set of the 65SC02 using the following
check will succeed for both CPUs (and also for the 65816 and HUC6280).
<tscreen><verb>
#if (__CPU__ & __CPU_ISET_65SC02__)
</verb></tscreen>
This is much simpler and more future proof than checking for specific CPUs.
The compiler defines a set of constants named <tt/__CPU_ISET_xxx/ to do the
checks. The <tt/__CPU__/ variable is usually derived from the target system
given, but can be changed using the <tt/<ref id="option--cpu" name="--cpu">/
command line option.
<tag><tt>__CPU_6502__</tt></tag>
This macro is defined if the code is compiled for a 6502 CPU.
<tag><tt>__CPU_6502X__</tt></tag>
This macro is defined if the code is compiled for a 6502 CPU with invalid
opcodes.
<tag><tt>__CPU_6502DTV__</tt></tag>
This macro is defined if the code is compiled for a DTV CPU.
<tag><tt>__CPU_65SC02__</tt></tag>
This macro is defined if the code is compiled for a 65SC02 CPU.
<tag><tt>__CPU_65C02__</tt></tag>
This macro is defined if the code is compiled for a 65C02 CPU.
<tag><tt>__CPU_65816__</tt></tag>
This macro is defined if the code is compiled for a 65816 CPU.
<tag><tt>__CPU_HUC6280__</tt></tag>
This macro is defined if the code is compiled for a HUC6280 CPU.
<tag><tt>__CPU_ISET_6502__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 6502 CPU.
<tag><tt>__CPU_ISET_6502X__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 6502X CPU.
<tag><tt>__CPU_ISET_6502DTV__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 6502DTV CPU.
<tag><tt>__CPU_ISET_65SC02__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 65SC02 CPU.
<tag><tt>__CPU_ISET_65C02__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 65C02 CPU.
<tag><tt>__CPU_ISET_65816__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the 65816 CPU.
<tag><tt>__CPU_ISET_HUC6280__</tt></tag>
This macro expands to a numeric constant that can be used to check the
<tt/<ref id="macro-CPU" name="__CPU__">/ macro for the instruction set
of the HUC6280 CPU.
<tag><tt>__CX16__</tt></tag>
This macro is defined if the target is the Commander X16 (-t cx16).
+3
View File
@@ -109,6 +109,9 @@
<descrip>
<tag><htmlurl url="agat.html" name="agat.html"></tag>
Topics specific to the Agat machines.
<tag><htmlurl url="apple2.html" name="apple2.html"></tag>
Topics specific to the Apple&nbsp;&rsqb;&lsqb;.
+19 -1
View File
@@ -165,8 +165,26 @@ The names in the parentheses denote the symbols to be used for static linking of
<sect1>Graphics drivers<p>
No graphics drivers are currently available for the Plus/4.
<descrip>
<tag><tt/ted-hi.tgi (ted_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 121 TED colors).
Note that the text-mode character matrix and color data are destroyed by this
driver. The driver calls the Kernal <tt/CLRSCR/ routine to return the text
screen to a usable (if empty) state on <tt/tgi_done()/.
This driver places the bitmap at &dollar;C000-&dollar;E000. Programs using
this driver must either be linked with the option <tt/-D
__HIMEM__=&dollar;C000/, or use the <tt/plus4-hires.cfg/ linker configuration.
The <tt/plus4-hires.cfg/ is preferable, as it allows the stack to remain at
&dollar;FCFF, and exposes the remaining high memory from the end of the bitmap
to the stack top as a <tt/HIBSS/ segment that can be used by the programmer,
or given to <tt/_heapadd()/ (using the symbols <tt/_HIBSS_START__/ and
<tt/_HIBSS_SIZE__/).
</descrip><p>
<sect1>Extended memory drivers<p>
+76
View File
@@ -0,0 +1,76 @@
#ifndef _AGAT_H
#define _AGAT_H
/* Check for errors */
#if !defined(__AGAT__)
# error This module may only be used when compiling for the Agat!
#endif
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* 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
/* Characters codes */
#define CH_CTRL_C 0x03
#define CH_ENTER 0x0D
#define CH_ESC 0x1B
#define CH_CURS_LEFT 0x08
#define CH_CURS_RIGHT 0x15
#define CH_CURS_UP 0x19
#define CH_CURS_DOWN 0x1A
#define CH_ESC 0x1B
#define CH_HLINE 0x1B
#define CH_VLINE 0x5C
#define CH_ULCORNER 0x10
#define CH_URCORNER 0x12
#define CH_LLCORNER 0x1D
#define CH_LRCORNER 0x1F
/* 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 AGAT_UNKNOWN 0x00
#define AGAT_7 0x10 /* Agat 7 */
#define AGAT_9 0x20 /* Agat 9 */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
unsigned char get_ostype (void);
/* Get the machine type. Returns one of the AGAT_xxx codes. */
void rebootafterexit (void);
/* Reboot machine after program termination has completed. */
/* 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 _bgcolor(color) COLOR_BLACK
#define _bordercolor(color) COLOR_BLACK
/* End of agat.h */
#endif
+17 -3
View File
@@ -40,6 +40,20 @@
/*****************************************************************************/
#if (__CPU__ & __CPU_ISET_65SC02__)
/* Always inline, three bytes is not more than a jsr */
#define ntohs(x) \
( \
__AX__=(x), \
asm("phx"), \
asm("tax"), \
asm("pla"), \
__AX__ \
)
#define htons(x) ntohs(x)
#else
#if (__OPT_i__ < 200)
int __fastcall__ ntohs (int val);
@@ -56,12 +70,12 @@ int __fastcall__ htons (int val);
)
#define htons(x) ntohs(x)
#endif
#endif /* __OPT_i__ < 200 */
#endif /* __CPU__ & __CPU_ISET_65SC02__ */
long __fastcall__ ntohl (long val);
long __fastcall__ htonl (long val);
/* End of arpa/inet.h */
#endif
+17 -1
View File
@@ -110,7 +110,23 @@
#define COLOR_LIGHTBLUE (BCOLOR_LIGHTBLUE | CATTR_LUMA7)
#define COLOR_GRAY3 (BCOLOR_WHITE | CATTR_LUMA5)
/* TGI color defines */
#define TGI_COLOR_BLACK (BCOLOR_BLACK)
#define TGI_COLOR_WHITE (BCOLOR_WHITE | CATTR_LUMA7)
#define TGI_COLOR_RED (BCOLOR_RED | CATTR_LUMA4)
#define TGI_COLOR_CYAN (BCOLOR_CYAN | CATTR_LUMA7)
#define TGI_COLOR_PURPLE (BCOLOR_LIGHTVIOLET | CATTR_LUMA7)
#define TGI_COLOR_GREEN (BCOLOR_GREEN | CATTR_LUMA7)
#define TGI_COLOR_BLUE (BCOLOR_BLUE | CATTR_LUMA7)
#define TGI_COLOR_YELLOW (BCOLOR_YELLOW | CATTR_LUMA7)
#define TGI_COLOR_ORANGE (BCOLOR_ORANGE | CATTR_LUMA7)
#define TGI_COLOR_BROWN (BCOLOR_BROWN | CATTR_LUMA7)
#define TGI_COLOR_LIGHTRED (BCOLOR_RED | CATTR_LUMA7)
#define TGI_COLOR_GRAY1 (BCOLOR_WHITE | CATTR_LUMA1)
#define TGI_COLOR_GRAY2 (BCOLOR_WHITE | CATTR_LUMA3)
#define TGI_COLOR_LIGHTGREEN (BCOLOR_LIGHTGREEN | CATTR_LUMA7)
#define TGI_COLOR_LIGHTBLUE (BCOLOR_LIGHTBLUE | CATTR_LUMA7)
#define TGI_COLOR_GRAY3 (BCOLOR_WHITE | CATTR_LUMA5)
/* Masks for joy_read */
#define JOY_UP_MASK 0x01
+1 -2
View File
@@ -57,8 +57,7 @@
/* The addresses of the static drivers */
extern void plus4_stdjoy_joy[]; /* Referred to by joy_static_stddrv[] */
extern void plus4_stdser_ser[]; /* Referred to by ser_static_stddrv[] */
extern void ted_hi_tgi[];
/* End of plus4.h */
#endif
+2
View File
@@ -37,6 +37,8 @@
# include <apple2enh.h>
#elif defined(__APPLE2__)
# include <apple2.h>
#elif defined(__AGAT__)
# include <agat.h>
#elif defined(__ATARI__)
# include <atari.h>
#elif defined(__ATARI2600__)
+2 -1
View File
@@ -25,7 +25,8 @@ CBMS = c128 \
GEOS = geos-apple \
geos-cbm
TARGETS = apple2 \
TARGETS = agat \
apple2 \
apple2enh \
atari \
atarixl \
+23
View File
@@ -0,0 +1,23 @@
;
; Ullrich von Bassewitz, 26.10.2000
; Konstantin Fedorov, 12.06.2025
;
; Screen size variables
;
.export screensize
.include "agat.inc"
screensize:
lda WNDWDTH
bit TATTR
bmi t64
lsr
t64:
tax
lda WNDBTM
sec
sbc WNDTOP
tay
rts
+113
View File
@@ -0,0 +1,113 @@
;
; Ullrich von Bassewitz, 27.09.1998
; Oleg A. Odintsov, Moscow, 2024
;
; 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 "agat.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
+18
View File
@@ -0,0 +1,18 @@
;
; Oleg A. Odintsov, Moscow, 2024
;
; void __fastcall__ cclear (unsigned char length);
;
.export _cclear
.import COUT
.include "zeropage.inc"
_cclear:
sta ptr1
lda #$A0
next:
jsr COUT
dec ptr1
bne next
rts
+23
View File
@@ -0,0 +1,23 @@
;
; Oleg A. Odintsov, Moscow, 2024
;
; char cgetc (void);
;
.export _cgetc
.import cursor
.include "agat.inc"
_cgetc:
lda #$DF ; _
bit cursor
bne hascur
lda #$00
hascur:
sta CURSOR
jsr j1
cmp #$A0
bpl :+
and #$7F
: rts
j1: jmp (VCIN)
+33
View File
@@ -0,0 +1,33 @@
;
; Ullrich von Bassewitz, 08.08.1998
; Colin Leroy-Mira, 26.05.2025
; Konstantin Fedorov, 12.06.2025
;
; void chlinexy (unsigned char x, unsigned char y, unsigned char length);
; void chline (unsigned char length);
;
.export _chlinexy, _chline, chlinedirect
.import gotoxy, putchar
.include "zeropage.inc"
_chlinexy:
pha ; Save the length
jsr gotoxy ; Call this one, will pop params
pla ; Restore the length and run into _chline
_chline:
ldx #$1B ; horizontal line character
chlinedirect:
stx tmp1
cmp #$00 ; Is the length zero?
beq done ; Jump if done
sta tmp2
: lda tmp1 ; Screen code
jsr putchar ; Direct output
dec tmp2
bne :-
done: rts
+10
View File
@@ -0,0 +1,10 @@
;
; Kevin Ruland
;
; void clrscr (void);
;
.export _clrscr
.import HOME
_clrscr := HOME
+20
View File
@@ -0,0 +1,20 @@
;
; Oleg A. Odintsov, Moscow, 2024
;
; unsigned char __fastcall__ textcolor (unsigned char color);
;
.export _textcolor
.include "agat.inc"
_textcolor:
ldx TATTR
eor TATTR
and #$07
eor TATTR
sta TATTR
txa
and #$0F
rts
+14
View File
@@ -0,0 +1,14 @@
;
; Oleg A. Odintsov, Moscow, 2024
;
; COUT routine
;
.export COUT
.include "agat.inc"
COUT:
cmp #$10
bpl out
ora #$80
out: jmp (VCOUT)
+60
View File
@@ -0,0 +1,60 @@
;
; Oleg A. Odintsov, Moscow, 2024
; Konstantin Fedorov, 12.06.2025
;
; void __fastcall__ cputcxy (unsigned char x, unsigned char y, char c);
; void __fastcall__ cputc (char c);
;
.import COUT
.export _cputcxy, _cputc, newline, putchar,putchardirect
.import gotoxy, VTABZ
.include "agat.inc"
_cputcxy:
pha
jsr gotoxy
pla
_cputc:
cmp #$0D ; Test for \r = carriage return
bne notleft
ldy #$00
sty CH
rts
notleft:
cmp #$0A ; Test for \n = line feed
beq newline
putchar:
ldy CH
sta (BASL),Y
iny
lda TATTR
bmi wch ; Skip if t64
sta (BASL),Y
iny
wch:
sty CH
cpy WNDWDTH
bcc noend
ldy #$00
sty CH
newline:
inc CV
lda CV
cmp WNDBTM
bcc :+
lda WNDTOP
sta CV
: jmp VTABZ
noend:
rts
putchardirect:
ldy CH
sta (BASL),Y
lda TATTR
bmi :+
iny
sta (BASL),Y
: rts
+78
View File
@@ -0,0 +1,78 @@
;
; Startup code for cc65 (Agat version)
;
.export __STARTUP__ : absolute = 1 ; Mark as startup
.export _exit
.import initlib, donelib
.import zerobss, callmain
.import __ONCE_LOAD__, __ONCE_SIZE__ ; Linker generated
.include "zeropage.inc"
.include "agat.inc"
; ------------------------------------------------------------------------
.segment "STARTUP"
jsr init
jsr zerobss
jsr callmain
_exit:
ldx #<exit
lda #>exit
jsr reset
jsr donelib
exit:
ldx #$02
: lda rvsave,x
sta SOFTEV,x
dex
bpl :-
ldx #zpspace-1
: lda zpsave,x
sta sp,x
dex
bpl :-
ldx #$FF
txs
jmp DOSWARM
.segment "ONCE"
init:
ldx #zpspace-1
: lda sp,x
sta zpsave,x
dex
bpl :-
ldx #$02
: lda SOFTEV,x
sta rvsave,x
dex
bpl :-
lda HIMEM
ldx HIMEM+1
sta sp
stx sp+1
ldx #<_exit
lda #>_exit
jsr reset
jmp initlib
.code
reset:
stx SOFTEV
sta SOFTEV+1
eor #$A5
sta PWREDUP
rts
.segment "INIT"
zpsave: .res zpspace
rvsave: .res 3
+29
View File
@@ -0,0 +1,29 @@
;
; Ullrich von Bassewitz, 08.08.1998
; Colin Leroy-Mira, 26.05.2025
; Konstantin Fedorov, 12.06.2025
;
; void cvlinexy (unsigned char x, unsigned char y, unsigned char length);
; void cvline (unsigned char length);
;
.export _cvlinexy, _cvline
.import gotoxy, putchardirect, 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:
cmp #$00 ; Is the length zero?
beq done ; Jump if done
sta tmp2
: lda #$5C ; vertical line character
jsr putchardirect ; Write, no cursor advance
jsr newline ; Advance cursor to next line
dec tmp2
bne :-
done: rts
+43
View File
@@ -0,0 +1,43 @@
;
; 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.
;
; Agat target uses this header only for compatibility with Apple Commander
; because Agat's 140K disk filesystem is identical to Apple II DOS 3.3 and
; "ac.jar -as" option can be used to import binaries into disk images.
.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:
+28
View File
@@ -0,0 +1,28 @@
;
; Ullrich von Bassewitz, 06.08.1998
; Oleg A. Odintsov, Moscow, 2024
;
; void __fastcall__ gotoxy (unsigned char x, unsigned char y);
; void __fastcall__ gotox (unsigned char x);
;
.export gotoxy, _gotoxy, _gotox
.import popa, VTABZ
.include "agat.inc"
gotoxy:
jsr popa ; Get Y
_gotoxy:
clc
adc WNDTOP
sta CV ; Store Y
jsr VTABZ
jsr popa ; Get X
_gotox:
bit TATTR
bmi t64
asl
t64:
sta CH ; Store X
rts
+16
View File
@@ -0,0 +1,16 @@
;
; Ullrich von Bassewitz, 06.08.1998
; Oleg A. Odintsov, Moscow, 2024
;
; void __fastcall__ gotoy (unsigned char y);
;
.import VTABZ
.export _gotoy
.include "agat.inc"
_gotoy:
clc
adc WNDTOP
sta CV
jmp VTABZ
+15
View File
@@ -0,0 +1,15 @@
;
; Oleg A. Odintsov, Moscow, 2024
;
; HOME routine
;
.export HOME
.import COUT
.include "agat.inc"
HOME:
lda #$8C
jmp COUT
rts
+19
View File
@@ -0,0 +1,19 @@
;
; Kevin Ruland
; Ullrich von Bassewitz, 2005-03-25
; Oleg A. Odintsov, Moscow, 2024
;
; unsigned char kbhit (void);
;
.export _kbhit
.include "agat.inc"
_kbhit:
lda KBD ; Reading KBD checks for keypress
rol ; if high bit is set, key was pressed
lda #$00
tax
rol
rts
+18
View File
@@ -0,0 +1,18 @@
;
; Ullrich von Bassewitz, 07.11.2002
; Oleg A. Odintsov, Moscow, 2024
;
; void _randomize (void);
; /* Initialize the random number generator */
;
.export __randomize
.import _srand
.include "agat.inc"
__randomize:
ldx RNDH ; Use random value supplied by ROM
lda RNDL
jmp _srand ; Initialize generator
+38
View File
@@ -0,0 +1,38 @@
;
; Ullrich von Bassewitz, 2005-03-28
; Oleg A. Odintsov, Moscow, 2024
;
; unsigned char __fastcall__ revers (unsigned char onoff)
; unsigned char __fastcall__ flash (unsigned char onoff)
;
.export _revers, _flash
.include "agat.inc"
_revers:
tax
beq noinv
lda TATTR
and #$D7
sta TATTR
rts
noinv:
lda TATTR
ora #$20
sta TATTR
rts
_flash:
tax
beq noflash
lda TATTR
and #$DF
ora #$08
sta TATTR
rts
noflash:
lda TATTR
ora #$20
sta TATTR
rts
+24
View File
@@ -0,0 +1,24 @@
;
; Oleg A. Odintsov, Moscow, 2024
;
; VTABZ routine
;
.export VTABZ
.include "agat.inc"
VTABZ:
lda CV
ror
ror
ror
and #$C0
sta BASL
lda CV
lsr
lsr
eor BASH
and #$07
eor BASH
sta BASH
rts
+19
View File
@@ -0,0 +1,19 @@
;
; Kevin Ruland
; Oleg A. Odintsov, Moscow, 2024
;
; unsigned char wherex (void);
;
.export _wherex
.include "agat.inc"
_wherex:
lda CH
bit TATTR
bmi t64
lsr
t64:
ldx #$00
rts
+17
View File
@@ -0,0 +1,17 @@
;
; Kevin Ruland
; Oleg A. Odintsov, Moscow, 2024
;
; unsigned char wherey (void);
;
.export _wherey
.include "agat.inc"
_wherey:
lda CV
sec
sbc WNDTOP
ldx #$00
rts
+50
View File
@@ -0,0 +1,50 @@
;
; Oleg A. Odintsov, Moscow, 2024
;
; int __fastcall__ write (int fd, const void* buf, unsigned count);
;
.export _write
.import popax, popptr1
.import COUT
.include "zeropage.inc"
_write:
sta ptr2
stx ptr2+1
jsr popptr1
jsr popax
; Check for zero count
ora ptr2
beq done
; Get char from buf
next: ldy #$00
lda (ptr1),y
; Replace '\n' with '\r'
cmp #$0A
bne output
lda #$8D
; Set hi bit and write to device
output:
jsr COUT ; Preserves X and Y
; Increment pointer
inc ptr1
bne :+
inc ptr1+1
; Decrement count
: dec ptr2
bne next
dec ptr2+1
bpl next
; Return success
done: lda #$00
rts
+23 -1
View File
@@ -58,6 +58,7 @@ init: ldx #zpspace-1
; Check for ProDOS.
ldy $BF00 ; MLI call entry point
cpy #$4C ; Is MLI present? (JMP opcode)
php ; Remember whether we're running ProDOS
bne basic
; Check the ProDOS system bit map.
@@ -99,7 +100,20 @@ basic: lda HIMEM
bit $C081
bit $C081
; Set the source start address.
plp ; Are we running ProDOS?
beq :+ ; Yes, no need to patch vectors
lda #<reset_6502
ldx #>reset_6502
sta ROM_RST
stx ROM_RST+1
lda #<irq_6502
ldx #>irq_6502
sta ROM_IRQ
stx ROM_IRQ+1
: ; Set the source start address.
; Aka __LC_LOAD__ iff segment LC exists.
lda #<(__ONCE_LOAD__ + __ONCE_SIZE__)
ldy #>(__ONCE_LOAD__ + __ONCE_SIZE__)
@@ -144,6 +158,14 @@ quit: jsr $BF00 ; MLI call entry point
.byte $65 ; Quit
.word q_param
reset_6502: ; Used with DOS3.3 programs
bit $C082 ; Switch in ROM
jmp (ROM_RST) ; Jump to ROM's RESET vector
irq_6502: ; Used with DOS3.3 programs
bit $C082 ; Switch in ROM
jmp (ROM_IRQ) ; Jump to ROM's IRQ/BRK vector
; ------------------------------------------------------------------------
.rodata
+5
View File
@@ -18,11 +18,16 @@ _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
lda #%00100000
bit $FF06
bne L2 ; always disable cursor if in bitmap mode
; 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
+47 -21
View File
@@ -9,8 +9,7 @@
.import callirq_y, initlib, donelib
.import callmain, zerobss
.import __INTERRUPTOR_COUNT__
.import __MAIN_START__, __MAIN_SIZE__ ; Linker generated
.import __STACKSIZE__ ; Linker generated
.import __HIMEM__ ; Linker generated
.importzp ST
.include "zeropage.inc"
@@ -52,19 +51,28 @@ L1: lda sp,x
tsx
stx spsave ; Save system stk ptr
lda #<(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
ldx #>(__MAIN_START__ + __MAIN_SIZE__ + __STACKSIZE__)
lda #<__HIMEM__
ldx #>__HIMEM__
sta sp
stx sp+1
; Set up the IRQ vector in the banked RAM; and, switch off the ROM.
ldx #<IRQ
ldy #>IRQ
lda #<IRQ
ldx #>IRQ
sei ; No ints, handler not yet in place
sta ENABLE_RAM
stx $FFFE ; Install interrupt handler
sty $FFFF
sta $FFFE ; Install interrupt handler
stx $FFFF
lda IRQVec
ldx IRQVec+1
sta IRQInd+1
stx IRQInd+2
lda #<IRQStub
ldx #>IRQStub
sta IRQVec
stx IRQVec+1
cli ; Allow interrupts
; Clear the BSS data.
@@ -95,6 +103,13 @@ _exit: pha ; Save the return code
lda #0
sta irqcount ; Disable custom IRQ handlers
sei
ldx IRQInd+1
ldy IRQInd+2
stx IRQVec
sty IRQVec+1
cli
; Copy back the zero-page stuff.
ldx #zpspace-1
@@ -122,9 +137,13 @@ L2: lda zpsave,x
; 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.
;
; When RAM is banked in, we skip the whole part of the ROM handler, and jump to
; the indirect vectors directly, after calling our own interrupt handlers.
;
; When ROM is banked in, a stub installed in the $314 indirect vector ensures
; that our interrupt handlers are still called (otherwise, interrupts that are
; not serviced by the ROM handler may cause a deadlock).
.segment "LOWCODE"
@@ -139,15 +158,6 @@ IRQ: cld ; Just to be sure
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.
@@ -161,7 +171,7 @@ IRQ: cld ; Just to be sure
pha ; Push faked X register
pha ; Push faked Y register
sta ENABLE_ROM ; Switch to ROM
jmp (IRQVec) ; Jump indirect to Kernal IRQ handler
jmp (IRQVec) ; Jump indirect to IRQ stub
irq_ret:
sta ENABLE_RAM ; Switch back to RAM
@@ -183,6 +193,22 @@ nohandler:
sta ENABLE_ROM
jmp (BRKVec) ; Jump indirect to the break vector
; IRQ stub installed at $314, called by our handler above if RAM is banked in,
; or the Kernal IRQ handler if ROM is banked in.
; 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.
IRQStub:
cld ; Just to be sure
sta ENABLE_RAM
ldy irqcount
beq @L1
jsr callirq_y ; Call the IRQ functions
@L1: sta ENABLE_ROM
jmp (IRQInd+1) ; Jump to the saved IRQ vector
; ------------------------------------------------------------------------
; Data
+2 -1
View File
@@ -2,8 +2,9 @@
; Oliver Schmidt, 2013-05-31
;
.export joy_libref, ser_libref
.export joy_libref, ser_libref, tgi_libref
.import _exit
joy_libref := _exit
ser_libref := _exit
tgi_libref := _exit
+21 -20
View File
@@ -64,15 +64,15 @@ ACIA_STATUS := ACIA+1 ; Status register
ACIA_CMD := ACIA+2 ; Command register
ACIA_CTRL := ACIA+3 ; Control register
RecvHead := $07D1 ; Head of receive buffer
RecvTail := $07D2 ; Tail of receive buffer
RecvFreeCnt := $07D3 ; Number of bytes in receive buffer
;----------------------------------------------------------------------------
;
; 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
@@ -88,7 +88,7 @@ SendBuf: .res 256
; Tables used to translate RS232 params into register values
BaudTable: ; bit7 = 1 means setting is invalid
BaudTable: ; Bit7 = 1 means setting is invalid
.byte $FF ; SER_BAUD_45_5
.byte $01 ; SER_BAUD_50
.byte $02 ; SER_BAUD_75
@@ -354,26 +354,27 @@ SER_IOCTL:
;
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
lda ACIA_STATUS ; (4) Check for byte received
and #$08 ; (2)
beq @L9 ; (2*)
lda ACIA_DATA ; (4) 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*)
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
@L2: lda RtsOff ; (3)
sta ACIA_CMD ; (4)
sta Stopped ; (3)
@L3: sec ; Interrupt handled
@L9: rts
;----------------------------------------------------------------------------
+860
View File
@@ -0,0 +1,860 @@
;
; Graphics driver for the 320x200x2 mode on Commodore Plus/4 systems.
;
; Luminance/Chrominance matrices at $800/$C00, overwriting text-mode character
; and color data. Bitmap is at $C000-$DF3F. Programs using this driver should
; either be linked with the option '-D __HIMEM__=0xC000'.
;
; Based on the c64-hi TGI driver, which in turn was based on Stephen L. Judd's
; GRLIB code.
;
; 2017-01-13, Greg King
; 2018-03-13, Sven Klose
; 2019-10-23, Richard Halkyard
;
.include "zeropage.inc"
.include "tgi-kernel.inc"
.include "tgi-error.inc"
.include "cbm_kernal.inc"
.include "plus4.inc"
.macpack generic
.macpack module
; ------------------------------------------------------------------------
; Header. Includes jump table and constants.
module_header _ted_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
; 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, $71 ; 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
; The TED uses the CPU's memory configuration to fetch color data! Although
; we run with ROMs banked out, putting color data in banked RAM (above $8000)
; will result in color artifacts appearing when we bank ROM back in for
; interrupts and Kernal calls. Bitmap data is not affected by this limitation,
; but since there is no way to access RAM under IO (FE00-FF40), we can't put the
; bitmap at $E000 like we do on the C64, and have to use the next lowest
; position at $C000.
LBASE := $0800 ; Luminance memory base address
VBASE := $C000 ; Bitmap base address
CBASE := LBASE + $400 ; Chrominance memory base address (fixed relative to LBASE)
CHRBASE := $0800 ; Base address of text mode data
.assert LBASE .mod $0800 = 0, error, "Luma/Chroma memory base address must be a multiple of 2K"
.assert VBASE .mod $2000 = 0, error, "Bitmap base address must be a multiple of 8K"
.assert LBASE + $800 < $8000, warning, "Luma/Chroma memory overlaps ROM. This will produce color artifacts."
.assert VBASE + $2000 < $FE00, error, "Bitmap overlaps IO space"
.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 $FF12 ; Set bitmap address and enable fetch from RAM
and #%00000011
ora #(>VBASE >> 2)
sta $FF12
.if LBASE <> CHRBASE
lda #>LBASE ; Set color memory address
sta $FF14
.endif
lda $FF06 ; Enable bitmap mode
ora #%00100000
sta $FF06
; 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 $FF12
ora #%00000100 ; Fetch from ROM
sta $FF12
.if LBASE <> CHRBASE
lda #>CHRBASE ; Reset character/color matrix address
sta $FF14
.else
sta ENABLE_ROM ; Clear text display since we clobbered it
jsr CLRSCR
sta ENABLE_RAM
.endif
lda $FF06
and #%11011111 ; Exit bitmap mode
sta $FF06
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
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
sta PALETTE,y
dey
bpl @L1
; Get luma values from the high nybble of the palette entries
lda PALETTE+1 ; Foreground luma
lsr a
lsr a
lsr a
lsr a
sta TEMP ; Foreground -> low nybble
lda PALETTE ; Background luma
and #$F0
ora TEMP ; Background -> high nybble
; Initialize the luma map with the new luma values
ldy #0
@L2: sta LBASE+$0000,y
sta LBASE+$0100,y
sta LBASE+$0200,y
sta LBASE+$02e8,y
iny
bne @L2
; Get chroma values from the low nybble of the palette entries
lda PALETTE+1 ; Foreground chroma
and #$0F
asl a
asl a
asl a
asl a
sta TEMP ; Foreground -> high nybble
lda PALETTE ; Background chroma
and #$0F
ora TEMP ; Background -> low nybble
; Initialize the chroma map with the new chroma values
ldy #0
@L3: sta CBASE+$0000,y
sta CBASE+$0100,y
sta CBASE+$0200,y
sta CBASE+$02e8,y
iny
bne @L3
; 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 (POINT),Y
eor BITMASK
and BITTAB,X
eor (POINT),Y
sta (POINT),Y
@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
lda (POINT),Y
ldy #$00
and BITTAB,X
beq @L1
iny
@L1:
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
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
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
jmp LINEPLOT ; Plot the last chunk
;
; 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:
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
+14
View File
@@ -0,0 +1,14 @@
;
; Address of the static standard tgi driver
;
; Oliver Schmidt, 2012-11-01
;
; const void tgi_static_stddrv[];
;
.export _tgi_static_stddrv
.import _ted_hi_tgi
.rodata
_tgi_static_stddrv := _ted_hi_tgi
+13
View File
@@ -0,0 +1,13 @@
;
; Name of the standard tgi driver
;
; Oliver Schmidt, 2011-05-02
;
; const char tgi_stddrv[];
;
.export _tgi_stddrv
.rodata
_tgi_stddrv: .asciiz "ted-hi.tgi"
+21 -2
View File
@@ -109,6 +109,7 @@ DISK_apple2 = samples.dsk
DISK_apple2enh = samples.dsk
DISK_atari = samples.atr
DISK_atarixl = samples.atr
DISK_plus4 = samples.d64
# --------------------------------------------------------------------------
# System-dependent settings
@@ -156,6 +157,8 @@ LDFLAGS_tgidemo_atarixl = --start-addr 0x4000
.o:
ifeq ($(SYS),vic20)
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C vic20-32k.cfg -m $@.map $^ $(SYS).lib
else ifeq ($(SYS),plus4)
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -C plus4-hires.cfg -m $@.map $^ $(SYS).lib
else
$(LD) $(LDFLAGS_$(@F)_$(SYS)) $(LDFLAGS) -o $@ -t $(SYS) -m $@.map $^ $(SYS).lib
endif
@@ -168,6 +171,11 @@ DIRLIST = tutorial geos atari2600 atari5200 apple2 gamate lynx supervision sym1
# --------------------------------------------------------------------------
# Lists of executables
EXELIST_agat = \
ascii \
checkversion \
hello \
sieve
EXELIST_apple2 = \
ascii \
@@ -331,9 +339,11 @@ EXELIST_plus4 = \
enumdevdir \
gunzip65 \
hello \
mandelbrot \
terminal \
tinyshell \
sieve
sieve \
tgidemo
EXELIST_sim6502 = \
checkversion \
@@ -400,6 +410,7 @@ all:
# --------------------------------------------------------------------------
# List of every supported platform
TARGETS := \
agat \
apple2 \
apple2enh \
atari \
@@ -455,7 +466,15 @@ multdemo: multidemo.o
ovrldemo: overlaydemo.o
$(LD) $(LDFLAGS) -o $@ -C $(SYS)-overlay.cfg -m $@.map $^ $(SYS).lib
OVERLAYLIST := $(foreach I,1 2 3,multdemo.$I ovrldemo.$I)
OVERLAYLIST :=
ifneq ($(filter ovrldemo,$(EXELIST_$(SYS))),)
OVERLAYLIST += $(foreach I,1 2 3,ovrldemo.$I)
endif
ifneq ($(filter multdemo,$(EXELIST_$(SYS))),)
OVERLAYLIST += $(foreach I,1 2 3,multdemo.$I)
endif
# --------------------------------------------------------------------------
# TGI programs on the VIC-20 need a special ld65 configuration file.
+1
View File
@@ -30,6 +30,7 @@
#define DYN_BOX_DRAW
#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
+1
View File
@@ -7,6 +7,7 @@
#define DYN_BOX_DRAW
#include <stdlib.h>
#include <string.h>
#include <conio.h>
+1 -1
View File
@@ -12,7 +12,7 @@
/* Workaround missing clock stuff */
#ifdef __APPLE2__
#if defined(__APPLE2__) || defined(__AGAT__)
# define clock() 0
# define CLOCKS_PER_SEC 1
#endif
+42 -15
View File
@@ -12,8 +12,10 @@
# define DYN_DRV 1
#endif
#define COLOR_BACK TGI_COLOR_BLACK
#define COLOR_FORE TGI_COLOR_WHITE
/* Color values passed to TGI functions are indices into the default palette. */
#define COLOR_BACK 0
#define COLOR_FORE 1
/*****************************************************************************/
@@ -65,17 +67,39 @@ static void DoWarning (void)
#endif
/*
* Note that everywhere else in the TGI API, colors are referred to via an index
* to the current palette.
*
* TGI_COLOR_ values can be used (ONLY!) for setting the palette, using them
* with other TGI functions only works by chance, on some targets.
*/
static void DoPalette (int n)
{
static const unsigned char Palette[4][2] = {
/* FIXME: add some ifdefs with proper values for targets that need it */
#if !defined(__APPLE2__)
{ TGI_COLOR_BLACK, TGI_COLOR_BLUE },
{ TGI_COLOR_WHITE, TGI_COLOR_BLACK },
{ TGI_COLOR_RED, TGI_COLOR_BLACK },
#else
{ TGI_COLOR_WHITE, TGI_COLOR_BLACK },
{ TGI_COLOR_BLACK, TGI_COLOR_WHITE },
{ TGI_COLOR_WHITE, TGI_COLOR_BLACK },
#endif
};
tgi_setpalette (Palette[n]);
}
static void DoCircles (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLUE };
unsigned char I;
unsigned char Color = COLOR_BACK;
const unsigned X = MaxX / 2;
const unsigned Y = MaxY / 2;
const unsigned Limit = (X < Y) ? Y : X;
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
tgi_clear ();
tgi_line (0, 0, MaxX, MaxY);
@@ -87,7 +111,9 @@ static void DoCircles (void)
tgi_ellipse (X, Y, I, tgi_imulround (I, AspectRatio));
}
}
while (kbhit ()) {
cgetc ();
}
cgetc ();
}
@@ -95,11 +121,9 @@ static void DoCircles (void)
static void DoCheckerboard (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK };
unsigned X, Y;
unsigned char Color = COLOR_BACK;
tgi_setpalette (Palette);
tgi_clear ();
while (1) {
@@ -123,13 +147,11 @@ static void DoCheckerboard (void)
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);
tgi_clear ();
@@ -160,6 +182,9 @@ static void DoDiagram (void)
tgi_lineto (XOrigin + X, YOrigin + Y);
}
while (kbhit ()) {
cgetc ();
}
cgetc ();
}
@@ -167,11 +192,9 @@ static void DoDiagram (void)
static void DoLines (void)
{
static const unsigned char Palette[2] = { TGI_COLOR_WHITE, TGI_COLOR_BLACK };
unsigned X;
const unsigned Min = (MaxX < MaxY) ? MaxX : MaxY;
tgi_setpalette (Palette);
tgi_setcolor (COLOR_FORE);
tgi_clear ();
@@ -182,6 +205,9 @@ static void DoLines (void)
tgi_line (Min, Min, Min-X, 0);
}
while (kbhit ()) {
cgetc ();
}
cgetc ();
}
@@ -216,10 +242,11 @@ int main (void)
Border = bordercolor (COLOR_BLACK);
/* Do graphics stuff */
DoCircles ();
DoCheckerboard ();
DoDiagram ();
DoLines ();
/* use default palette */ DoCircles ();
DoPalette (0); DoCheckerboard ();
DoPalette (1); DoDiagram ();
DoPalette (2); DoLines ();
#if DYN_DRV
/* Unload the driver */
+15
View File
@@ -178,4 +178,19 @@ $(eval $(call OBJS_template,common))
$(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog))))
.PHONY: dbginfo dbgsh test
test: dbginfo dbgsh
$(eval $(call OBJS_template,dbginfo))
dbginfo: $(dbginfo_OBJS)
../wrk/dbgsh$(EXE_SUFFIX): $(dbginfo_OBJS) ../wrk/common/common.a
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
dbgsh: ../wrk/dbgsh$(EXE_SUFFIX)
-include $(DEPS)
+11
View File
@@ -394,6 +394,16 @@ void DoConditionals (void)
CalcOverallIfCond ();
break;
case TOK_IFP02X:
D = AllocIf (".IFP02X", 1);
NextTok ();
if (IfCond) {
SetIfCond (D, GetCPU() == CPU_6502X);
}
ExpectSep ();
CalcOverallIfCond ();
break;
case TOK_IFP4510:
D = AllocIf (".IFP4510", 1);
NextTok ();
@@ -485,6 +495,7 @@ int CheckConditionals (void)
case TOK_IFNDEF:
case TOK_IFNREF:
case TOK_IFP02:
case TOK_IFP02X:
case TOK_IFP4510:
case TOK_IFP816:
case TOK_IFPC02:
+27
View File
@@ -169,8 +169,10 @@ static const struct {
unsigned Count;
InsDesc Ins[56];
} InsTab6502 = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTab6502.Ins) / sizeof (InsTab6502.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
{ "AND", 0x080A26C, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
@@ -227,6 +229,7 @@ static const struct {
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
/* END SORTED.SH */
}
};
@@ -235,8 +238,10 @@ static const struct {
unsigned Count;
InsDesc Ins[75];
} InsTab6502X = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTab6502X.Ins) / sizeof (InsTab6502X.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
{ "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */
{ "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */
@@ -312,6 +317,7 @@ static const struct {
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
/* END SORTED.SH */
}
};
@@ -324,8 +330,10 @@ static const struct {
unsigned Count;
InsDesc Ins[71];
} InsTab6502DTV = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTab6502DTV.Ins) / sizeof (InsTab6502DTV.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x080A26C, 0x60, 0, PutAll },
{ "ALR", 0x0800000, 0x4B, 0, PutAll }, /* X */
{ "ANC", 0x0800000, 0x0B, 0, PutAll }, /* X */
@@ -397,6 +405,7 @@ static const struct {
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
/* END SORTED.SH */
}
};
@@ -405,8 +414,10 @@ static const struct {
unsigned Count;
InsDesc Ins[66];
} InsTab65SC02 = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTab65SC02.Ins) / sizeof (InsTab65SC02.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
{ "AND", 0x080A66C, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
@@ -473,6 +484,7 @@ static const struct {
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
/* END SORTED.SH */
}
};
@@ -481,8 +493,10 @@ static const struct {
unsigned Count;
InsDesc Ins[100];
} InsTab65C02 = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTab65C02.Ins) / sizeof (InsTab65C02.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
{ "AND", 0x080A66C, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
@@ -583,6 +597,7 @@ static const struct {
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll },
{ "WAI", 0x0000001, 0xcb, 0, PutAll }
/* END SORTED.SH */
}
};
@@ -591,8 +606,10 @@ static const struct {
unsigned Count;
InsDesc Ins[133];
} InsTab4510 = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTab4510.Ins) / sizeof (InsTab4510.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
{ "AND", 0x080A66C, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
@@ -726,6 +743,7 @@ static const struct {
{ "TYA", 0x0000001, 0x98, 0, PutAll },
{ "TYS", 0x0000001, 0x2b, 0, PutAll },
{ "TZA", 0x0000001, 0x6b, 0, PutAll },
/* END SORTED.SH */
}
};
@@ -734,8 +752,10 @@ static const struct {
unsigned Count;
InsDesc Ins[100];
} InsTab65816 = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTab65816.Ins) / sizeof (InsTab65816.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x0b8f6fc, 0x60, 0, PutAll },
{ "AND", 0x0b8f6fc, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
@@ -836,6 +856,7 @@ static const struct {
{ "WDM", 0x0800004, 0x42, 6, PutAll },
{ "XBA", 0x0000001, 0xeb, 0, PutAll },
{ "XCE", 0x0000001, 0xfb, 0, PutAll }
/* END SORTED.SH */
}
};
@@ -844,8 +865,10 @@ static const struct {
unsigned Count;
InsDesc Ins[26];
} InsTabSweet16 = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTabSweet16.Ins) / sizeof (InsTabSweet16.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADD", AMSW16_REG, 0xA0, 0, PutSweet16 },
{ "BC", AMSW16_BRA, 0x03, 0, PutSweet16Branch },
{ "BK", AMSW16_IMP, 0x0A, 0, PutSweet16 },
@@ -872,6 +895,7 @@ static const struct {
{ "STD", AMSW16_IND, 0x70, 0, PutSweet16 },
{ "STP", AMSW16_IND, 0x90, 0, PutSweet16 },
{ "SUB", AMSW16_REG, 0xB0, 0, PutSweet16 },
/* END SORTED.SH */
}
};
@@ -880,8 +904,10 @@ static const struct {
unsigned Count;
InsDesc Ins[135];
} InsTabHuC6280 = {
/* CAUTION: table must be sorted for bsearch */
sizeof (InsTabHuC6280.Ins) / sizeof (InsTabHuC6280.Ins[0]),
{
/* BEGIN SORTED.SH */
{ "ADC", 0x080A66C, 0x60, 0, PutAll },
{ "AND", 0x080A66C, 0x20, 0, PutAll },
{ "ASL", 0x000006e, 0x02, 1, PutAll },
@@ -1017,6 +1043,7 @@ static const struct {
{ "TXA", 0x0000001, 0x8a, 0, PutAll },
{ "TXS", 0x0000001, 0x9a, 0, PutAll },
{ "TYA", 0x0000001, 0x98, 0, PutAll }
/* END SORTED.SH */
}
};
+4
View File
@@ -350,6 +350,10 @@ static void SetSys (const char* Sys)
NewSymbol ("__RP6502__", 1);
break;
case TGT_AGAT:
NewSymbol ("__AGAT__", 1);
break;
default:
AbEnd ("Invalid target name: '%s'", Sys);
+101 -89
View File
@@ -1562,6 +1562,14 @@ static void DoP02 (void)
static void DoP02X (void)
/* Switch to 6502 CPU */
{
SetCPU (CPU_6502X);
}
static void DoPC02 (void)
/* Switch to 65C02 CPU */
{
@@ -2057,70 +2065,72 @@ struct CtrlDesc {
void (*Handler) (void); /* Command handler */
};
/* NOTE: .AND, .BITAND, .BITNOT, .BITOR, .BITXOR, .MOD, .NOT, .OR, .SHL, .SHR
and .XOR do NOT go into this table */
#define PSEUDO_COUNT (sizeof (CtrlCmdTab) / sizeof (CtrlCmdTab [0]))
static CtrlDesc CtrlCmdTab [] = {
{ ccNone, DoA16 },
{ ccNone, DoA8 },
{ ccNone, DoA16 }, /* .A16 */
{ ccNone, DoA8 }, /* .A8 */
{ ccNone, DoAddr }, /* .ADDR */
{ ccNone, DoUnexpected }, /* .ADDRSIZE */
{ ccNone, DoAlign },
{ ccNone, DoASCIIZ },
{ ccNone, DoAlign }, /* .ALIGN */
{ ccNone, DoASCIIZ }, /* .ASCIIZ */
{ ccNone, DoUnexpected }, /* .ASIZE */
{ ccNone, DoAssert },
{ ccNone, DoAutoImport },
{ ccNone, DoAssert }, /* .ASSERT */
{ ccNone, DoAutoImport }, /* .AUTOIMPORT */
{ ccNone, DoUnexpected }, /* .BANK */
{ ccNone, DoUnexpected }, /* .BANKBYTE */
{ ccNone, DoBankBytes },
{ ccNone, DoBankBytes }, /* .BANKBYTES */
{ ccNone, DoUnexpected }, /* .BLANK */
{ ccNone, DoBss },
{ ccNone, DoByte },
{ ccNone, DoCase },
{ ccNone, DoCharMap },
{ ccNone, DoCode },
{ ccNone, DoBss }, /* .BSS */
{ ccNone, DoByte }, /* .BYT, .BYTE */
{ ccNone, DoCase }, /* .CASE */
{ ccNone, DoCharMap }, /* .CHARMAP */
{ ccNone, DoCode }, /* .CODE */
{ ccNone, DoUnexpected, }, /* .CONCAT */
{ ccNone, DoConDes },
{ ccNone, DoConDes }, /* .CONDES */
{ ccNone, DoUnexpected }, /* .CONST */
{ ccNone, DoConstructor },
{ ccNone, DoConstructor }, /* .CONSTRUCTOR */
{ ccNone, DoUnexpected }, /* .CPU */
{ ccNone, DoData },
{ ccNone, DoDbg, },
{ ccNone, DoDByt },
{ ccNone, DoDebugInfo },
{ ccKeepToken, DoDefine },
{ ccNone, DoData }, /* .DATA */
{ ccNone, DoDbg, }, /* .DBG */
{ ccNone, DoDByt }, /* .DBYT */
{ ccNone, DoDebugInfo }, /* .DEBUGINFO */
{ ccKeepToken, DoDefine }, /* .DEF, .DEFINE */
{ ccNone, DoUnexpected }, /* .DEFINED */
{ ccNone, DoUnexpected }, /* .DEFINEDMACRO */
{ ccNone, DoDelMac },
{ ccNone, DoDestructor },
{ ccNone, DoDWord },
{ ccNone, DoDelMac }, /* .DELMAC, .DELMACRO */
{ ccNone, DoDestructor }, /* .DESTRUCTOR */
{ ccNone, DoDWord }, /* .DWORD */
{ ccKeepToken, DoConditionals }, /* .ELSE */
{ ccKeepToken, DoConditionals }, /* .ELSEIF */
{ ccKeepToken, DoEnd },
{ ccKeepToken, DoEnd }, /* .END */
{ ccNone, DoUnexpected }, /* .ENDENUM */
{ ccKeepToken, DoConditionals }, /* .ENDIF */
{ ccNone, DoUnexpected }, /* .ENDMACRO */
{ ccNone, DoEndProc },
{ ccNone, DoUnexpected }, /* .ENDREPEAT */
{ ccNone, DoEndScope },
{ ccNone, DoUnexpected }, /* .ENDMAC, .ENDMACRO */
{ ccNone, DoEndProc }, /* .ENDPROC */
{ ccNone, DoUnexpected }, /* .ENDREP, .ENDREPEAT */
{ ccNone, DoEndScope }, /* .ENDSCOPE */
{ 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, DoEnum }, /* .ENUM */
{ ccNone, DoError }, /* .ERROR */
{ ccNone, DoExitMacro }, /* .EXITMAC, .EXITMACRO */
{ ccNone, DoExport }, /* .EXPORT */
{ ccNone, DoExportZP }, /* .EXPORTZP */
{ ccNone, DoFarAddr }, /* .FARADDR */
{ ccNone, DoFatal }, /* .FATAL */
{ ccNone, DoFeature }, /* .FEATURE */
{ ccNone, DoFileOpt }, /* .FOPT, .FILEOPT */
{ ccNone, DoForceImport }, /* .FORCEIMPORT */
{ ccNone, DoUnexpected }, /* .FORCEWORD */
{ ccNone, DoGlobal },
{ ccNone, DoGlobalZP },
{ ccNone, DoGlobal }, /* .GLOBAL */
{ ccNone, DoGlobalZP }, /* .GLOBALZP */
{ ccNone, DoUnexpected }, /* .HIBYTE */
{ ccNone, DoHiBytes },
{ ccNone, DoHiBytes }, /* .HIBYTES */
{ ccNone, DoUnexpected }, /* .HIWORD */
{ ccNone, DoI16 },
{ ccNone, DoI8 },
{ ccNone, DoI16 }, /* .I16 */
{ ccNone, DoI8 }, /* .I8 */
{ ccNone, DoUnexpected }, /* .IDENT */
{ ccKeepToken, DoConditionals }, /* .IF */
{ ccKeepToken, DoConditionals }, /* .IFBLANK */
@@ -2131,81 +2141,83 @@ static CtrlDesc CtrlCmdTab [] = {
{ ccKeepToken, DoConditionals }, /* .IFNDEF */
{ ccKeepToken, DoConditionals }, /* .IFNREF */
{ ccKeepToken, DoConditionals }, /* .IFP02 */
{ ccKeepToken, DoConditionals }, /* .IFP02X */
{ ccKeepToken, DoConditionals }, /* .IFP4510 */
{ ccKeepToken, DoConditionals }, /* .IFP816 */
{ ccKeepToken, DoConditionals }, /* .IFPC02 */
{ ccKeepToken, DoConditionals }, /* .IFPDTV */
{ ccKeepToken, DoConditionals }, /* .IFPSC02 */
{ ccKeepToken, DoConditionals }, /* .IFREF */
{ ccNone, DoImport },
{ ccNone, DoImportZP },
{ ccNone, DoIncBin },
{ ccNone, DoInclude },
{ ccNone, DoInterruptor },
{ ccNone, DoImport }, /* .IMPORT */
{ ccNone, DoImportZP }, /* .IMPORTZP */
{ ccNone, DoIncBin }, /* .INCBIN */
{ ccNone, DoInclude }, /* .INCLUDE */
{ ccNone, DoInterruptor }, /* .INTERRUPTPOR */
{ ccNone, DoUnexpected }, /* .ISIZE */
{ ccNone, DoUnexpected }, /* .ISMNEMONIC */
{ ccNone, DoInvalid }, /* .LEFT */
{ ccNone, DoLineCont },
{ ccNone, DoList },
{ ccNone, DoListBytes },
{ ccNone, DoLiteral },
{ ccNone, DoLineCont }, /* .LINECONT */
{ ccNone, DoList }, /* .LIST */
{ ccNone, DoListBytes }, /* .LISTBYTES */
{ ccNone, DoLiteral }, /* .LITERAL */
{ ccNone, DoUnexpected }, /* .LOBYTE */
{ ccNone, DoLoBytes },
{ ccNone, DoLoBytes }, /* .LOBYTES */
{ ccNone, DoUnexpected }, /* .LOCAL */
{ ccNone, DoLocalChar },
{ ccNone, DoLocalChar }, /* .LOCALCHAR */
{ ccNone, DoUnexpected }, /* .LOWORD */
{ ccNone, DoMacPack },
{ ccNone, DoMacro },
{ ccNone, DoMacPack }, /* .MACPACK */
{ ccNone, DoMacro }, /* .MAC, .MACRO */
{ 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, DoNull }, /* .NULL */
{ ccNone, DoOrg }, /* .ORG */
{ ccNone, DoOut }, /* .OUT */
{ ccNone, DoP02 }, /* .P02 */
{ ccNone, DoP02X }, /* .P02X */
{ ccNone, DoP4510 }, /* .P4510 */
{ ccNone, DoP816 }, /* .P816 */
{ ccNone, DoPageLength }, /* .PAGELEN, .PAGELENGTH */
{ ccNone, DoUnexpected }, /* .PARAMCOUNT */
{ ccNone, DoPC02 },
{ ccNone, DoPDTV },
{ ccNone, DoPopCharmap },
{ ccNone, DoPopCPU },
{ ccNone, DoPopSeg },
{ ccNone, DoProc },
{ ccNone, DoPSC02 },
{ ccNone, DoPushCharmap },
{ ccNone, DoPushCPU },
{ ccNone, DoPushSeg },
{ ccNone, DoUnexpected }, /* .REFERENCED */
{ ccNone, DoReferTo }, /* .REFERTO */
{ ccNone, DoReloc },
{ ccNone, DoRepeat },
{ ccNone, DoRes },
{ ccNone, DoPC02 }, /* .PSC02 */
{ ccNone, DoPDTV }, /* .PDTV */
{ ccNone, DoPopCharmap }, /* .POPCHARMAP */
{ ccNone, DoPopCPU }, /* .POPCPU */
{ ccNone, DoPopSeg }, /* .POPSEG */
{ ccNone, DoProc }, /* .PROC */
{ ccNone, DoPSC02 }, /* .PSC02 */
{ ccNone, DoPushCharmap }, /* .PUSHCHARMAP */
{ ccNone, DoPushCPU }, /* .PUSHCPU */
{ ccNone, DoPushSeg }, /* .PUSHSEG */
{ ccNone, DoUnexpected }, /* .REF, .REFERENCED */
{ ccNone, DoReferTo }, /* .REFTO, .REFERTO */
{ ccNone, DoReloc }, /* .RELOC */
{ ccNone, DoRepeat }, /* .REPEAT */
{ ccNone, DoRes }, /* .RES */
{ ccNone, DoInvalid }, /* .RIGHT */
{ ccNone, DoROData },
{ ccNone, DoScope },
{ ccNone, DoSegment },
{ ccNone, DoROData }, /* .RODATA */
{ ccNone, DoScope }, /* .SCOPE */
{ ccNone, DoSegment }, /* .SEGMENT */
{ ccNone, DoUnexpected }, /* .SET */
{ ccNone, DoSetCPU },
{ ccNone, DoSetCPU }, /* .SETCPU */
{ ccNone, DoUnexpected }, /* .SIZEOF */
{ ccNone, DoSmart },
{ ccNone, DoSmart }, /* .SMART */
{ ccNone, DoUnexpected }, /* .SPRINTF */
{ ccNone, DoUnexpected }, /* .STRAT */
{ ccNone, DoUnexpected }, /* .STRING */
{ ccNone, DoUnexpected }, /* .STRLEN */
{ ccNone, DoStruct },
{ ccNone, DoTag },
{ ccNone, DoStruct }, /* .STRUCT */
{ ccNone, DoTag }, /* .TAG */
{ ccNone, DoUnexpected }, /* .TCOUNT */
{ ccNone, DoUnexpected }, /* .TIME */
{ ccKeepToken, DoUnDef },
{ ccNone, DoUnion },
{ ccKeepToken, DoUnDef }, /* .UNDEF, .UNDEFINE */
{ ccNone, DoUnion }, /* .UNION */
{ ccNone, DoUnexpected }, /* .VERSION */
{ ccNone, DoWarning },
{ ccNone, DoWord },
{ ccNone, DoWarning }, /* .WARNING */
{ ccNone, DoWord }, /* .WORD */
{ ccNone, DoUnexpected }, /* .XMATCH */
{ ccNone, DoZeropage },
{ ccNone, DoZeropage }, /* .ZEROPAGE */
};
+5
View File
@@ -131,10 +131,12 @@ static int C = 0; /* Current input character */
int ForcedEnd = 0;
/* List of dot keywords with the corresponding tokens */
/* CAUTION: table must be sorted for bsearch */
struct DotKeyword {
const char* Key; /* MUST be first field */
token_t Tok;
} DotKeywords [] = {
/* BEGIN SORTED.SH */
{ ".A16", TOK_A16 },
{ ".A8", TOK_A8 },
{ ".ADDR", TOK_ADDR },
@@ -219,6 +221,7 @@ struct DotKeyword {
{ ".IFNDEF", TOK_IFNDEF },
{ ".IFNREF", TOK_IFNREF },
{ ".IFP02", TOK_IFP02 },
{ ".IFP02X", TOK_IFP02X },
{ ".IFP4510", TOK_IFP4510 },
{ ".IFP816", TOK_IFP816 },
{ ".IFPC02", TOK_IFPC02 },
@@ -257,6 +260,7 @@ struct DotKeyword {
{ ".ORG", TOK_ORG },
{ ".OUT", TOK_OUT },
{ ".P02", TOK_P02 },
{ ".P02X", TOK_P02X },
{ ".P4510", TOK_P4510 },
{ ".P816", TOK_P816 },
{ ".PAGELEN", TOK_PAGELENGTH },
@@ -306,6 +310,7 @@ struct DotKeyword {
{ ".XMATCH", TOK_XMATCH },
{ ".XOR", TOK_BOOLXOR },
{ ".ZEROPAGE", TOK_ZEROPAGE },
/* END SORTED.SH */
};
+2
View File
@@ -193,6 +193,7 @@ typedef enum token_t {
TOK_IFNDEF,
TOK_IFNREF,
TOK_IFP02,
TOK_IFP02X,
TOK_IFP4510,
TOK_IFP816,
TOK_IFPC02,
@@ -226,6 +227,7 @@ typedef enum token_t {
TOK_ORG,
TOK_OUT,
TOK_P02,
TOK_P02X,
TOK_P4510,
TOK_P816,
TOK_PAGELENGTH,
+10 -4
View File
@@ -90,7 +90,9 @@ struct FuncInfo {
** routines are marked to use only the A register. The remainder is ignored
** anyway.
*/
/* CAUTION: table must be sorted for bsearch */
static const FuncInfo FuncInfoTable[] = {
/* BEGIN SORTED.SH */
{ "addeq0sp", SLV_TOP | REG_AX, PSTATE_ALL | REG_AXY },
{ "addeqysp", SLV_IND | REG_AXY, PSTATE_ALL | REG_AXY },
{ "addysp", REG_SP | REG_Y, PSTATE_ALL | REG_SP },
@@ -190,12 +192,12 @@ static const FuncInfo FuncInfoTable[] = {
{ "ldeaxysp", SLV_IND | REG_Y, PSTATE_ALL | REG_EAXY },
{ "leaa0sp", REG_SP | REG_A, PSTATE_ALL | REG_AX },
{ "leaaxsp", REG_SP | REG_AX, PSTATE_ALL | REG_AX },
{ "leave00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
{ "leave0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
{ "leave", REG_SP, PSTATE_ALL | REG_SP | REG_Y },
{ "leavey00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
{ "leavey0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
{ "leave0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
{ "leave00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
{ "leavey", REG_SP | REG_Y, PSTATE_ALL | REG_SP | REG_Y },
{ "leavey0", REG_SP, PSTATE_ALL | REG_SP | REG_XY },
{ "leavey00", REG_SP, PSTATE_ALL | REG_SP | REG_AXY },
{ "lsubeq", REG_EAXY | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
{ "lsubeq0sp", SLV_TOP | REG_EAX, PSTATE_ALL | REG_EAXY },
{ "lsubeq1", REG_Y | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
@@ -376,11 +378,14 @@ static const FuncInfo FuncInfoTable[] = {
{ "tosxoreax", SLV_TOP | REG_EAX, PSTATE_ALL | REG_SP | REG_EAXY | REG_TMP1 },
{ "tsteax", REG_EAX, PSTATE_ALL | REG_Y },
{ "utsteax", REG_EAX, PSTATE_ALL | REG_Y },
/* END SORTED.SH */
};
#define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
/* Table with names of zero page locations used by the compiler */
/* CAUTION: table must be sorted for bsearch */
static const ZPInfo ZPInfoTable[] = {
/* BEGIN SORTED.SH */
{ 0, "ptr1", 2, REG_PTR1_LO, REG_PTR1 },
{ 0, "ptr1+1", 1, REG_PTR1_HI, REG_PTR1 },
{ 0, "ptr2", 2, REG_PTR2_LO, REG_PTR2 },
@@ -398,6 +403,7 @@ static const ZPInfo ZPInfoTable[] = {
{ 0, "tmp2", 1, REG_NONE, REG_NONE },
{ 0, "tmp3", 1, REG_NONE, REG_NONE },
{ 0, "tmp4", 1, REG_NONE, REG_NONE },
/* END SORTED.SH */
};
#define ZPInfoCount (sizeof(ZPInfoTable) / sizeof(ZPInfoTable[0]))
+14 -8
View File
@@ -102,6 +102,8 @@ struct OptFunc {
/* A list of all the function descriptions */
/* CAUTION: should be sorted by "name" */
/* BEGIN DECL SORTED_CODEOPT.SH */
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 };
@@ -152,18 +154,13 @@ static OptFunc DOptJumpTarget3 = { OptJumpTarget3, "OptJumpTarget3", 100, 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 DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 0, 0, 0, 0, 0, 0 };
static OptFunc DOptLongAssign = { OptLongAssign, "OptLongAssign", 100, 0, 0, 0, 0, 0 };
static OptFunc DOptLongCopy = { OptLongCopy, "OptLongCopy", 100, 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 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 };
@@ -173,6 +170,12 @@ static OptFunc DOptPtrLoad16 = { OptPtrLoad16, "OptPtrLoad16", 100, 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 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 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 };
@@ -202,7 +205,6 @@ static OptFunc DOptStore3 = { OptStore3, "OptStore3", 120, 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 DOptLoadStoreLoad= { OptLoadStoreLoad,"OptLoadStoreLoad", 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 };
@@ -214,10 +216,13 @@ static OptFunc DOptTransfers3 = { OptTransfers3, "OptTransfers3", 65, 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 };
/* END DECL SORTED_CODEOPT.SH */
/* Table containing all the steps in alphabetical order */
/* CAUTION: table must be sorted for bsearch */
static OptFunc* OptFuncs[] = {
/* BEGIN SORTED_CODEOPT.SH */
&DOpt65C02BitOps,
&DOpt65C02Ind,
&DOpt65C02Stores,
@@ -268,6 +273,7 @@ static OptFunc* OptFuncs[] = {
&DOptLoad1,
&DOptLoad2,
&DOptLoad3,
&DOptLoadStoreLoad,
&DOptLongAssign,
&DOptLongCopy,
&DOptNegAX1,
@@ -318,7 +324,6 @@ static OptFunc* OptFuncs[] = {
&DOptStore4,
&DOptStore5,
&DOptStoreLoad,
&DOptLoadStoreLoad,
&DOptSub1,
&DOptSub2,
&DOptSub3,
@@ -330,6 +335,7 @@ static OptFunc* OptFuncs[] = {
&DOptTransfers4,
&DOptUnusedLoads,
&DOptUnusedStores,
/* END SORTED_CODEOPT.SH */
};
#define OPTFUNC_COUNT (sizeof(OptFuncs) / sizeof(OptFuncs[0]))
+6 -4
View File
@@ -1225,6 +1225,12 @@ static int CmpHarmless (const void* Key, const void* Entry)
}
/* CAUTION: table must be sorted for bsearch */
static const char* const Tab[] = {
/* BEGIN SORTED.SH */
"_abs",
/* END SORTED.SH */
};
int HarmlessCall (const CodeEntry* E, int PushedBytes)
/* Check if this is a call to a harmless subroutine that will not interrupt
@@ -1252,10 +1258,6 @@ int HarmlessCall (const CodeEntry* E, int PushedBytes)
}
return 1;
} else {
static const char* const Tab[] = {
"_abs",
};
void* R = bsearch (E->Arg,
Tab,
sizeof (Tab) / sizeof (Tab[0]),
+8
View File
@@ -496,6 +496,14 @@ void Compile (const char* FileName)
while (PreprocessNextLine ())
{ /* Nothing */ }
/* Output macros if requested by the user */
if (DumpPredefMacros) {
OutputPredefMacros ();
}
if (DumpUserMacros) {
OutputUserMacros ();
}
/* Close the output file */
CloseOutputFile ();
+6
View File
@@ -1464,7 +1464,9 @@ static unsigned Opt_a_tosxor (StackOpData* D)
/* The first column of these two tables must be sorted in lexical order */
/* CAUTION: table must be sorted for bsearch */
static const OptFuncDesc FuncTable[] = {
/* BEGIN SORTED.SH */
{ "___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 },
@@ -1485,9 +1487,12 @@ static const OptFuncDesc FuncTable[] = {
{ "tosuleax", Opt_tosuleax, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
{ "tosultax", Opt_tosultax, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
{ "tosxorax", Opt_tosxorax, REG_NONE, OP_NONE },
/* END SORTED.SH */
};
/* CAUTION: table must be sorted for bsearch */
static const OptFuncDesc FuncRegATable[] = {
/* BEGIN SORTED.SH */
{ "tosandax", Opt_a_tosand, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
{ "toseqax", Opt_a_toseq, REG_NONE, OP_NONE },
{ "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE },
@@ -1503,6 +1508,7 @@ static const OptFuncDesc FuncRegATable[] = {
{ "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE },
{ "tosultax", Opt_a_tosult, REG_NONE, OP_NONE },
{ "tosxorax", Opt_a_tosxor, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT },
/* END SORTED.SH */
};
#define FUNC_COUNT(Table) (sizeof(Table) / sizeof(Table[0]))
+65 -11
View File
@@ -39,6 +39,7 @@
/* common */
#include "coll.h"
#include "debugflag.h"
#include "print.h"
#include "strbuf.h"
@@ -183,11 +184,15 @@ static unsigned GetDiagnosticLineNum (void)
void Fatal (const char* Format, ...)
void Fatal_ (const char *file, int line, const char* Format, ...)
/* Print a message about a fatal error and die */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
fprintf (stderr, "%s:%u: Fatal: ", GetDiagnosticFileName (), GetDiagnosticLineNum ());
va_start (ap, Format);
@@ -203,11 +208,15 @@ void Fatal (const char* Format, ...)
void Internal (const char* Format, ...)
void Internal_ (const char *file, int line, const char* Format, ...)
/* Print a message about an internal compiler error and die */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
fprintf (stderr, "%s:%u: Internal compiler error:\n",
GetDiagnosticFileName (), GetDiagnosticLineNum ());
@@ -270,10 +279,15 @@ static void IntError (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap)
void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...)
void LIError_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...)
/* Print an error message with the line info given explicitly */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntError (EC, LI, Format, ap);
va_end (ap);
@@ -281,10 +295,15 @@ void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...)
void Error (const char* Format, ...)
void Error_ (const char *file, int line, const char* Format, ...)
/* Print an error message */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntError (EC_PARSER, GetDiagnosticLI (), Format, ap);
va_end (ap);
@@ -292,10 +311,15 @@ void Error (const char* Format, ...)
void PPError (const char* Format, ...)
void PPError_ (const char *file, int line, const char* Format, ...)
/* Print an error message. For use within the preprocessor */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntError (EC_PP, GetCurLineInfo (), Format, ap);
va_end (ap);
@@ -346,10 +370,15 @@ static void IntWarning (errcat_t EC, LineInfo* LI, const char* Msg, va_list ap)
void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...)
void LIWarning_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...)
/* Print a warning message with the line info given explicitly */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntWarning (EC, LI, Format, ap);
va_end (ap);
@@ -357,10 +386,15 @@ void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...)
void Warning (const char* Format, ...)
void Warning_ (const char *file, int line, const char* Format, ...)
/* Print a warning message */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntWarning (EC_PARSER, GetDiagnosticLI (), Format, ap);
va_end (ap);
@@ -368,10 +402,15 @@ void Warning (const char* Format, ...)
void PPWarning (const char* Format, ...)
void PPWarning_ (const char *file, int line, const char* Format, ...)
/* Print a warning message. For use within the preprocessor */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntWarning (EC_PP, GetCurLineInfo (), Format, ap);
va_end (ap);
@@ -436,10 +475,15 @@ static void IntNote (const LineInfo* LI, const char* Msg, va_list ap)
void LINote (const LineInfo* LI, const char* Format, ...)
void LINote_ (const char *file, int line, const LineInfo* LI, const char* Format, ...)
/* Print a note message with the line info given explicitly */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntNote (LI, Format, ap);
va_end (ap);
@@ -447,10 +491,15 @@ void LINote (const LineInfo* LI, const char* Format, ...)
void Note (const char* Format, ...)
void Note_ (const char *file, int line, const char* Format, ...)
/* Print a note message */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntNote (GetDiagnosticLI (), Format, ap);
va_end (ap);
@@ -458,10 +507,15 @@ void Note (const char* Format, ...)
void PPNote (const char* Format, ...)
void PPNote_ (const char *file, int line, const char* Format, ...)
/* Print a note message. For use within the preprocessor */
{
va_list ap;
if (Debug) {
fprintf(stderr, "[%s:%d] ", file, line);
}
va_start (ap, Format);
IntNote (GetDiagnosticLI (), Format, ap);
va_end (ap);
+22 -11
View File
@@ -103,28 +103,36 @@ struct StrBuf;
void PrintFileInclusionInfo (const LineInfo* LI);
/* Print hierarchy of file inclusion */
void Fatal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
void Fatal_ (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4)));
#define Fatal(...) Fatal_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a message about a fatal error and die */
void Internal (const char* Format, ...) attribute ((noreturn, format (printf, 1, 2)));
void Internal_ (const char *file, int line, const char* Format, ...) attribute ((noreturn, format (printf, 3, 4)));
#define Internal(...) Internal_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a message about an internal compiler error and die */
void Error (const char* Format, ...) attribute ((format (printf, 1, 2)));
void Error_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4)));
#define Error(...) Error_(__FILE__, __LINE__, __VA_ARGS__)
/* Print an error message */
void LIError (errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4)));
void LIError_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6)));
#define LIError(...) LIError_(__FILE__, __LINE__, __VA_ARGS__)
/* Print an error message with the line info given explicitly */
void PPError (const char* Format, ...) attribute ((format (printf, 1, 2)));
void PPError_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4)));
#define PPError(...) PPError_(__FILE__, __LINE__, __VA_ARGS__)
/* Print an error message. For use within the preprocessor */
void Warning (const char* Format, ...) attribute ((format (printf, 1, 2)));
void Warning_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4)));
#define Warning(...) Warning_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a warning message */
void LIWarning (errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 3, 4)));
void LIWarning_ (const char *file, int line, errcat_t EC, LineInfo* LI, const char* Format, ...) attribute ((format (printf, 5, 6)));
#define LIWarning(...) LIWarning_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a warning message with the line info given explicitly */
void PPWarning (const char* Format, ...) attribute ((format (printf, 1, 2)));
void PPWarning_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4)));
#define PPWarning(...) PPWarning_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a warning message. For use within the preprocessor */
void UnreachableCodeWarning (void);
@@ -140,13 +148,16 @@ IntStack* FindWarning (const char* Name);
void ListWarnings (FILE* F);
/* Print a list of warning types/names to the given file */
void Note (const char* Format, ...) attribute ((format (printf, 1, 2)));
void Note_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4)));
#define Note(...) Note_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a note message */
void LINote (const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 2, 3)));
void LINote_ (const char *file, int line, const LineInfo* LI, const char* Format, ...) attribute ((format (printf, 4, 5)));
#define LINote(...) LINote_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a note message with the line info given explicitly */
void PPNote (const char* Format, ...) attribute ((format (printf, 1, 2)));
void PPNote_ (const char *file, int line, const char* Format, ...) attribute ((format (printf, 3, 4)));
#define PPNote(...) PPNote_(__FILE__, __LINE__, __VA_ARGS__)
/* Print a note message. For use within the preprocessor */
unsigned GetTotalErrors (void);
+3 -1
View File
@@ -44,12 +44,14 @@
unsigned char AddSource = 0; /* Add source lines as comments */
unsigned char AllowNewComments = 0; /* Allow new style comments in C89 mode */
unsigned char AutoCDecl = 0; /* Make functions default to __cdecl__ */
unsigned char DebugInfo = 0; /* Add debug info to the obj */
unsigned char DumpPredefMacros = 0; /* Output predefined macros */
unsigned char DumpUserMacros = 0; /* Output user macros */
unsigned char PreprocessOnly = 0; /* Just preprocess the input */
unsigned char DebugOptOutput = 0; /* Output debug stuff */
unsigned RegisterSpace = 6; /* Space available for register vars */
unsigned AllowNewComments = 0; /* Allow new style comments in C89 mode */
/* Stackable options */
IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */
+3 -1
View File
@@ -52,12 +52,14 @@
/* Options */
extern unsigned char AddSource; /* Add source lines as comments */
extern unsigned char AllowNewComments; /* Allow new style comments in C89 mode */
extern unsigned char AutoCDecl; /* Make functions default to __cdecl__ */
extern unsigned char DebugInfo; /* Add debug info to the obj */
extern unsigned char DumpPredefMacros; /* Output predefined macros */
extern unsigned char DumpUserMacros; /* Output user macros */
extern unsigned char PreprocessOnly; /* Just preprocess the input */
extern unsigned char DebugOptOutput; /* Output debug stuff */
extern unsigned RegisterSpace; /* Space available for register vars */
extern unsigned AllowNewComments; /* Allow new style comments in C89 mode */
/* Stackable options */
extern IntStack WritableStrings; /* Literal strings are r/w */
+88 -6
View File
@@ -1,4 +1,4 @@
/*****************************************************************************/
/* */
/* macrotab.h */
/* */
@@ -42,6 +42,7 @@
/* cc65 */
#include "error.h"
#include "output.h"
#include "preproc.h"
#include "macrotab.h"
@@ -60,6 +61,70 @@ static Macro* MacroTab[MACRO_TAB_SIZE];
/* The undefined macros list head */
static Macro* UndefinedMacrosListHead;
/* Some defines for better readability when calling OutputMacros() */
#define USER_MACROS 0
#define PREDEF_MACROS 1
#define NAME_ONLY 0
#define FULL_DEFINITION 1
/*****************************************************************************/
/* helpers */
/*****************************************************************************/
static void OutputMacro (const Macro* M, int Full)
/* Output one macro. If Full is true, the replacement is also output. */
{
WriteOutput ("#define %s", M->Name);
int ParamCount = M->ParamCount;
if (M->ParamCount >= 0) {
int I;
if (M->Variadic) {
CHECK (ParamCount > 0);
--ParamCount;
}
WriteOutput ("(");
for (I = 0; I < ParamCount; ++I) {
const char* Name = CollConstAt (&M->Params, I);
WriteOutput ("%s%s", (I == 0)? "" : ",", Name);
}
if (M->Variadic) {
WriteOutput ("%s...", (ParamCount == 0)? "" : ",");
}
WriteOutput (")");
}
WriteOutput (" ");
if (Full) {
WriteOutput ("%.*s",
SB_GetLen (&M->Replacement),
SB_GetConstBuf (&M->Replacement));
}
WriteOutput ("\n");
}
static void OutputMacros (int Predefined, int Full)
/* Output macros to the output file depending on the flags given. */
{
/* Note: The Full flag is currently not used by any callers but is left in
** place for possible future changes.
*/
unsigned I;
for (I = 0; I < MACRO_TAB_SIZE; ++I) {
const Macro* M = MacroTab [I];
while (M) {
if ((Predefined != 0) == (M->Predefined != 0)) {
OutputMacro (M, Full);
}
M = M->Next;
}
}
}
/*****************************************************************************/
@@ -68,7 +133,7 @@ static Macro* UndefinedMacrosListHead;
Macro* NewMacro (const char* Name)
Macro* NewMacro (const char* Name, unsigned char Predefined)
/* Allocate a macro structure with the given name. The structure is not
** inserted into the macro table.
*/
@@ -84,6 +149,7 @@ Macro* NewMacro (const char* Name)
M->ParamCount = -1; /* Flag: Not a function-like macro */
InitCollection (&M->Params);
SB_Init (&M->Replacement);
M->Predefined = Predefined;
M->Variadic = 0;
memcpy (M->Name, Name, Len+1);
@@ -116,7 +182,7 @@ Macro* CloneMacro (const Macro* M)
** Use FreeMacro for that.
*/
{
Macro* New = NewMacro (M->Name);
Macro* New = NewMacro (M->Name, M->Predefined);
unsigned I;
for (I = 0; I < CollCount (&M->Params); ++I) {
@@ -134,7 +200,7 @@ Macro* CloneMacro (const Macro* M)
void DefineNumericMacro (const char* Name, long Val)
/* Define a macro for a numeric constant */
/* Define a predefined macro for a numeric constant */
{
char Buf[64];
@@ -148,10 +214,10 @@ void DefineNumericMacro (const char* Name, long Val)
void DefineTextMacro (const char* Name, const char* Val)
/* Define a macro for a textual constant */
/* Define a predefined macro for a textual constant */
{
/* Create a new macro */
Macro* M = NewMacro (Name);
Macro* M = NewMacro (Name, 1);
/* Set the value as replacement text */
SB_CopyStr (&M->Replacement, Val);
@@ -350,3 +416,19 @@ void PrintMacroStats (FILE* F)
}
}
}
void OutputPredefMacros (void)
/* Output all predefined macros to the output file */
{
OutputMacros (PREDEF_MACROS, FULL_DEFINITION);
}
void OutputUserMacros (void)
/* Output all user defined macros to the output file */
{
OutputMacros (USER_MACROS, FULL_DEFINITION);
}
+10 -3
View File
@@ -58,6 +58,7 @@ struct Macro {
int ParamCount; /* Number of parameters, -1 = no parens */
Collection Params; /* Parameter list (char*) */
StrBuf Replacement; /* Replacement text */
unsigned char Predefined; /* True if this is a predefined macro */
unsigned char Variadic; /* C99 variadic macro */
char Name[1]; /* Name, dynamically allocated */
};
@@ -70,7 +71,7 @@ struct Macro {
Macro* NewMacro (const char* Name);
Macro* NewMacro (const char* Name, unsigned char Predefined);
/* Allocate a macro structure with the given name. The structure is not
** inserted into the macro table.
*/
@@ -87,10 +88,10 @@ Macro* CloneMacro (const Macro* M);
*/
void DefineNumericMacro (const char* Name, long Val);
/* Define a macro for a numeric constant */
/* Define a predefined macro for a numeric constant */
void DefineTextMacro (const char* Name, const char* Val);
/* Define a macro for a textual constant */
/* Define a predefined macro for a textual constant */
void InsertMacro (Macro* M);
/* Insert the given macro into the macro table. */
@@ -132,6 +133,12 @@ int MacroCmp (const Macro* M1, const Macro* M2);
void PrintMacroStats (FILE* F);
/* Print macro statistics to the given text file. */
void OutputPredefMacros (void);
/* Output all predefined macros to the output file */
void OutputUserMacros (void);
/* Output all user defined macros to the output file */
/* End of macrotab.h */
+112 -3
View File
@@ -93,6 +93,8 @@ static void Usage (void)
" -V\t\t\t\tPrint the compiler version number\n"
" -W [-+]warning[,...]\t\tControl warnings ('-' disables, '+' enables)\n"
" -d\t\t\t\tDebug mode\n"
" -dM\t\t\t\tOutput all user macros (needs -E)\n"
" -dP\t\t\t\tOutput all predefined macros (needs -E)\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"
@@ -307,6 +309,10 @@ static void SetSys (const char* Sys)
DefineNumericMacro ("__RP6502__", 1);
break;
case TGT_AGAT:
DefineNumericMacro ("__AGAT__", 1);
break;
default:
AbEnd ("Unknown target system '%s'", Sys);
}
@@ -317,6 +323,81 @@ static void SetSys (const char* Sys)
static void DefineCpuMacros (void)
/* Define macros for the target CPU */
{
const char* CPUName;
/* Note: The list of CPUs handled here must match the one checked in
** OptCPU().
*/
switch (CPU) {
/* The following ones are legal CPUs as far as the assembler is
** concerned but are ruled out earlier in the compiler, so this
** function should never see them.
*/
case CPU_NONE:
case CPU_SWEET16:
case CPU_M740:
case CPU_4510:
case CPU_UNKNOWN:
CPUName = (CPU == CPU_UNKNOWN)? "unknown" : CPUNames[CPU];
Internal ("Invalid CPU \"%s\"", CPUName);
break;
case CPU_6502:
DefineNumericMacro ("__CPU_6502__", 1);
break;
case CPU_6502X:
DefineNumericMacro ("__CPU_6502X__", 1);
break;
case CPU_6502DTV:
DefineNumericMacro ("__CPU_6502DTV__", 1);
break;
case CPU_65SC02:
DefineNumericMacro ("__CPU_65SC02__", 1);
break;
case CPU_65C02:
DefineNumericMacro ("__CPU_65C02__", 1);
break;
case CPU_65816:
DefineNumericMacro ("__CPU_65816__", 1);
break;
case CPU_HUC6280:
DefineNumericMacro ("__CPU_HUC6280__", 1);
break;
default:
FAIL ("Unexpected value in switch");
break;
}
/* Define the macros for instruction sets. We only include the ones for
** the available CPUs.
*/
DefineNumericMacro ("__CPU_ISET_6502__", CPU_ISET_6502);
DefineNumericMacro ("__CPU_ISET_6502X__", CPU_ISET_6502X);
DefineNumericMacro ("__CPU_ISET_6502DTV__", CPU_ISET_6502DTV);
DefineNumericMacro ("__CPU_ISET_65SC02__", CPU_ISET_65SC02);
DefineNumericMacro ("__CPU_ISET_65C02__", CPU_ISET_65C02);
DefineNumericMacro ("__CPU_ISET_65816__", CPU_ISET_65816);
DefineNumericMacro ("__CPU_ISET_HUC6280__", CPU_ISET_HUC6280);
/* Now define the macro that contains the bit set with the available
** cpu instructions.
*/
DefineNumericMacro ("__CPU__", CPUIsets[CPU]);
}
static void FileNameOption (const char* Opt, const char* Arg, StrBuf* Name)
/* Handle an option that remembers a file name for later */
{
@@ -477,7 +558,9 @@ static void OptCreateFullDep (const char* Opt attribute ((unused)),
static void OptCPU (const char* Opt, const char* Arg)
/* Handle the --cpu option */
{
/* Find the CPU from the given name */
/* Find the CPU from the given name. We do only accept a certain number
** of CPUs. If the list is changed, be sure to adjust SetCpuMacros().
*/
CPU = FindCPU (Arg);
if (CPU != CPU_6502 && CPU != CPU_6502X && CPU != CPU_65SC02 &&
CPU != CPU_65C02 && CPU != CPU_65816 && CPU != CPU_HUC6280 &&
@@ -945,7 +1028,25 @@ int main (int argc, char* argv[])
break;
case 'd':
OptDebug (Arg, 0);
P = Arg + 2;
if (*P == '\0') {
OptDebug (Arg, 0);
} else {
while (*P) {
switch (*P) {
case 'M':
DumpUserMacros = 1;
break;
case 'P':
DumpPredefMacros = 1;
break;
default:
UnknownOption (Arg);
break;
}
++P;
}
}
break;
case 'h':
@@ -1057,13 +1158,20 @@ int main (int argc, char* argv[])
AbEnd ("No input files");
}
/* The options to output macros can only be used with -E */
if ((DumpPredefMacros || DumpUserMacros) && !PreprocessOnly) {
AbEnd ("Preprocessor macro output can only be used together with -E");
}
/* 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 no CPU given, use the default CPU for the target. Define macros that
** allow to query the CPU.
*/
if (CPU == CPU_UNKNOWN) {
if (Target != TGT_UNKNOWN) {
CPU = GetTargetProperties (Target)->DefaultCPU;
@@ -1071,6 +1179,7 @@ int main (int argc, char* argv[])
CPU = CPU_6502;
}
}
DefineCpuMacros ();
/* If no memory model was given, use the default */
if (MemoryModel == MMODEL_UNKNOWN) {
+4
View File
@@ -55,9 +55,12 @@
/* Opcode description table */
/* CAUTION: table must be sorted by mnemonic for bsearch */
const OPCDesc OPCTable[OP65_COUNT] = {
/* 65XX opcodes */
/* BEGIN SORTED_OPCODES.SH */
{ OP65_ADC, /* opcode */
"adc", /* mnemonic */
0, /* size */
@@ -586,6 +589,7 @@ const OPCDesc OPCTable[OP65_COUNT] = {
REG_Y, /* use */
REG_A | PSTATE_ZN /* chg */
},
/* END SORTED_OPCODES.SH */
};
+4 -6
View File
@@ -89,10 +89,12 @@ typedef enum {
} pragma_t;
/* Pragma table */
/* CAUTION: table must be sorted for bsearch */
static const struct Pragma {
const char* Key; /* Keyword */
pragma_t Tok; /* Token */
} Pragmas[] = {
/* BEGIN SORTED.SH */
{ "align", PRAGMA_ALIGN },
{ "allow-eager-inline", PRAGMA_ALLOW_EAGER_INLINE },
{ "allow_eager_inline", PRAGMA_ALLOW_EAGER_INLINE },
@@ -127,6 +129,7 @@ static const struct Pragma {
{ "writable-strings", PRAGMA_WRITABLE_STRINGS },
{ "writable_strings", PRAGMA_WRITABLE_STRINGS },
{ "zpsym", PRAGMA_ZPSYM },
/* END SORTED.SH */
};
#define PRAGMA_COUNT (sizeof (Pragmas) / sizeof (Pragmas[0]))
@@ -433,12 +436,7 @@ static void ApplySegNamePragma (pragma_t Token, int PushPop, const char* Name, u
SetSegAddrSize (Name, AddrSize);
}
/* 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);
}
g_segname (Seg);
}
+4 -1
View File
@@ -216,10 +216,12 @@ typedef enum {
/* Preprocessor directive tokens mapping table */
/* CAUTION: table must be sorted for bsearch */
static const struct PPDType {
const char* Tok; /* Token */
ppdirective_t Type; /* Type */
} PPDTypes[] = {
/* BEGIN SORTED.SH */
{ "define", PPD_DEFINE },
{ "elif", PPD_ELIF },
{ "else", PPD_ELSE },
@@ -233,6 +235,7 @@ static const struct PPDType {
{ "pragma", PPD_PRAGMA },
{ "undef", PPD_UNDEF },
{ "warning", PPD_WARNING },
/* END SORTED.SH */
};
/* Number of preprocessor directive types */
@@ -2572,7 +2575,7 @@ static void DoDefine (void)
CheckForBadIdent (Ident, Std, 0);
/* Create a new macro definition */
M = NewMacro (Ident);
M = NewMacro (Ident, 0);
/* Check if this is a function-like macro */
if (CurC == '(') {
+3
View File
@@ -87,11 +87,13 @@ enum {
};
/* Token table */
/* CAUTION: table must be sorted for bsearch */
static const struct Keyword {
char* Key; /* Keyword name */
unsigned char Tok; /* The token */
unsigned char Std; /* Token supported in which standards? */
} Keywords [] = {
/* BEGIN SORTED.SH */
{ "_Pragma", TOK_PRAGMA, TT_C89 | TT_C99 | TT_CC65 }, /* !! */
{ "_Static_assert", TOK_STATIC_ASSERT, TT_CC65 }, /* C11 */
{ "__AX__", TOK_AX, TT_C89 | TT_C99 | TT_CC65 },
@@ -145,6 +147,7 @@ static const struct Keyword {
{ "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 },
/* END SORTED.SH */
};
#define KEY_COUNT (sizeof (Keywords) / sizeof (Keywords [0]))
+4 -3
View File
@@ -78,19 +78,20 @@ static void StdFunc_strlen (FuncDesc*, ExprDesc*);
/* Table with all known functions and their handlers. Must be sorted
** alphabetically!
/* Table with all known functions and their handlers.
** CAUTION: table must be alphabetically sorted for bsearch
*/
static struct StdFuncDesc {
const char* Name;
void (*Handler) (FuncDesc*, ExprDesc*);
} StdFuncs[] = {
/* BEGIN SORTED.SH */
{ "memcpy", StdFunc_memcpy },
{ "memset", StdFunc_memset },
{ "strcmp", StdFunc_strcmp },
{ "strcpy", StdFunc_strcpy },
{ "strlen", StdFunc_strlen },
/* END SORTED.SH */
};
#define FUNC_COUNT (sizeof (StdFuncs) / sizeof (StdFuncs[0]))
+12 -3
View File
@@ -122,6 +122,11 @@ static int DoAssemble = 1;
/* The name of the output file, NULL if none given */
static const char* OutputName = 0;
/* The path part of the output file, NULL if none given
** or the OutputName is just a filename with no path
** information. */
static char *OutputDirectory = 0;
/* The name of the linker configuration file if given */
static const char* LinkerConfig = 0;
@@ -555,7 +560,7 @@ static void AssembleFile (const char* File, const char* TmpFile, unsigned ArgCou
if (TmpFile) {
ObjName = MakeFilename (TmpFile, ".o");
} else {
ObjName = MakeTmpFilename (".o");
ObjName = MakeTmpFilename (OutputDirectory, File, ".o");
}
CmdSetOutput (&CA65, ObjName);
CmdAddFile (&LD65, ObjName);
@@ -684,7 +689,7 @@ static void Compile (const char* File)
if (DoAssemble) {
/* set a temporary output file name */
TmpFile = MakeTmpFilename(".s");
TmpFile = MakeTmpFilename(OutputDirectory, File, ".s");
CmdSetOutput (&CC65, TmpFile);
}
@@ -729,7 +734,7 @@ static void CompileRes (const char* File)
** BEFORE adding the file
*/
if (DoAssemble && DoLink) {
AsmName = MakeTmpFilename(".s");
AsmName = MakeTmpFilename(OutputDirectory, File, ".s");
CmdSetAsmOutput(&GRC, AsmName);
}
@@ -1623,6 +1628,7 @@ int main (int argc, char* argv [])
case 'o':
/* Name the output file */
OutputName = GetArg (&I, 2);
OutputDirectory = GetFileDirectory(OutputName);
break;
case 'r':
@@ -1713,6 +1719,9 @@ int main (int argc, char* argv [])
}
RemoveTempFiles ();
if (OutputDirectory != NULL) {
xfree(OutputDirectory);
}
/* Return an apropriate exit code */
return EXIT_SUCCESS;
+3 -1
View File
@@ -48,8 +48,10 @@
/* CAUTION: table must be sorted for bsearch */
static const FileId TypeTable[] = {
/* Upper case stuff for obsolete operating systems */
/* BEGIN SORTED.SH */
{ "A", FILETYPE_LIB },
{ "A65", FILETYPE_ASM },
{ "ASM", FILETYPE_ASM },
@@ -65,7 +67,6 @@ static const FileId TypeTable[] = {
{ "S", FILETYPE_ASM },
{ "SER", FILETYPE_O65 },
{ "TGI", FILETYPE_O65 },
{ "a", FILETYPE_LIB },
{ "a65", FILETYPE_ASM },
{ "asm", FILETYPE_ASM },
@@ -81,6 +82,7 @@ static const FileId TypeTable[] = {
{ "s", FILETYPE_ASM },
{ "ser", FILETYPE_O65 },
{ "tgi", FILETYPE_O65 },
/* END SORTED.SH */
};
#define FILETYPE_COUNT (sizeof (TypeTable) / sizeof (TypeTable[0]))
+47 -23
View File
@@ -33,8 +33,17 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined(_MSC_VER)
# include <process.h>
#else
# include <unistd.h>
#endif
#include "xmalloc.h"
#include "fname.h"
@@ -93,7 +102,28 @@ const char* FindName (const char* Path)
return Path + Len;
}
char *GetFileDirectory (const char* File)
/* Return a copy of the path part of a File, or NULL if there is none. */
{
char *Out, *P;
if (File == NULL) {
return NULL;
}
Out = xmalloc (strlen (File) + 1);
strcpy(Out, File);
P = (char *)FindName (Out);
if (P == Out) {
/* This is a simple filename. */
xfree (Out);
return NULL;
}
*P = '\0';
return Out;
}
char* MakeFilename (const char* Origin, const char* Ext)
/* Make a new file name from Origin and Ext. If Origin has an extension, it
@@ -119,35 +149,29 @@ char* MakeFilename (const char* Origin, const char* Ext)
char* MakeTmpFilename (const char* Ext)
/* Make a new temporary file name from Ext. tmpnam(3) is called
** and Ext is appended to generate the filename.
char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ext)
/* Make a new temporary file name from Origin and Ext.
** The result is placed in a malloc'ed buffer and returned.
*/
{
char* Out;
char Buffer[L_tmpnam * 2]; /* a lazy way to ensure we have space for Ext */
size_t Len = 0;
static unsigned int Counter = 0;
/*
** gcc emits the following warning here:
**
** warning: the use of `tmpnam' is dangerous, better use `mkstemp'
**
** however, mkstemp actually opens a file, which we do not want.
** tmpfile() is unsuitable for the same reason.
**
** we could write our own version, but then we would have to struggle
** with supporting multiple build environments.
**
** tmpnam(3) is safe here, because ca65 / cc65 / ld65 will simply clobber
** an existing file, or exit if with an error if they are unable to.
**
** gcc will also complain, if you don't use the return value from tmpnam(3)
*/
strcat(tmpnam(Buffer), Ext);
/* Allocate enough for the directory, ... */
if (Directory != NULL) {
Len = strlen (Directory);
}
Out = xmalloc (strlen (Buffer) + 1);
strcpy (Out, Buffer);
/* ... plus the the original name, the maximum length of the PID, the
* maximum length of the counter, the extension, and the terminator.
*/
Len += strlen (Origin) + (strlen (".2147483648") * 2) + strlen (Ext) + 1;
Out = xmalloc (Len);
snprintf (Out, Len, "%s%s.%u.%u%s", (Directory != NULL ? Directory : ""),
FindName(Origin), getpid(), Counter, Ext);
Counter++;
return Out;
}
+7 -3
View File
@@ -52,6 +52,9 @@ const char* FindName (const char* Path);
** the file, the function returns Path as name.
*/
char *GetFileDirectory (const char* File);
/* Return a copy of the path part of a File, or NULL if there is none. */
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
@@ -59,9 +62,10 @@ char* MakeFilename (const char* Origin, const char* Ext);
** The function may be used to create "foo.o" from "foo.s".
*/
char* MakeTmpFilename (const char* Ext);
/* Make a new temporary file name from Ext. tmpnam(3) is called
** and Ext is appended to generate the filename.
char* MakeTmpFilename (const char *Directory, const char *Origin, const char* Ext);
/* Make a new temporary file name from Directory, Origin, and Ext.
** A temporary path is generated from the Directory,
** the Origin filename, the compiler's PID and the Extension.
** The result is placed in a malloc'ed buffer and returned.
*/
+25 -2
View File
@@ -129,7 +129,25 @@ static const unsigned char CTPET[256] = {
0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
};
/* Translation table KOI8-R -> Agat-9 */
static unsigned char CTAgat[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,
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,
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,0xA0,
0x1B,0x5C,0x10,0x12,0x1D,0x1F,0x13,0x1C,0x11,0x1E,0x14,0xA0,0x02,0x5F,0xA0,0xA0,
0xA0,0xA0,0xA0,0xA0,0xA0,0x9E,0x04,0xA0,0x3C,0x3E,0xA0,0xA0,0x30,0x32,0xA0,0x2F,
0xA0,0xA0,0xA0,0x0F,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,
0xA0,0xA0,0xA0,0x9F,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,
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;
@@ -138,10 +156,13 @@ struct TargetEntry {
target_t Id; /* Target ID */
};
/* Table that maps target names to IDs. Sorted alphabetically for bsearch().
/* Table that maps target names to IDs.
** Allows multiple entries for one target ID (target name aliases).
** CAUTION: must be alphabetically for bsearch().
*/
static const TargetEntry TargetMap[] = {
/* BEGIN SORTED.SH */
{ "agat", TGT_AGAT },
{ "apple2", TGT_APPLE2 },
{ "apple2enh", TGT_APPLE2ENH },
{ "atari", TGT_ATARI },
@@ -180,6 +201,7 @@ static const TargetEntry TargetMap[] = {
{ "sym1", TGT_SYM1 },
{ "telestrat", TGT_TELESTRAT },
{ "vic20", TGT_VIC20 },
/* END SORTED.SH */
};
#define MAP_ENTRY_COUNT (sizeof (TargetMap) / sizeof (TargetMap[0]))
@@ -223,6 +245,7 @@ static const TargetProperties PropertyTable[TGT_COUNT] = {
{ "sym1", CPU_6502, BINFMT_BINARY, CTNone },
{ "kim1", CPU_6502, BINFMT_BINARY, CTNone },
{ "rp6502", CPU_65C02, BINFMT_BINARY, CTNone },
{ "agat", CPU_6502, BINFMT_BINARY, CTAgat },
};
/* Target system */
+1
View File
@@ -89,6 +89,7 @@ typedef enum {
TGT_SYM1,
TGT_KIM1,
TGT_RP6502,
TGT_AGAT,
TGT_COUNT /* Number of target systems */
} target_t;
+3
View File
@@ -2523,6 +2523,7 @@ static void NextChar (InputData* D)
/* CAUTION: table must be sorted for bsearch */
static void NextToken (InputData* D)
/* Read the next token from the input stream */
{
@@ -2530,6 +2531,7 @@ static void NextToken (InputData* D)
const char Keyword[12];
Token Tok;
} KeywordTable[] = {
/* BEGIN SORTED.SH */
{ "abs", TOK_ABSOLUTE },
{ "addrsize", TOK_ADDRSIZE },
{ "auto", TOK_AUTO },
@@ -2578,6 +2580,7 @@ static void NextToken (InputData* D)
{ "var", TOK_VAR },
{ "version", TOK_VERSION },
{ "zp", TOK_ZEROPAGE },
/* END SORTED.SH */
};
+4 -1
View File
@@ -61,14 +61,17 @@ struct ConverterMapEntry {
StrBuf* (*ConvertFunc) (const Bitmap*, const Collection*);
};
/* Converter table, alphabetically sorted */
/* Converter table */
/* CAUTION: table must be alphabetically sorted for bsearch */
static const ConverterMapEntry ConverterMap[] = {
/* BEGIN SORTED.SH */
{ "geos-bitmap", GenGeosBitmap },
{ "geos-icon", GenGeosIcon },
{ "koala", GenKoala },
{ "lynx-sprite", GenLynxSprite },
{ "raw", GenRaw },
{ "vic2-sprite", GenVic2Sprite },
/* END SORTED.SH */
};
+4 -2
View File
@@ -69,12 +69,14 @@ static InputFormatDesc InputFormatTable[ifCount] = {
{ ReadPCXFile },
};
/* Table that maps extensions to input formats. Must be sorted alphabetically */
/* Table that maps extensions to input formats. */
/* CAUTION: table must be alphabetically sorted for bsearch */
static const FileId FormatTable[] = {
/* Upper case stuff for obsolete operating systems */
/* BEGIN SORTED.SH */
{ "PCX", ifPCX },
{ "pcx", ifPCX },
/* END SORTED.SH */
};
+4 -2
View File
@@ -78,22 +78,24 @@ static OutputFormatDesc OutputFormatTable[ofCount] = {
{ WriteCFile },
};
/* Table that maps extensions to Output formats. Must be sorted alphabetically */
/* Table that maps extensions to Output formats. */
/* CAUTION: table must be alphabetically sorted for bsearch */
static const FileId FormatTable[] = {
/* Upper case stuff for obsolete operating systems */
/* BEGIN SORTED.SH */
{ "A", ofAsm },
{ "ASM", ofAsm },
{ "BIN", ofBin },
{ "C", ofC },
{ "INC", ofAsm },
{ "S", ofAsm },
{ "a", ofAsm },
{ "asm", ofAsm },
{ "bin", ofBin },
{ "c", ofC },
{ "inc", ofAsm },
{ "s", ofAsm },
/* END SORTED.SH */
};
+4 -1
View File
@@ -56,9 +56,12 @@ struct PaletteMapEntry {
StrBuf* (*PaletteFunc) (const Bitmap*, const Collection*);
};
/* Converter table, alphabetically sorted */
/* Converter table */
/* CAUTION: table must be alphabetically sorted for bsearch */
static const PaletteMapEntry PaletteMap[] = {
/* BEGIN SORTED.SH */
{ "lynx-palette", GenLynxPalette },
/* END SORTED.SH */
};
Binary file not shown.
+14
View File
@@ -8,6 +8,10 @@
lda #$ea
.endif
.ifp02x
lax #$ea
.endif
.ifpsc02
jmp ($1234,x)
.endif
@@ -72,3 +76,13 @@
.byte 0,"CPU_ISET_6502DTV"
.endif
; step 3: switch through all supported cpus to verify the pseudo-op is there
.p02
.p02X
.psc02
.pc02
.p816
.p4510
.pdtv
+162
View File
@@ -0,0 +1,162 @@
/* test headers which should define NULL */
#include <locale.h>
#ifndef NULL
#error "NULL should be defined in locale.h"
#endif
#undef NULL
#include <stdlib.h>
#ifndef NULL
#error "NULL should be defined in stdlib.h"
#endif
#undef NULL
#include <string.h>
#ifndef NULL
#error "NULL should be defined in string.h"
#endif
#undef NULL
#include <stddef.h>
#ifndef NULL
#error "NULL should be defined in stddef.h"
#endif
#undef NULL
#include <stdio.h>
#ifndef NULL
#error "NULL should be defined in stdio.h"
#endif
#undef NULL
#include <time.h>
#ifndef NULL
#error "NULL should be defined in time.h"
#endif
#undef NULL
/* does not exist in cc65 (yet)
#include <wchar.h>
#ifndef NULL
#error "NULL should be defined in wchar.h"
#endif */
#undef NULL
/* test headers which should NOT define NULL */
#include <assert.h>
#ifdef NULL
#error "NULL should NOT be defined in assert.h"
#undef NULL
#endif
/* does not exist in cc65 (yet)
#include <complex.h>
#ifdef NULL
#error "NULL should NOT be defined in complex.h"
#undef NULL
#endif */
#include <ctype.h>
#ifdef NULL
#error "NULL should NOT be defined in ctype.h"
#undef NULL
#endif
#include <errno.h>
#ifdef NULL
#error "NULL should NOT be defined in errno.h"
#undef NULL
#endif
/* does not exist in cc65 (yet)
#include <fenv.h>
#ifdef NULL
#error "NULL should NOT be defined in fenv.h"
#undef NULL
#endif */
/* does not exist in cc65 (yet)
#include <float.h>
#ifdef NULL
#error "NULL should NOT be defined in float.h"
#undef NULL
#endif */
#include <inttypes.h>
#ifdef NULL
#error "NULL should NOT be defined in inttypes.h"
#undef NULL
#endif
#include <iso646.h>
#ifdef NULL
#error "NULL should NOT be defined in iso646.h"
#undef NULL
#endif
#include <limits.h>
#ifdef NULL
#error "NULL should NOT be defined in limits.h"
#undef NULL
#endif
/* does not exist in cc65 (yet)
#include <math.h>
#ifdef NULL
#error "NULL should NOT be defined in math.h"
#undef NULL
#endif */
#include <setjmp.h>
#ifdef NULL
#error "NULL should NOT be defined in setjmp.h"
#undef NULL
#endif
#include <signal.h>
#ifdef NULL
#error "NULL should NOT be defined in signal.h"
#undef NULL
#endif
#include <stdarg.h>
#ifdef NULL
#error "NULL should NOT be defined in stdarg.h"
#undef NULL
#endif
#include <stdbool.h>
#ifdef NULL
#error "NULL should NOT be defined in stdbool.h"
#undef NULL
#endif
#include <stdint.h>
#ifdef NULL
#error "NULL should NOT be defined in stdint.h"
#undef NULL
#endif
/* does not exist in cc65 (yet)
#include <tgmath.h>
#ifdef NULL
#error "NULL should NOT be defined in tgmath.h"
#undef NULL
#endif */
/* does not exist in cc65 (yet)
#include <wctype.h>
#ifdef NULL
#error "NULL should NOT be defined in wctype.h"
#undef NULL
#endif */
int main(void)
{
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
// bug #2172 - Invalid code generated for switch statement
#include <stdlib.h>
#include <stdio.h>
// cc65 -o bug2172.s -Cl -Oirs -T -t c64 bug2172.c
int func(int expr)
{
switch (expr) {
int i;
case 0:
i = 17;
return i;
default:
i = 16;
return i;
}
}
int err = 0;
int main(void)
{
int i = 0;
int n = 42;
for (i = -3; i < 0; i++) {
n = func(i);
if ((i < -3) || (i >= 0)) {
goto stackerr;
}
printf("i:%d expect:16 got:%d\n", i, n);
if (n != 16) {
err++;
}
}
n = func(0);
printf("i:%d expect:17 got:%d\n", 0, n);
if (n != 17) {
err++;
}
for (i = 1; i < 4; i++) {
n = func(i);
if ((i < 1) || (i >= 4)) {
goto stackerr;
}
printf("i:%d expect:16 got:%d\n", i, n);
if (n != 16) {
err++;
}
}
return err;
stackerr:
fputs("stack messed up?\n", stdout);
return -1;
}
+51
View File
@@ -0,0 +1,51 @@
#include <stdlib.h>
#include <stdio.h>
/* Just some arbitrary code, more fun with goto */
int func(int m)
{
long x = -42; /* sp: -4 */
switch (x) {
/* return 0; // C99 only */
int i = 42; /* sp: -6 */
L0:
--i;
default:
if (i != 0) {
long j = 13; /* sp: -10 */
goto L1;
L1:
case 0x7FFF01:
m--;
case 0x7EFF0001:
case 0x7FFF0001:
i++;
} /* sp: -6 */
case 0x7FFF00:
case 0x7FFF0000:
break;
goto L0;
{
int skipped = 42; /* sp: -8 */
case 0x7EFF00:
case 0x7EFF0000:
++skipped;
} /* sp: -6 */
} /* sp: -4 */
return m;
}
int err = 0;
int main(void)
{
int n = 42;
n = func(7);
if (n != 7) {
err++;
}
printf("n:%d\n", n);
return err;
}

Some files were not shown because too many files have changed in this diff Show More