mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 10:42:07 +00:00
Compare commits
149 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c10ca62ad | ||
|
|
49809f6caf | ||
|
|
81675bc4c7 | ||
|
|
37b615f070 | ||
|
|
6438ae2591 | ||
|
|
33ae6d8ca3 | ||
|
|
ebc9a4b786 | ||
|
|
e195076793 | ||
|
|
b14beeff10 | ||
|
|
db54c2ebd6 | ||
|
|
eadaa47770 | ||
|
|
b5e7855afd | ||
|
|
ce7d1d5d49 | ||
|
|
64a3929f4e | ||
|
|
1c1a4e6ac9 | ||
|
|
cc3aa969b8 | ||
|
|
7055301616 | ||
|
|
bbf24916e6 | ||
|
|
261503c7c8 | ||
|
|
b924f58bb0 | ||
|
|
ac78c37f9d | ||
|
|
c8d9ae21e6 | ||
|
|
5281704f62 | ||
|
|
fd4327327c | ||
|
|
d81d128a04 | ||
|
|
d067f31678 | ||
|
|
d02294505c | ||
|
|
eb4bbb3e0b | ||
|
|
2ab10a95e4 | ||
|
|
bc60b85785 | ||
|
|
9d0203a4ee | ||
|
|
a18b65de21 | ||
|
|
1c47ffcce8 | ||
|
|
bbf60c7197 | ||
|
|
60c3a7e2f3 | ||
|
|
5702995978 | ||
|
|
483d94f88b | ||
|
|
9b4d16b0d8 | ||
|
|
a3e95f99d2 | ||
|
|
e3a31d7e59 | ||
|
|
d9f5ce339a | ||
|
|
361f1ac50b | ||
|
|
4f8cf84ed4 | ||
|
|
c75b9d4d55 | ||
|
|
cd2af0204e | ||
|
|
91241b44da | ||
|
|
1d174f37da | ||
|
|
2777044f70 | ||
|
|
e5e64b8cec | ||
|
|
8534f3a148 | ||
|
|
bdc6401eba | ||
|
|
21d0b402d3 | ||
|
|
a305649557 | ||
|
|
3b0e207036 | ||
|
|
83eddb4c4e | ||
|
|
57997756b6 | ||
|
|
ab66b28fdf | ||
|
|
116569f54d | ||
|
|
2b839fec37 | ||
|
|
513d451710 | ||
|
|
9399ba36f9 | ||
|
|
ef3a486845 | ||
|
|
f0e5c5ccc8 | ||
|
|
9b4959cb75 | ||
|
|
dca82e6d95 | ||
|
|
871c5ed360 | ||
|
|
635014b74d | ||
|
|
7ad634febd | ||
|
|
1e1339467e | ||
|
|
9e24c26468 | ||
|
|
c1213f536b | ||
|
|
82de716454 | ||
|
|
a64d725a8d | ||
|
|
80e2129f22 | ||
|
|
af70f03933 | ||
|
|
004bc2e50e | ||
|
|
25efb00769 | ||
|
|
c6c7b99fad | ||
|
|
e28d8384fb | ||
|
|
27a350eaab | ||
|
|
cd8d895c1b | ||
|
|
4577a01c68 | ||
|
|
6758387668 | ||
|
|
424702b272 | ||
|
|
191f98a008 | ||
|
|
00de7674af | ||
|
|
32fa032a62 | ||
|
|
73e44cb803 | ||
|
|
3e4350afa4 | ||
|
|
0d07caba60 | ||
|
|
3992ce2502 | ||
|
|
215d6f0c5b | ||
|
|
f3394f46b4 | ||
|
|
e3df758897 | ||
|
|
d7319ecd00 | ||
|
|
d661b3a532 | ||
|
|
c0be5ddbb2 | ||
|
|
97d431d1f4 | ||
|
|
a849e1107e | ||
|
|
a41bdff88f | ||
|
|
cb383e6b1a | ||
|
|
45b6872e2a | ||
|
|
056109652d | ||
|
|
284600ef1f | ||
|
|
2bf31870a7 | ||
|
|
6198cc185c | ||
|
|
e4571bc0fc | ||
|
|
46269240c8 | ||
|
|
b1269ab53a | ||
|
|
3ecd169cd6 | ||
|
|
2dab1474b8 | ||
|
|
08b1b97a45 | ||
|
|
17192ea6f0 | ||
|
|
af506985e5 | ||
|
|
0f488b6759 | ||
|
|
240d2a7f14 | ||
|
|
2ff286223b | ||
|
|
af5f889326 | ||
|
|
3e92f33319 | ||
|
|
0ffa4ce9ef | ||
|
|
34656f9e5d | ||
|
|
c61c112218 | ||
|
|
55974bc743 | ||
|
|
94005513a4 | ||
|
|
36edec6231 | ||
|
|
7d176245d8 | ||
|
|
c65d58c589 | ||
|
|
1f9fd0f060 | ||
|
|
1218da79a9 | ||
|
|
fd4b5c8925 | ||
|
|
bc99ee2210 | ||
|
|
de269987f7 | ||
|
|
7770827cce | ||
|
|
7ab9742299 | ||
|
|
6aecf65552 | ||
|
|
2571dc459c | ||
|
|
da19380cc4 | ||
|
|
ab47428c0e | ||
|
|
23b29a9ae1 | ||
|
|
35448887af | ||
|
|
6ccd386587 | ||
|
|
34d40a67c9 | ||
|
|
c21c0f458f | ||
|
|
51c01e3aad | ||
|
|
d0d85abb97 | ||
|
|
88ac0282e4 | ||
|
|
8811784b71 | ||
|
|
6579743410 | ||
|
|
b90406861d |
13
LICENSE
13
LICENSE
@@ -1,5 +1,5 @@
|
||||
rgbasm, rgblink, and rgblib are derived from Justin Lloyd's RGBDS, which
|
||||
is released under the following license:
|
||||
rgbasm and rgblink are derived from Justin Lloyd's RGBDS, which is
|
||||
released under the following license:
|
||||
|
||||
DO WHATEVER PUBLIC LICENSE*
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
@@ -17,3 +17,12 @@ is released under the following license:
|
||||
|
||||
rgbfix was rewritten from scratch by Anthony J. Bentley, and is released
|
||||
under the ISC license; see the source file for the text of the license.
|
||||
|
||||
extern/err.c is derived from the Musl C library, http://www.musl-libc.org,
|
||||
and is released under the MIT license.
|
||||
|
||||
extern/reallocarray.c is derived from the OpenBSD Project,
|
||||
http://www.openbsd.org, and is released under the ISC license.
|
||||
|
||||
extern/strl.c is derived from the OpenBSD Project, http://www.openbsd.org,
|
||||
and is released under the BSD license.
|
||||
|
||||
118
Makefile
118
Makefile
@@ -1,4 +1,8 @@
|
||||
CFLAGS += -Wall -Iinclude -Iinclude/asm/gameboy -g -std=c99
|
||||
.POSIX:
|
||||
|
||||
WARNFLAGS = -Wall -Werror=implicit
|
||||
REALCFLAGS = ${CFLAGS} ${WARNFLAGS} -Iinclude -g \
|
||||
-std=c99 -D_POSIX_C_SOURCE=200809L
|
||||
|
||||
# User-defined variables
|
||||
PREFIX = /usr/local
|
||||
@@ -6,15 +10,9 @@ BINPREFIX = ${PREFIX}/bin
|
||||
MANPREFIX = ${PREFIX}/man
|
||||
Q = @
|
||||
|
||||
yacc_pre := \
|
||||
src/asm/yaccprt1.y\
|
||||
src/asm/gameboy/yaccprt2.y\
|
||||
src/asm/yaccprt3.y\
|
||||
src/asm/gameboy/yaccprt4.y
|
||||
|
||||
rgbasm_obj := \
|
||||
src/asm/alloca.o \
|
||||
rgbasm_obj = \
|
||||
src/asm/asmy.o \
|
||||
src/asm/charmap.o \
|
||||
src/asm/fstack.o \
|
||||
src/asm/globlex.o \
|
||||
src/asm/lexer.o \
|
||||
@@ -23,13 +21,13 @@ rgbasm_obj := \
|
||||
src/asm/output.o \
|
||||
src/asm/rpn.o \
|
||||
src/asm/symbol.o \
|
||||
src/asm/gameboy/locallex.o
|
||||
src/asm/locallex.o \
|
||||
src/extern/err.o \
|
||||
src/extern/reallocarray.o \
|
||||
src/extern/strlcpy.o \
|
||||
src/extern/strlcat.o
|
||||
|
||||
rgblib_obj := \
|
||||
src/lib/library.o \
|
||||
src/lib/main.o
|
||||
|
||||
rgblink_obj := \
|
||||
rgblink_obj = \
|
||||
src/link/assign.o \
|
||||
src/link/library.o \
|
||||
src/link/main.o \
|
||||
@@ -37,75 +35,73 @@ rgblink_obj := \
|
||||
src/link/object.o \
|
||||
src/link/output.o \
|
||||
src/link/patch.o \
|
||||
src/link/symbol.o
|
||||
src/link/symbol.o \
|
||||
src/extern/err.o
|
||||
|
||||
rgbfix_obj := \
|
||||
src/fix/main.o
|
||||
rgbfix_obj = \
|
||||
src/fix/main.o \
|
||||
src/extern/err.o
|
||||
|
||||
all: rgbasm rgblib rgblink rgbfix
|
||||
all: rgbasm rgblink rgbfix
|
||||
|
||||
clean:
|
||||
${Q}rm -rf rgbasm rgbasm.exe ${rgbasm_obj}
|
||||
${Q}rm -rf rgblib rgblib.exe ${rgblib_obj}
|
||||
${Q}rm -rf rgblink rgblink.exe ${rgblink_obj}
|
||||
${Q}rm -rf rgbfix rgbfix.exe ${rgbfix_obj}
|
||||
${Q}rm -rf src/asm/asmy.c
|
||||
$Qrm -rf rgbds.html
|
||||
$Qrm -rf rgbasm rgbasm.exe ${rgbasm_obj} rgbasm.html
|
||||
$Qrm -rf rgblink rgblink.exe ${rgblink_obj} rgblink.html
|
||||
$Qrm -rf rgbfix rgbfix.exe ${rgbfix_obj} rgbfix.html
|
||||
$Qrm -rf src/asm/asmy.c src/asm/asmy.h
|
||||
|
||||
install: all
|
||||
${Q}install -s -m 555 rgbasm ${BINPREFIX}/rgbasm
|
||||
${Q}install -s -m 555 rgbfix ${BINPREFIX}/rgbfix
|
||||
${Q}install -s -m 555 rgblink ${BINPREFIX}/rgblink
|
||||
${Q}install -s -m 555 rgblib ${BINPREFIX}/rgblib
|
||||
${Q}install -m 444 src/rgbds.7 ${MANPREFIX}/man7/rgbds.7
|
||||
${Q}install -m 444 src/asm/rgbasm.1 \
|
||||
${MANPREFIX}/man1/rgbasm.1
|
||||
${Q}install -m 444 src/fix/rgbfix.1 \
|
||||
${MANPREFIX}/man1/rgbfix.1
|
||||
${Q}install -m 444 src/link/rgblink.1 \
|
||||
${MANPREFIX}/man1/rgblink.1
|
||||
${Q}install -m 444 src/lib/rgblib.1 \
|
||||
${MANPREFIX}/man1/rgblib.1
|
||||
$Qmkdir -p ${BINPREFIX}
|
||||
$Qinstall -s -m 555 rgbasm ${BINPREFIX}/rgbasm
|
||||
$Qinstall -s -m 555 rgbfix ${BINPREFIX}/rgbfix
|
||||
$Qinstall -s -m 555 rgblink ${BINPREFIX}/rgblink
|
||||
$Qmkdir -p ${MANPREFIX}/man1 ${MANPREFIX}/man7
|
||||
$Qinstall -m 444 src/rgbds.7 ${MANPREFIX}/man7/rgbds.7
|
||||
$Qinstall -m 444 src/asm/rgbasm.1 ${MANPREFIX}/man1/rgbasm.1
|
||||
$Qinstall -m 444 src/fix/rgbfix.1 ${MANPREFIX}/man1/rgbfix.1
|
||||
$Qinstall -m 444 src/link/rgblink.1 ${MANPREFIX}/man1/rgblink.1
|
||||
|
||||
rgbasm: ${rgbasm_obj}
|
||||
${Q}${CC} ${CFLAGS} -o $@ ${rgbasm_obj} -lm
|
||||
|
||||
rgblib: ${rgblib_obj}
|
||||
${Q}${CC} ${CFLAGS} -o $@ ${rgblib_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgbasm_obj} -lm
|
||||
|
||||
rgblink: ${rgblink_obj}
|
||||
${Q}${CC} ${CFLAGS} -o $@ ${rgblink_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgblink_obj}
|
||||
|
||||
rgbfix: ${rgbfix_obj}
|
||||
${Q}${CC} ${CFLAGS} -o $@ ${rgbfix_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgbfix_obj}
|
||||
|
||||
.y.c:
|
||||
$Q${YACC} -d ${YFLAGS} -o $@ $<
|
||||
|
||||
.c.o:
|
||||
${Q}${CC} ${CFLAGS} -c -o $@ $<
|
||||
|
||||
src/asm/asmy.c: src/asm/asmy.y
|
||||
${Q}${YACC} -d -o $@ $<
|
||||
|
||||
src/asm/asmy.y: ${yacc_pre}
|
||||
${Q}cat ${yacc_pre} > $@
|
||||
$Q${CC} ${REALCFLAGS} -c -o $@ $<
|
||||
|
||||
src/asm/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h
|
||||
src/asm/asmy.h: src/asm/asmy.c
|
||||
|
||||
# Below is a target for the project maintainer to easily create win32 exes.
|
||||
# This is not for Windows users!
|
||||
# If you're building on Windows with Cygwin or Mingw, just follow the Unix
|
||||
# install instructions instead.
|
||||
mingw:
|
||||
${Q}env PATH=/usr/local/mingw32/bin:/bin:/usr/bin:/usr/local/bin make CC=gcc CFLAGS="-I/usr/local/mingw32/include ${CFLAGS}"
|
||||
${Q}mv rgbasm rgbasm.exe
|
||||
${Q}mv rgblib rgblib.exe
|
||||
${Q}mv rgblink rgblink.exe
|
||||
${Q}mv rgbfix rgbfix.exe
|
||||
$Qenv PATH=/usr/local/mingw32/bin:/bin:/usr/bin:/usr/local/bin \
|
||||
make WARNFLAGS= CC=gcc CFLAGS="-I/usr/local/mingw32/include \
|
||||
${CFLAGS}"
|
||||
$Qmv rgbasm rgbasm.exe
|
||||
$Qmv rgblink rgblink.exe
|
||||
$Qmv rgbfix rgbfix.exe
|
||||
|
||||
# Below is a target for the project maintainer to easily create web manuals.
|
||||
# It relies on mandoc: http://mdocml.bsd.lv
|
||||
MANDOC = -Thtml -Oman=/rgbds/manual/%N/ -Ostyle=/rgbds/manual/manual.css -Ios=General
|
||||
MANDOC = -Thtml -Ios=General -Oman=/rgbds/manual/%N/ \
|
||||
-Ostyle=/rgbds/manual/manual.css
|
||||
|
||||
wwwman:
|
||||
${Q}mandoc ${MANDOC} src/rgbds.7 | sed s/OpenBSD/General/ > rgbds.html
|
||||
${Q}mandoc ${MANDOC} src/asm/rgbasm.1 | sed s/OpenBSD/General/ > rgbasm.html
|
||||
${Q}mandoc ${MANDOC} src/fix/rgbfix.1 | sed s/OpenBSD/General/ > rgbfix.html
|
||||
${Q}mandoc ${MANDOC} src/lib/rgblib.1 | sed s/OpenBSD/General/ > rgblib.html
|
||||
${Q}mandoc ${MANDOC} src/link/rgblink.1 | sed s/OpenBSD/General/ > rgblink.html
|
||||
$Qmandoc ${MANDOC} src/rgbds.7 | sed s/OpenBSD/General/ > rgbds.html
|
||||
$Qmandoc ${MANDOC} src/asm/rgbasm.1 | sed s/OpenBSD/General/ > \
|
||||
rgbasm.html
|
||||
$Qmandoc ${MANDOC} src/fix/rgbfix.1 | sed s/OpenBSD/General/ > \
|
||||
rgbfix.html
|
||||
$Qmandoc ${MANDOC} src/link/rgblink.1 | sed s/OpenBSD/General/ > \
|
||||
rgblink.html
|
||||
|
||||
3
README
3
README
@@ -7,7 +7,6 @@ for the Game Boy and Game Boy Color. It consists of:
|
||||
|
||||
- rgbasm (assembler)
|
||||
- rgblink (linker)
|
||||
- rgblib (library manager)
|
||||
- rgbfix (checksum/header fixer)
|
||||
|
||||
rgbds-linux is a fork of the original RGBDS which aims to make the programs
|
||||
@@ -54,6 +53,6 @@ this variable. Defaults to @.
|
||||
Installing RGBDS (Windows)
|
||||
============================
|
||||
|
||||
Windows builds are available here: http://anthony.bentley.name/rgbds/
|
||||
Windows builds are available here: https://github.com/bentley/rgbds/releases
|
||||
|
||||
Copy the .exe files to C:\Windows\ or similar.
|
||||
|
||||
10
doc/asm.htm
10
doc/asm.htm
@@ -42,7 +42,7 @@
|
||||
<h3>Other ways than mnemonics to define data</h3>
|
||||
<ul>
|
||||
<li><a href="asm/db.htm">Defining constant data</a>
|
||||
<li><a href="asm/ds.htm">Declaring variables in a BSS section</a>
|
||||
<li><a href="asm/ds.htm">Declaring variables in a RAM section</a>
|
||||
<li><a href="asm/incbin.htm">Including binary files</a>
|
||||
</ul>
|
||||
|
||||
@@ -65,10 +65,7 @@
|
||||
<li><a href="asm/expr_fix.htm">ATAN</a>
|
||||
<li><a href="asm/expr_fix.htm">ATAN2</a>
|
||||
<li><a href="asm/miscfunc.htm">BANK</a>
|
||||
<li><a href="asm/section.htm">BSS</a>
|
||||
<li><a href="asm/section.htm">CODE</a>
|
||||
<li><a href="asm/expr_fix.htm">COS</a>
|
||||
<li><a href="asm/section.htm">DATA</a>
|
||||
<li><a href="asm/db.htm">DB</a>
|
||||
<li><a href="asm/miscfunc.htm">DEF</a>
|
||||
<li><a href="asm/expr_fix.htm">DIV</a>
|
||||
@@ -101,6 +98,8 @@
|
||||
<li><a href="asm/pops.htm">PUSHS</a>
|
||||
<li><a href="asm/rept.htm">REPT</a>
|
||||
<li><a href="asm/rs.htm">RB</a>
|
||||
<li><a href="asm/section.htm">ROM0</a>
|
||||
<li><a href="asm/section.htm">ROMX</a>
|
||||
<li><a href="asm/rs.htm">RSRESET</a>
|
||||
<li><a href="asm/rs.htm">RSSET</a>
|
||||
<li><a href="asm/rs.htm">RW</a>
|
||||
@@ -108,6 +107,7 @@
|
||||
<li><a href="asm/set.htm">SET</a>
|
||||
<li><a href="asm/shift.htm">SHIFT</a>
|
||||
<li><a href="asm/expr_fix.htm">SIN</a>
|
||||
<li><a href="asm/section.htm">SRAM</a>
|
||||
<li><a href="asm/expr_str.htm">STRCAT</a>
|
||||
<li><a href="asm/expr_str.htm">STRCMP</a>
|
||||
<li><a href="asm/expr_str.htm">STRIN</a>
|
||||
@@ -117,6 +117,8 @@
|
||||
<li><a href="asm/expr_str.htm">STRUPR</a>
|
||||
<li><a href="asm/expr_fix.htm">TAN</a>
|
||||
<li><a href="asm/section.htm">VRAM</a>
|
||||
<li><a href="asm/section.htm">WRAM0</a>
|
||||
<li><a href="asm/section.htm">WRAMX</a>
|
||||
<li><a href="asm/fail.htm">WARN</a>
|
||||
<li><a href="asm/export.htm">XDEF</a>
|
||||
<li><a href="asm/export.htm">XREF</a>
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<p><dfn>DB</dfn> defines a list of bytes that will be stored in the final image. Ideal for tables and text.</p>
|
||||
<pre>DB 1,2,3,4,"This is a string"</pre>
|
||||
<p>Alternatively you can use <dfn>DW</dfn> to store a list of words. Strings are not allowed as arguments to DW.</p>
|
||||
<p>You can also use DB and DW without arguments. This works exactly like “DS 1” and “DS 2” respectively. Consequently DB and DW can be used in a BSS/HRAM/VRAM section.</p>
|
||||
<p>You can also use DB and DW without arguments. This works exactly like “DS 1” and “DS 2” respectively. Consequently DB and DW can be used in a WRAM0/WRAMX/HRAM/VRAM/SRAM section.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
<li><a href="expr_fix.htm">Fixed-point expressions and functions</a>
|
||||
<li><a href="expr_str.htm">String expressions, functions and formatting</a>
|
||||
<li><a href="ds.htm">Declaring variables in a BSS section</a>
|
||||
<li><a href="ds.htm">Declaring variables in a RAM section</a>
|
||||
<li><a href="miscfunc.htm">Other functions</a>
|
||||
</ul>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>DS</h1>
|
||||
<p><dfn>DS</dfn> allocates a number of bytes. The content is undefined. This is the preferred method of allocationg space in a <a href="section.htm">BSS section</a>. You can however also use DB and DW without any arguments.</p>
|
||||
<p><dfn>DS</dfn> allocates a number of bytes. The content is undefined. This is the preferred method of allocationg space in a <a href="section.htm">RAM section</a>. You can however also use DB and DW without any arguments.</p>
|
||||
<pre>DS str_SIZEOF ;allocate str_SIZEOF bytes</pre>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
|
||||
@@ -8,47 +8,54 @@
|
||||
<body>
|
||||
<h1>SECTION</h1>
|
||||
<p>Before you can start writing code you must define a section. This tells the assembler what kind of data follows and if it is code where to put it.</p>
|
||||
<pre>SECTION "CoolStuff",CODE</pre>
|
||||
<pre>SECTION "CoolStuff",ROMX</pre>
|
||||
<p>This switches to the section called <b>"CoolStuff"</b> (or creates it if it doesn't already exits) and it defines it as a code section. All sections within a sourcefile must be identified by a <em>unique</em> name.</p>
|
||||
<table>
|
||||
<caption>Section types</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Function</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>CODE</td>
|
||||
<td>A code section. The linker decides where to put this. For the Gameboy it also decides which bank to put it in except #0 (the HOME bank).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DATA</td>
|
||||
<td>Really just a synonym for CODE.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>BSS</td>
|
||||
<td>This section is for variables. For the Gameboy it will be placed where the Gameboy RAM is.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HOME</td>
|
||||
<td>Gameboy ONLY: A code section that will be placed in Gameboy bank #0.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>VRAM</td>
|
||||
<td>Gameboy ONLY: This section is for allocating VRAM and will be placed where the Gameboy VRAM is.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HRAM</td>
|
||||
<td>Gameboy ONLY: This section is for allocating variables in the high RAM area ($FF80-$FFFE) and will be placed there. Suggested by Jens Ch. Restemeier. NOTE WELL: if you use this method of allocating HRAM the assembler will NOT choose the short addressingmode in the LD instruction because the actual address calculation is done by the linker! If you find this undesirable you can use <a href="rs.htm">RSSET/RB/RW</a> instead or use the LDIO mnemonic. The address calculation is then done by the assembler.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>Possible section types are as follows:
|
||||
|
||||
<dl>
|
||||
<dt>ROM0</dt>
|
||||
<dd>A ROM section. Mapped to memory at $0000–$3fff.</dd>
|
||||
|
||||
<dt>ROMX</dt>
|
||||
<dd>A banked ROM section. Mapped to memory at $4000–$7fff. Valid banks range from 1 to 511.</dd>
|
||||
|
||||
<dt>VRAM</dt>
|
||||
<dd>A banked video RAM section. Mapped to memory at $8000–$9fff. Can only allocate memory, not fill it. Valid banks range from 0 to 1.</dd>
|
||||
|
||||
<dt>SRAM</dt>
|
||||
<dd>A banked external (save) RAM section. Mapped to memory at $a000–$bfff. Can only allocate memory, not fill it. Valid banks range from 0 to 3.</dd>
|
||||
|
||||
<dt>WRAM0</dt>
|
||||
<dd>A general-purpose RAM section. Mapped to memory at $c000–$cfff. Can only allocate memory, not fill it.</dd>
|
||||
|
||||
<dt>WRAMX</dt>
|
||||
<dd>A banked general-purpose RAM section. Mapped to memory at $d000–$dfff. Can only allocate memory, not fill it. Valid banks range from 1 to 7.</dd>
|
||||
|
||||
<dt>HRAM</dt>
|
||||
<dd>A high RAM section. Mapped to memory at $ff80–$fffe. Can only allocate memory, not fill it. NOTE WELL: if you use this method of allocating HRAM the assembler will NOT choose the short addressingmode in the LD instruction because the actual address calculation is done by the linker! If you find this undesirable you can use <a href="rs.htm">RSSET/RB/RW</a> instead or use the LDIO mnemonic. The address calculation is then done by the assembler.</dd>
|
||||
</dl>
|
||||
|
||||
<p>The following deprecated section names are aliases for some of the above sections:
|
||||
|
||||
<dl>
|
||||
<dt>HOME</dt>
|
||||
<dd>Alias for ROM0.</dd>
|
||||
|
||||
<dt>CODE</dt>
|
||||
<dt>DATA</dt>
|
||||
<dd>Alias for ROMX.</dd>
|
||||
|
||||
<dt>BSS</dt>
|
||||
<dd>Alias for WRAM0.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Due to quite a lot of emails requesting an ORG directive you can now add an address to the sectiontype for the Gameboy:</p>
|
||||
<pre>SECTION "CoolStuff",HOME[$1234]</pre>
|
||||
<p>This will force the section to address $1234. This also works with the other sectiontypes. For CODE/DATA sections the linker will then place the section in any bank at the address you specify. If you also want to specify the bank you can do:</p>
|
||||
<pre>SECTION "CoolStuff",DATA[$4567],BANK[3]</pre>
|
||||
<pre>SECTION "CoolStuff",ROM0[$1234]</pre>
|
||||
<p>This will force the section to address $1234. This also works with the other sectiontypes. For ROMX sections the linker will then place the section in any bank at the address you specify. If you also want to specify the bank you can do:</p>
|
||||
<pre>SECTION "CoolStuff",ROMX[$4567],BANK[3]</pre>
|
||||
<p>And if you only want to force the section into a certain bank, and not it's position within the bank, that's also possible:</p>
|
||||
<pre>SECTION "CoolStuff",CODE,BANK[7]</pre>
|
||||
<pre>SECTION "CoolStuff",ROMX,BANK[7]</pre>
|
||||
<p><strong>HINT:</strong> If you think this is a lot of typing for doing a simple ORG type thing you can quite easily write an intelligent macro (called ORG for example) that uses <a href="expr_str.htm">\@</a> for the sectionname and determines correct sectiontype etc as arguments for SECTION</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
@@ -58,6 +65,6 @@
|
||||
<li><a href="pops.htm">POPS and PUSHS:</a> The section stack.
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated <EFBFBD>18 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
<p>Last updated 18 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
<li><a href="geninfo.htm">ASMotor General Information</a>
|
||||
<li><a href="asm.htm">xASM Documentation</a>
|
||||
<li><a href="link.htm">xLink Documentation</a>
|
||||
<li><a href="lib.htm">xLib Documentation</a>
|
||||
<li><a href="fix.htm">RGBFix Documentation</a>
|
||||
<li><a href="rgb0.htm">The RGB0-2 ObjectFileFormat</a>
|
||||
</ul>
|
||||
|
||||
47
doc/lib.htm
47
doc/lib.htm
@@ -1,47 +0,0 @@
|
||||
<!DOCTYPE HTML PUBliC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
|
||||
<title>xLib</title>
|
||||
<link rel="stylesheet" type="text/css" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>xLib Documentation</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#history"> History</A>
|
||||
<li><a href="#usage"> Usage</A>
|
||||
<li><a href="#commands"> The commands</A>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2 id="history">History</h2>
|
||||
<table>
|
||||
<caption>The history of xLib</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Version</th>
|
||||
<th scope="col">Dated</th>
|
||||
<th scope="col">Release notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>1.0</td>
|
||||
<td>21 Sep. 1997</td>
|
||||
<td>First release</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2 id="usage">Usage</h2>
|
||||
<pre> xlib library command [module1 module2 ... modulen]</pre>
|
||||
<h2 id="commands">The Commands</h2>
|
||||
<p>The <b>command</b> specified after <b>library</b> on the <a href="#Usage">commandline</a> tells xLib what to do.
|
||||
<p>The following commands are available:
|
||||
<ul>
|
||||
<li>a — Adds (or replaces if already present) the modules to the library
|
||||
<li>d — Deletes the modules specified from the library
|
||||
<li>l — Lists the library contents
|
||||
<li>x — Extracts the modules from the library
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 September 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
17
doc/link.htm
17
doc/link.htm
@@ -104,27 +104,14 @@
|
||||
<p>A line starting with # is ignored.
|
||||
<p>If you use libraries they will only be included if one of the objects actually reference them. This works on a SECTION level and not on a module level. This means that when you write libraries you can put each subroutine in its own SECTION so only the relevant bits are included.
|
||||
<h2 id="operationtg">Operation for Gameboy (-tg)</h2>
|
||||
<p><a href="asm.htm#sections">Sections</a> created with <b>HOME</b> in the assembler are placed in the GB bank #0 (the fixed bank $0000-$3FFF) in the order they are loaded from the objectfiles specified in the linkfile. So you want the first file in the linkfile to contain your header. <b>CODE/DATA</b> sections are placed in <em>any bank other than #0</em>. This means you have absolutely <em>no</em> control over which sections goes where. This insures minimal slack (unused bytes) at the end of each bank in the image.
|
||||
<p><a href="asm.htm#sections">Sections</a> created with <b>ROM0</b> in the assembler are placed in the GB bank #0 (the fixed bank $0000-$3FFF) in the order they are loaded from the objectfiles specified in the linkfile. So you want the first file in the linkfile to contain your header. <b>ROMX</b> sections are placed in <em>any bank other than #0</em>. This means you have absolutely <em>no</em> control over which sections goes where. This insures minimal slack (unused bytes) at the end of each bank in the image.
|
||||
<p>Currently the linker doesn't calculate the GB checksums.
|
||||
You must use <a href="fix.htm">RGBFix</a> to do this.
|
||||
|
||||
<h3 id="smallmode">Operation for Gameboy small mode (-ts)</h3>
|
||||
<p>Small mode forces all <b>DATA/CODE</b> sections to be of type <b>HOME</b> and increases the <b>HOME</b> section size from 16kB to 32kB. This also means that <b>CODE/DATA/HOME</b> sections are written to the final image in the order you have specified in the linkfile.
|
||||
<p>Small mode forces all <b>ROMX</b> sections to be of type <b>ROM0</b> and increases the <b>ROM0</b> section size from 16kB to 32kB. This also means that <b>ROM0/ROMX</b> sections are written to the final image in the order you have specified on the command line.
|
||||
<p>Currently the linker doesn't calculate the GB checksums. You must use <a href="fix.htm">RGBFix</a> to do this.
|
||||
|
||||
<h2 id="psion2">Operation for Psion2 relocatable modules (-tp)</h2>
|
||||
<p>This is a fileformat for the Psion2 that allows you to load your code into where ever there's any free space. The only sections types allowed are <b>HOME, DATA and BSS</b>. All CODE and DATA sections are written to the output file in the order specified in the linkfile. The BSS are actually then expanded to DATA sections filled with zeroes and appended. This might change later.
|
||||
<p>The file looks like this (all values are big endian):
|
||||
<pre>
|
||||
LONG NumberOfDataBytes
|
||||
REPT NumberOfDataBytes
|
||||
DB x
|
||||
ENDR
|
||||
LONG NumberOfPatches
|
||||
REPT NumberOfPatches
|
||||
LONG x ; A value to add to the word at address x in the code
|
||||
ENDR
|
||||
</pre>
|
||||
<hr>
|
||||
<p>Last updated 08 October 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
|
||||
10
doc/rgb0.htm
10
doc/rgb0.htm
@@ -50,10 +50,10 @@
|
||||
|
||||
REPT NumberOfSections
|
||||
LONG Size ;Size in bytes of this section
|
||||
BYTE Type ;0 = BSS
|
||||
BYTE Type ;0 = WRAM0
|
||||
;1 = VRAM
|
||||
;2 = CODE
|
||||
;3 = HOME
|
||||
;2 = ROMX
|
||||
;3 = ROM0
|
||||
;4 = HRAM
|
||||
LONG Org ;Only present in RGB1. Address to fix this
|
||||
;section at. -1 if the linker should
|
||||
@@ -61,8 +61,8 @@
|
||||
LONG Bank ;Only present in RGB1. Bank to load this
|
||||
;section into. -1 if the linker should
|
||||
;decide (normal operation). This field is
|
||||
;only valid for CODE sections.
|
||||
IF Type==CODE || Type==HOME
|
||||
;only valid for ROMX sections.
|
||||
IF Type==ROMX || Type==ROM0
|
||||
BYTE Data[Size]
|
||||
LONG NumberOfPatches
|
||||
|
||||
|
||||
@@ -6,18 +6,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASMOTOR_ASM_ASM_H
|
||||
#define ASMOTOR_ASM_ASM_H
|
||||
#ifndef RGBDS_ASM_ASM_H
|
||||
#define RGBDS_ASM_ASM_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
#include "asm/symbol.h"
|
||||
|
||||
#include "localasm.h"
|
||||
|
||||
#include "asmotor.h"
|
||||
#include "asm/localasm.h"
|
||||
|
||||
extern SLONG nLineNo;
|
||||
extern ULONG nTotalLines;
|
||||
@@ -28,9 +27,9 @@ extern char tzCurrentFileName[_MAX_PATH + 1];
|
||||
extern struct Section *pCurrentSection;
|
||||
extern struct sSymbol *tHashedSymbols[HASHSIZE];
|
||||
extern struct sSymbol *pPCSymbol;
|
||||
extern UBYTE oDontExpandStrings;
|
||||
extern bool oDontExpandStrings;
|
||||
|
||||
#define MAXMACROARGS 9
|
||||
#define MAXMACROARGS 256
|
||||
#define MAXINCPATHS 16
|
||||
|
||||
#endif /* // ASM_H */
|
||||
|
||||
18
include/asm/charmap.h
Normal file
18
include/asm/charmap.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef RGBDS_ASM_CHARMAP_H
|
||||
#define RGBDS_ASM_CHARMAP_H
|
||||
|
||||
#define MAXCHARMAPS 512
|
||||
#define CHARMAPLENGTH 8
|
||||
|
||||
struct Charmap {
|
||||
int count;
|
||||
char input[MAXCHARMAPS][CHARMAPLENGTH + 1];
|
||||
char output[MAXCHARMAPS];
|
||||
};
|
||||
|
||||
int readUTF8Char(char *destination, char *source);
|
||||
void charmap_Sort();
|
||||
int charmap_Add(char *input, UBYTE output);
|
||||
int charmap_Convert(char **input);
|
||||
|
||||
#endif
|
||||
@@ -6,11 +6,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASMOTOR_ASM_FSTACK_H
|
||||
#define ASMOTOR_ASM_FSTACK_H
|
||||
#ifndef RGBDS_ASM_FSTACK_H
|
||||
#define RGBDS_ASM_FSTACK_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "asm/asm.h"
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
#include "asm/lexer.h"
|
||||
|
||||
struct sContext {
|
||||
@@ -27,14 +29,17 @@ struct sContext {
|
||||
ULONG nREPTBlockSize;
|
||||
};
|
||||
|
||||
extern ULONG fstk_RunInclude(char *s);
|
||||
void
|
||||
fstk_RunInclude(char *);
|
||||
extern void fstk_RunMacroArg(SLONG s);
|
||||
extern ULONG fstk_Init(char *s);
|
||||
void
|
||||
fstk_Init(char *);
|
||||
extern void fstk_Dump(void);
|
||||
extern void fstk_AddIncludePath(char *s);
|
||||
extern ULONG fstk_RunMacro(char *s);
|
||||
extern void fstk_RunRept(ULONG count);
|
||||
extern void fstk_FindFile(char *s);
|
||||
FILE *
|
||||
fstk_FindFile(char *);
|
||||
|
||||
extern int yywrap(void);
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#ifndef ASMOTOR_ASM_LEXER_H
|
||||
#define ASMOTOR_ASM_LEXER_H
|
||||
#ifndef RGBDS_ASM_LEXER_H
|
||||
#define RGBDS_ASM_LEXER_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
|
||||
#define LEXHASHSIZE 512
|
||||
#define LEXHASHSIZE (1 << 11)
|
||||
#define MAXSTRLEN 255
|
||||
|
||||
struct sLexInitString {
|
||||
char *tzName;
|
||||
@@ -18,7 +19,9 @@ struct sLexFloat {
|
||||
};
|
||||
|
||||
struct yy_buffer_state {
|
||||
char *pBufferStart;
|
||||
char *pBufferRealStart; // actual starting address
|
||||
char *pBufferStart; // address where the data is initially written
|
||||
// after the "safety margin"
|
||||
char *pBuffer;
|
||||
ULONG nBufferSize;
|
||||
ULONG oAtLineStart;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#ifndef ASMOTOR_MAIN_H
|
||||
#define ASMOTOR_MAIN_H
|
||||
#ifndef RGBDS_MAIN_H
|
||||
#define RGBDS_MAIN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct sOptions {
|
||||
char gbgfx[4];
|
||||
char binary[2];
|
||||
SLONG fillchar;
|
||||
bool verbose;
|
||||
bool haltnop;
|
||||
//-1 == random
|
||||
};
|
||||
|
||||
@@ -19,10 +23,8 @@ extern void opt_Push(void);
|
||||
extern void opt_Pop(void);
|
||||
extern void opt_Parse(char *s);
|
||||
|
||||
void fatalerror(char *s);
|
||||
void yyerror(char *s);
|
||||
|
||||
extern char temptext[1024];
|
||||
void fatalerror(const char *fmt, ...);
|
||||
void yyerror(const char *fmt, ...);
|
||||
|
||||
#define YY_FATAL_ERROR fatalerror
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef ASMOTOR_ASM_LINK_H
|
||||
#define ASMOTOR_ASM_LINK_H
|
||||
#ifndef RGBDS_ASM_LINK_H
|
||||
#define RGBDS_ASM_LINK_H
|
||||
|
||||
/* RGB0 .obj format:
|
||||
*
|
||||
@@ -30,7 +30,7 @@
|
||||
* Section:
|
||||
* LONG SizeInBytes
|
||||
* char Type
|
||||
* if( Type!=BSS )
|
||||
* if( Type!=WRAM0 )
|
||||
* {
|
||||
* char Data[SizeInBytes]
|
||||
* Patches
|
||||
@@ -95,11 +95,13 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
SECT_BSS = 0,
|
||||
SECT_WRAM0 = 0,
|
||||
SECT_VRAM,
|
||||
SECT_CODE,
|
||||
SECT_HOME,
|
||||
SECT_HRAM
|
||||
SECT_ROMX,
|
||||
SECT_ROM0,
|
||||
SECT_HRAM,
|
||||
SECT_WRAMX,
|
||||
SECT_SRAM
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef ASMOTOR_ASM_MATH_H
|
||||
#define ASMOTOR_ASM_MATH_H
|
||||
#ifndef RGBDS_ASM_MATH_H
|
||||
#define RGBDS_ASM_MATH_H
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
|
||||
void math_DefinePI(void);
|
||||
void math_Print(SLONG i);
|
||||
@@ -14,5 +14,8 @@ SLONG math_ATan(SLONG i);
|
||||
SLONG math_ATan2(SLONG i, SLONG j);
|
||||
SLONG math_Mul(SLONG i, SLONG j);
|
||||
SLONG math_Div(SLONG i, SLONG j);
|
||||
SLONG math_Round(SLONG i);
|
||||
SLONG math_Ceil(SLONG i);
|
||||
SLONG math_Floor(SLONG i);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef ASMOTOR_ASM_OUTPUT_H
|
||||
#define ASMOTOR_ASM_OUTPUT_H
|
||||
#ifndef RGBDS_ASM_OUTPUT_H
|
||||
#define RGBDS_ASM_OUTPUT_H
|
||||
|
||||
#include "asm/rpn.h"
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
|
||||
struct Section {
|
||||
char *pzName;
|
||||
@@ -12,6 +12,7 @@ struct Section {
|
||||
ULONG nBank;
|
||||
struct Section *pNext;
|
||||
struct Patch *pPatches;
|
||||
struct Charmap *charmap;
|
||||
UBYTE *tData;
|
||||
};
|
||||
|
||||
@@ -20,12 +21,14 @@ void out_SetFileName(char *s);
|
||||
void out_NewSection(char *pzName, ULONG secttype);
|
||||
void out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank);
|
||||
void out_AbsByte(int b);
|
||||
void out_AbsByteGroup(char *s, int length);
|
||||
void out_RelByte(struct Expression * expr);
|
||||
void out_RelWord(struct Expression * expr);
|
||||
void out_PCRelByte(struct Expression * expr);
|
||||
void out_WriteObject(void);
|
||||
void out_Skip(int skip);
|
||||
void out_BinaryFile(char *s);
|
||||
void out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length);
|
||||
void out_String(char *s);
|
||||
void out_AbsLong(SLONG b);
|
||||
void out_RelLong(struct Expression * expr);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef ASMOTOR_ASM_RPN_H
|
||||
#define ASMOTOR_ASM_RPN_H
|
||||
#ifndef RGBDS_ASM_RPN_H
|
||||
#define RGBDS_ASM_RPN_H
|
||||
|
||||
struct Expression {
|
||||
SLONG nVal;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef ASMOTOR_SYMBOL_H
|
||||
#define ASMOTOR_SYMBOL_H
|
||||
#ifndef RGBDS_SYMBOL_H
|
||||
#define RGBDS_SYMBOL_H
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
|
||||
#define HASHSIZE 73
|
||||
#define HASHSIZE (1 << 16)
|
||||
#define MAXSYMLEN 256
|
||||
|
||||
struct sSymbol {
|
||||
@@ -35,6 +35,7 @@ struct sSymbol {
|
||||
#define SYMF_CONST 0x200 /* symbol has a constant value, will
|
||||
* not be changed during linking */
|
||||
|
||||
ULONG calchash(char *s);
|
||||
void sym_PrepPass1(void);
|
||||
void sym_PrepPass2(void);
|
||||
void sym_AddLocalReloc(char *tzSym);
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef ASMOTOR_ASM_TYPES_H
|
||||
#define ASMOTOR_ASM_TYPES_H
|
||||
|
||||
#if defined(AMIGA) || defined(__GNUC__)
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
|
||||
typedef unsigned char UBYTE;
|
||||
typedef signed char SBYTE;
|
||||
typedef unsigned short UWORD;
|
||||
typedef signed short SWORD;
|
||||
typedef unsigned long ULONG;
|
||||
typedef signed long SLONG;
|
||||
|
||||
#endif
|
||||
@@ -1,21 +0,0 @@
|
||||
/* asmotor.h
|
||||
*
|
||||
* Contains defines for every program in the ASMotor package
|
||||
*
|
||||
* Copyright 1997 Carsten Sorensen
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ASMOTOR_ASMOTOR_H
|
||||
#define ASMOTOR_ASMOTOR_H
|
||||
|
||||
#define ASMOTOR
|
||||
|
||||
#define ASMOTOR_VERSION "1.10-linux"
|
||||
|
||||
#define ASM_VERSION "1.08c"
|
||||
#define LINK_VERSION "1.06c"
|
||||
#define RGBFIX_VERSION "1.02"
|
||||
#define LIB_VERSION "1.00"
|
||||
|
||||
#endif
|
||||
33
include/extern/err.h
vendored
Normal file
33
include/extern/err.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef EXTERN_ERR_H
|
||||
#define EXTERN_ERR_H
|
||||
|
||||
#ifdef ERR_IN_LIBC
|
||||
#include <err.h>
|
||||
#else
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "extern/stdnoreturn.h"
|
||||
|
||||
#define warn rgbds_warn
|
||||
#define vwarn rgbds_vwarn
|
||||
#define warnx rgbds_warnx
|
||||
#define vwarnx rgbds_vwarnx
|
||||
|
||||
#define err rgbds_err
|
||||
#define verr rgbds_verr
|
||||
#define errx rgbds_errx
|
||||
#define verrx rgbds_verrx
|
||||
|
||||
void warn(const char *, ...);
|
||||
void vwarn(const char *, va_list);
|
||||
void warnx(const char *, ...);
|
||||
void vwarnx(const char *, va_list);
|
||||
|
||||
noreturn void err(int, const char *, ...);
|
||||
noreturn void verr(int, const char *, va_list);
|
||||
noreturn void errx(int, const char *, ...);
|
||||
noreturn void verrx(int, const char *, va_list);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
14
include/extern/reallocarray.h
vendored
Normal file
14
include/extern/reallocarray.h
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef EXTERN_REALLOCARRAY_H
|
||||
#define EXTERN_REALLOCARRAY_H
|
||||
|
||||
#ifdef REALLOCARRAY_IN_LIBC
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
|
||||
#define reallocarray rgbds_reallocarray
|
||||
|
||||
void *reallocarray(void *, size_t, size_t);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
16
include/extern/stdnoreturn.h
vendored
Normal file
16
include/extern/stdnoreturn.h
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
/* C11 or newer */
|
||||
#define noreturn _Noreturn
|
||||
#elif __cplusplus >= 201103L
|
||||
/* C++11 or newer */
|
||||
#define noreturn [[noreturn]]
|
||||
#elif __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ >= 5))
|
||||
/* GCC 2.5 or newer */
|
||||
#define noreturn __attribute__ ((noreturn))
|
||||
#elif _MSC_VER >= 1310
|
||||
/* MS Visual Studio 2003/.NET Framework 1.1 or newer */
|
||||
#define noreturn _declspec( noreturn)
|
||||
#else
|
||||
/* unsupported, but no need to throw a fit */
|
||||
#define noreturn
|
||||
#endif
|
||||
13
include/extern/strl.h
vendored
Normal file
13
include/extern/strl.h
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#ifndef STRL_H
|
||||
#define STRL_H
|
||||
|
||||
#ifdef STRL_IN_LIBC
|
||||
#include <string.h>
|
||||
#else
|
||||
#define strlcpy rgbds_strlcpy
|
||||
#define strlcat rgbds_strlcat
|
||||
size_t strlcpy(char *, const char *, size_t);
|
||||
size_t strlcat(char *, const char *, size_t);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,13 +0,0 @@
|
||||
#ifndef ASMOTOR_LIB_LIBRARY_H
|
||||
#define ASMOTOR_LIB_LIBRARY_H
|
||||
|
||||
#include "lib/libwrap.h"
|
||||
|
||||
extern sLibrary *lib_Read(char *filename);
|
||||
extern BBOOL lib_Write(sLibrary * lib, char *filename);
|
||||
extern sLibrary *lib_AddReplace(sLibrary * lib, char *filename);
|
||||
extern void lib_Free(sLibrary * lib);
|
||||
extern sLibrary *lib_DeleteModule(sLibrary * lib, char *filename);
|
||||
extern sLibrary *lib_Find(sLibrary * lib, char *filename);
|
||||
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
#ifndef ASMOTOR_LIB_LIBWRAP_H
|
||||
#define ASMOTOR_LIB_LIBWRAP_H
|
||||
|
||||
#include "lib/types.h"
|
||||
|
||||
#define MAXNAMELENGTH 256
|
||||
|
||||
struct LibraryWrapper {
|
||||
char tName[MAXNAMELENGTH];
|
||||
UWORD uwTime;
|
||||
UWORD uwDate;
|
||||
SLONG nByteLength;
|
||||
UBYTE *pData;
|
||||
struct LibraryWrapper *pNext;
|
||||
};
|
||||
|
||||
typedef struct LibraryWrapper sLibrary;
|
||||
|
||||
#endif
|
||||
@@ -1,15 +1,17 @@
|
||||
#ifndef ASMOTOR_LINK_ASSIGN_H
|
||||
#define ASMOTOR_LINK_ASSIGN_H
|
||||
#ifndef RGBDS_LINK_ASSIGN_H
|
||||
#define RGBDS_LINK_ASSIGN_H
|
||||
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
enum eBankDefine {
|
||||
BANK_HOME = 0,
|
||||
BANK_BSS = 256,
|
||||
BANK_VRAM,
|
||||
BANK_HRAM
|
||||
BANK_ROM0 = 0,
|
||||
BANK_WRAM0 = 512,
|
||||
BANK_WRAMX,
|
||||
BANK_VRAM = 520,
|
||||
BANK_HRAM = 522,
|
||||
BANK_SRAM = 523
|
||||
};
|
||||
#define MAXBANKS 259
|
||||
#define MAXBANKS 527
|
||||
|
||||
extern SLONG area_Avail(SLONG bank);
|
||||
extern void AssignSections(void);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef ASMOTOR_LINK_LIBRARY_H
|
||||
#define ASMOTOR_LINK_LIBRARY_H
|
||||
#ifndef RGBDS_LINK_LIBRARY_H
|
||||
#define RGBDS_LINK_LIBRARY_H
|
||||
|
||||
extern void AddNeededModules(void);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef ASMOTOR_LINK_MAIN_H
|
||||
#define ASMOTOR_LINK_MAIN_H
|
||||
#ifndef RGBDS_LINK_MAIN_H
|
||||
#define RGBDS_LINK_MAIN_H
|
||||
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
extern SLONG fillchar;
|
||||
extern char smartlinkstartsymbol[256];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef ASMOTOR_LINK_MAPFILE_H
|
||||
#define ASMOTOR_LINK_MAPFILE_H
|
||||
#ifndef RGBDS_LINK_MAPFILE_H
|
||||
#define RGBDS_LINK_MAPFILE_H
|
||||
|
||||
extern void SetMapfileName(char *name);
|
||||
extern void SetSymfileName(char *name);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#ifndef ASMOTOR_LINK_LINK_H
|
||||
#define ASMOTOR_LINK_LINK_H
|
||||
#ifndef RGBDS_LINK_LINK_H
|
||||
#define RGBDS_LINK_LINK_H
|
||||
|
||||
#if defined(AMIGA) || defined(__GNUC__)
|
||||
#ifndef _MAX_PATH
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
extern SLONG options;
|
||||
#define OPT_SMALL 0x01
|
||||
@@ -51,11 +51,13 @@ enum eRpnData {
|
||||
};
|
||||
|
||||
enum eSectionType {
|
||||
SECT_BSS,
|
||||
SECT_WRAM0,
|
||||
SECT_VRAM,
|
||||
SECT_CODE,
|
||||
SECT_HOME,
|
||||
SECT_HRAM
|
||||
SECT_ROMX,
|
||||
SECT_ROM0,
|
||||
SECT_HRAM,
|
||||
SECT_WRAMX,
|
||||
SECT_SRAM
|
||||
};
|
||||
|
||||
struct sSection {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef ASMOTOR_LINK_OBJECT_H
|
||||
#define ASMOTOR_LINK_OBJECT_H
|
||||
#ifndef RGBDS_LINK_OBJECT_H
|
||||
#define RGBDS_LINK_OBJECT_H
|
||||
|
||||
extern void obj_Readfile(char *tzObjectfile);
|
||||
extern void lib_Readfile(char *tzLibfile);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef ASMOTOR_LINK_OUTPUT_H
|
||||
#define ASMOTOR_LINK_OUTPUT_H
|
||||
#ifndef RGBDS_LINK_OUTPUT_H
|
||||
#define RGBDS_LINK_OUTPUT_H
|
||||
|
||||
void out_Setname(char *tzOutputfile);
|
||||
void Output(void);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef ASMOTOR_LINK_PATCH_H
|
||||
#define ASMOTOR_LINK_PATCH_H
|
||||
#ifndef RGBDS_LINK_PATCH_H
|
||||
#define RGBDS_LINK_PATCH_H
|
||||
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
void Patch(void);
|
||||
extern SLONG nPC;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef ASMOTOR_LINK_SYMBOL_H
|
||||
#define ASMOTOR_LINK_SYMBOL_H
|
||||
#ifndef RGBDS_LINK_SYMBOL_H
|
||||
#define RGBDS_LINK_SYMBOL_H
|
||||
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
void sym_Init(void);
|
||||
void sym_CreateSymbol(char *tzName, SLONG nValue, SBYTE nBank);
|
||||
void sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank);
|
||||
SLONG sym_GetValue(char *tzName);
|
||||
SLONG sym_GetBank(char *tzName);
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef ASMOTOR_LINK_TYPES_H
|
||||
#define ASMOTOR_LINK_TYPES_H
|
||||
|
||||
#if defined(AMIGA) || defined(__GNUC__)
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
|
||||
typedef unsigned char UBYTE;
|
||||
typedef signed char SBYTE;
|
||||
typedef unsigned short UWORD;
|
||||
typedef signed short SWORD;
|
||||
typedef unsigned long ULONG;
|
||||
typedef signed long SLONG;
|
||||
typedef signed char BBOOL;
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef ASMOTOR_LIB_TYPES_H
|
||||
#define ASMOTOR_LIB_TYPES_H
|
||||
#ifndef RGBDS_TYPES_H
|
||||
#define RGBDS_TYPES_H
|
||||
|
||||
#if defined(AMIGA) || defined(__GNUC__)
|
||||
#ifndef _MAX_PATH
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
|
||||
1
src/asm/.gitignore
vendored
1
src/asm/.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
asmy.c
|
||||
asmy.h
|
||||
asmy.y
|
||||
|
||||
466
src/asm/alloca.c
466
src/asm/alloca.c
@@ -1,466 +0,0 @@
|
||||
/* alloca.c -- allocate automatically reclaimed memory
|
||||
(Mostly) portable public-domain implementation -- D A Gwyn
|
||||
|
||||
This implementation of the PWB library alloca function,
|
||||
which is used to allocate space off the run-time stack so
|
||||
that it is automatically reclaimed upon procedure exit,
|
||||
was inspired by discussions with J. Q. Johnson of Cornell.
|
||||
J.Otto Tennant <jot@cray.com> contributed the Cray support.
|
||||
|
||||
There are some preprocessor constants that can
|
||||
be defined when compiling for your specific system, for
|
||||
improved efficiency; however, the defaults should be okay.
|
||||
|
||||
The general concept of this implementation is to keep
|
||||
track of all alloca-allocated blocks, and reclaim any
|
||||
that are found to be deeper in the stack than the current
|
||||
invocation. This heuristic does not reclaim storage as
|
||||
soon as it becomes invalid, but it will do so eventually.
|
||||
|
||||
As a special case, alloca(0) reclaims storage without
|
||||
allocating any. It is a good idea to use alloca(0) in
|
||||
your main control loop, etc. to force garbage collection. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef emacs
|
||||
#include "blockinput.h"
|
||||
#endif
|
||||
|
||||
/* If compiling with GCC 2, this file's not needed. */
|
||||
#if !defined (__GNUC__) || __GNUC__ < 2
|
||||
|
||||
/* If someone has defined alloca as a macro,
|
||||
there must be some other way alloca is supposed to work. */
|
||||
#ifndef alloca
|
||||
|
||||
#ifdef emacs
|
||||
#ifdef static
|
||||
/* actually, only want this if static is defined as ""
|
||||
-- this is for usg, in which emacs must undefine static
|
||||
in order to make unexec workable
|
||||
*/
|
||||
#ifndef STACK_DIRECTION
|
||||
you lose-- must know STACK_DIRECTION at compile - time
|
||||
#endif /* STACK_DIRECTION undefined */
|
||||
#endif /* static */
|
||||
#endif /* emacs */
|
||||
/* If your stack is a linked list of frames, you have to
|
||||
provide an "address metric" ADDRESS_FUNCTION macro. */
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
long i00afunc();
|
||||
#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg))
|
||||
#else
|
||||
#define ADDRESS_FUNCTION(arg) &(arg)
|
||||
#endif
|
||||
#if __STDC__
|
||||
typedef void *pointer;
|
||||
#else
|
||||
typedef char *pointer;
|
||||
#endif
|
||||
|
||||
#define NULL 0
|
||||
|
||||
/* Different portions of Emacs need to call different versions of
|
||||
malloc. The Emacs executable needs alloca to call xmalloc, because
|
||||
ordinary malloc isn't protected from input signals. On the other
|
||||
hand, the utilities in lib-src need alloca to call malloc; some of
|
||||
them are very simple, and don't have an xmalloc routine.
|
||||
|
||||
Non-Emacs programs expect this to call use xmalloc.
|
||||
|
||||
Callers below should use malloc. */
|
||||
|
||||
/* Carsten Sorensen 09/09/97
|
||||
* Commented out the following, I want malloc!
|
||||
#ifndef emacs
|
||||
#define malloc xmalloc
|
||||
#endif
|
||||
extern pointer malloc ();
|
||||
And added the following line:
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Define STACK_DIRECTION if you know the direction of stack
|
||||
growth for your system; otherwise it will be automatically
|
||||
deduced at run-time.
|
||||
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown */
|
||||
|
||||
#ifndef STACK_DIRECTION
|
||||
#define STACK_DIRECTION 0 /* Direction unknown. */
|
||||
#endif
|
||||
|
||||
#if STACK_DIRECTION != 0
|
||||
|
||||
#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */
|
||||
|
||||
#else /* STACK_DIRECTION == 0; need run-time code. */
|
||||
|
||||
static int stack_dir; /* 1 or -1 once known. */
|
||||
#define STACK_DIR stack_dir
|
||||
|
||||
static void
|
||||
find_stack_direction()
|
||||
{
|
||||
static char *addr = NULL; /* Address of first `dummy', once
|
||||
* known. */
|
||||
auto char dummy; /* To get stack address. */
|
||||
|
||||
if (addr == NULL) { /* Initial entry. */
|
||||
addr = ADDRESS_FUNCTION(dummy);
|
||||
|
||||
find_stack_direction(); /* Recurse once. */
|
||||
} else {
|
||||
/* Second entry. */
|
||||
if (ADDRESS_FUNCTION(dummy) > addr)
|
||||
stack_dir = 1; /* Stack grew upward. */
|
||||
else
|
||||
stack_dir = -1; /* Stack grew downward. */
|
||||
}
|
||||
}
|
||||
#endif /* STACK_DIRECTION == 0 */
|
||||
|
||||
/* An "alloca header" is used to:
|
||||
(a) chain together all alloca'ed blocks;
|
||||
(b) keep track of stack depth.
|
||||
|
||||
It is very important that sizeof(header) agree with malloc
|
||||
alignment chunk size. The following default should work okay. */
|
||||
|
||||
#ifndef ALIGN_SIZE
|
||||
#define ALIGN_SIZE sizeof(double)
|
||||
#endif
|
||||
|
||||
typedef union hdr {
|
||||
char align[ALIGN_SIZE]; /* To force sizeof(header). */
|
||||
struct {
|
||||
union hdr *next;/* For chaining headers. */
|
||||
char *deep; /* For stack depth measure. */
|
||||
} h;
|
||||
} header;
|
||||
|
||||
static header *last_alloca_header = NULL; /* -> last alloca header. */
|
||||
|
||||
/* Return a pointer to at least SIZE bytes of storage,
|
||||
which will be automatically reclaimed upon exit from
|
||||
the procedure that called alloca. Originally, this space
|
||||
was supposed to be taken from the current stack frame of the
|
||||
caller, but that method cannot be made to work for some
|
||||
implementations of C, for example under Gould's UTX/32. */
|
||||
|
||||
pointer
|
||||
alloca(size)
|
||||
unsigned size;
|
||||
{
|
||||
auto char probe; /* Probes stack depth: */
|
||||
register char *depth = ADDRESS_FUNCTION(probe);
|
||||
|
||||
#if STACK_DIRECTION == 0
|
||||
if (STACK_DIR == 0) /* Unknown growth direction. */
|
||||
find_stack_direction();
|
||||
#endif
|
||||
|
||||
/* Reclaim garbage, defined as all alloca'd storage that was allocated
|
||||
* from deeper in the stack than currently. */
|
||||
|
||||
{
|
||||
register header *hp; /* Traverses linked list. */
|
||||
|
||||
#ifdef emacs
|
||||
BLOCK_INPUT;
|
||||
#endif
|
||||
|
||||
for (hp = last_alloca_header; hp != NULL;)
|
||||
if ((STACK_DIR > 0 && hp->h.deep > depth)
|
||||
|| (STACK_DIR < 0 && hp->h.deep < depth)) {
|
||||
register header *np = hp->h.next;
|
||||
|
||||
free((pointer) hp); /* Collect garbage. */
|
||||
|
||||
hp = np; /* -> next header. */
|
||||
} else
|
||||
break; /* Rest are not deeper. */
|
||||
|
||||
last_alloca_header = hp; /* -> last valid storage. */
|
||||
|
||||
#ifdef emacs
|
||||
UNBLOCK_INPUT;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
return NULL; /* No allocation required. */
|
||||
|
||||
/* Allocate combined header + user data storage. */
|
||||
|
||||
{
|
||||
register pointer new = malloc(sizeof(header) + size);
|
||||
/* Address of header. */
|
||||
|
||||
((header *) new)->h.next = last_alloca_header;
|
||||
((header *) new)->h.deep = depth;
|
||||
|
||||
last_alloca_header = (header *) new;
|
||||
|
||||
/* User storage begins just after header. */
|
||||
|
||||
return (pointer) ((char *) new + sizeof(header));
|
||||
}
|
||||
}
|
||||
#if defined (CRAY) && defined (CRAY_STACKSEG_END)
|
||||
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifndef CRAY_STACK
|
||||
#define CRAY_STACK
|
||||
#ifndef CRAY2
|
||||
/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */
|
||||
struct stack_control_header {
|
||||
long shgrow:32; /* Number of times stack has grown. */
|
||||
long shaseg:32; /* Size of increments to stack. */
|
||||
long shhwm:32; /* High water mark of stack. */
|
||||
long shsize:32; /* Current size of stack (all segments). */
|
||||
};
|
||||
/* The stack segment linkage control information occurs at
|
||||
the high-address end of a stack segment. (The stack
|
||||
grows from low addresses to high addresses.) The initial
|
||||
part of the stack segment linkage control information is
|
||||
0200 (octal) words. This provides for register storage
|
||||
for the routine which overflows the stack. */
|
||||
|
||||
struct stack_segment_linkage {
|
||||
long ss[0200]; /* 0200 overflow words. */
|
||||
long sssize:32; /* Number of words in this segment. */
|
||||
long ssbase:32; /* Offset to stack base. */
|
||||
long:32;
|
||||
long sspseg:32; /* Offset to linkage control of previous
|
||||
* segment of stack. */
|
||||
long:32;
|
||||
long sstcpt:32; /* Pointer to task common address block. */
|
||||
long sscsnm; /* Private control structure number for
|
||||
* microtasking. */
|
||||
long ssusr1; /* Reserved for user. */
|
||||
long ssusr2; /* Reserved for user. */
|
||||
long sstpid; /* Process ID for pid based multi-tasking. */
|
||||
long ssgvup; /* Pointer to multitasking thread giveup. */
|
||||
long sscray[7]; /* Reserved for Cray Research. */
|
||||
long ssa0;
|
||||
long ssa1;
|
||||
long ssa2;
|
||||
long ssa3;
|
||||
long ssa4;
|
||||
long ssa5;
|
||||
long ssa6;
|
||||
long ssa7;
|
||||
long sss0;
|
||||
long sss1;
|
||||
long sss2;
|
||||
long sss3;
|
||||
long sss4;
|
||||
long sss5;
|
||||
long sss6;
|
||||
long sss7;
|
||||
};
|
||||
#else /* CRAY2 */
|
||||
/* The following structure defines the vector of words
|
||||
returned by the STKSTAT library routine. */
|
||||
struct stk_stat {
|
||||
long now; /* Current total stack size. */
|
||||
long maxc; /* Amount of contiguous space which would be
|
||||
* required to satisfy the maximum stack
|
||||
* demand to date. */
|
||||
long high_water; /* Stack high-water mark. */
|
||||
long overflows; /* Number of stack overflow ($STKOFEN) calls. */
|
||||
long hits; /* Number of internal buffer hits. */
|
||||
long extends; /* Number of block extensions. */
|
||||
long stko_mallocs; /* Block allocations by $STKOFEN. */
|
||||
long underflows; /* Number of stack underflow calls ($STKRETN). */
|
||||
long stko_free; /* Number of deallocations by $STKRETN. */
|
||||
long stkm_free; /* Number of deallocations by $STKMRET. */
|
||||
long segments; /* Current number of stack segments. */
|
||||
long maxs; /* Maximum number of stack segments so far. */
|
||||
long pad_size; /* Stack pad size. */
|
||||
long current_address; /* Current stack segment address. */
|
||||
long current_size; /* Current stack segment size. This number is
|
||||
* actually corrupted by STKSTAT to include
|
||||
* the fifteen word trailer area. */
|
||||
long initial_address; /* Address of initial segment. */
|
||||
long initial_size; /* Size of initial segment. */
|
||||
};
|
||||
/* The following structure describes the data structure which trails
|
||||
any stack segment. I think that the description in 'asdef' is
|
||||
out of date. I only describe the parts that I am sure about. */
|
||||
|
||||
struct stk_trailer {
|
||||
long this_address; /* Address of this block. */
|
||||
long this_size; /* Size of this block (does not include this
|
||||
* trailer). */
|
||||
long unknown2;
|
||||
long unknown3;
|
||||
long link; /* Address of trailer block of previous
|
||||
* segment. */
|
||||
long unknown5;
|
||||
long unknown6;
|
||||
long unknown7;
|
||||
long unknown8;
|
||||
long unknown9;
|
||||
long unknown10;
|
||||
long unknown11;
|
||||
long unknown12;
|
||||
long unknown13;
|
||||
long unknown14;
|
||||
};
|
||||
#endif /* CRAY2 */
|
||||
#endif /* not CRAY_STACK */
|
||||
|
||||
#ifdef CRAY2
|
||||
/* Determine a "stack measure" for an arbitrary ADDRESS.
|
||||
I doubt that "lint" will like this much. */
|
||||
|
||||
static long
|
||||
i00afunc(long *address)
|
||||
{
|
||||
struct stk_stat status;
|
||||
struct stk_trailer *trailer;
|
||||
long *block, size;
|
||||
long result = 0;
|
||||
|
||||
/* We want to iterate through all of the segments. The first step is
|
||||
* to get the stack status structure. We could do this more quickly
|
||||
* and more directly, perhaps, by referencing the $LM00 common block,
|
||||
* but I know that this works. */
|
||||
|
||||
STKSTAT(&status);
|
||||
|
||||
/* Set up the iteration. */
|
||||
|
||||
trailer = (struct stk_trailer *) (status.current_address
|
||||
+ status.current_size - 15);
|
||||
|
||||
/* There must be at least one stack segment. Therefore it is a fatal
|
||||
* error if "trailer" is null. */
|
||||
|
||||
if (trailer == 0)
|
||||
abort();
|
||||
|
||||
/* Discard segments that do not contain our argument address. */
|
||||
|
||||
while (trailer != 0) {
|
||||
block = (long *) trailer->this_address;
|
||||
size = trailer->this_size;
|
||||
if (block == 0 || size == 0)
|
||||
abort();
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
if ((block <= address) && (address < (block + size)))
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the result to the offset in this segment and add the sizes of
|
||||
* all predecessor segments. */
|
||||
|
||||
result = address - block;
|
||||
|
||||
if (trailer == 0) {
|
||||
return result;
|
||||
}
|
||||
do {
|
||||
if (trailer->this_size <= 0)
|
||||
abort();
|
||||
result += trailer->this_size;
|
||||
trailer = (struct stk_trailer *) trailer->link;
|
||||
}
|
||||
while (trailer != 0);
|
||||
|
||||
/* We are done. Note that if you present a bogus address (one not in
|
||||
* any segment), you will get a different number back, formed from
|
||||
* subtracting the address of the first block. This is probably not
|
||||
* what you want. */
|
||||
|
||||
return (result);
|
||||
}
|
||||
#else /* not CRAY2 */
|
||||
/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP.
|
||||
Determine the number of the cell within the stack,
|
||||
given the address of the cell. The purpose of this
|
||||
routine is to linearize, in some sense, stack addresses
|
||||
for alloca. */
|
||||
|
||||
static long
|
||||
i00afunc(long address)
|
||||
{
|
||||
long stkl = 0;
|
||||
|
||||
long size, pseg, this_segment, stack;
|
||||
long result = 0;
|
||||
|
||||
struct stack_segment_linkage *ssptr;
|
||||
|
||||
/* Register B67 contains the address of the end of the current stack
|
||||
* segment. If you (as a subprogram) store your registers on the
|
||||
* stack and find that you are past the contents of B67, you have
|
||||
* overflowed the segment.
|
||||
*
|
||||
* B67 also points to the stack segment linkage control area, which is
|
||||
* what we are really interested in. */
|
||||
|
||||
stkl = CRAY_STACKSEG_END();
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
|
||||
/* If one subtracts 'size' from the end of the segment, one has the
|
||||
* address of the first word of the segment.
|
||||
*
|
||||
* If this is not the first segment, 'pseg' will be nonzero. */
|
||||
|
||||
pseg = ssptr->sspseg;
|
||||
size = ssptr->sssize;
|
||||
|
||||
this_segment = stkl - size;
|
||||
|
||||
/* It is possible that calling this routine itself caused a stack
|
||||
* overflow. Discard stack segments which do not contain the target
|
||||
* address. */
|
||||
|
||||
while (!(this_segment <= address && address <= stkl)) {
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf(stderr, "%011o %011o %011o\n", this_segment, address,
|
||||
stkl);
|
||||
#endif
|
||||
if (pseg == 0)
|
||||
break;
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
this_segment = stkl - size;
|
||||
}
|
||||
|
||||
result = address - this_segment;
|
||||
|
||||
/* If you subtract pseg from the current end of the stack, you get the
|
||||
* address of the previous stack segment's end. This seems a little
|
||||
* convoluted to me, but I'll bet you save a cycle somewhere. */
|
||||
|
||||
while (pseg != 0) {
|
||||
#ifdef DEBUG_I00AFUNC
|
||||
fprintf(stderr, "%011o %011o\n", pseg, size);
|
||||
#endif
|
||||
stkl = stkl - pseg;
|
||||
ssptr = (struct stack_segment_linkage *) stkl;
|
||||
size = ssptr->sssize;
|
||||
pseg = ssptr->sspseg;
|
||||
result += size;
|
||||
}
|
||||
return (result);
|
||||
}
|
||||
#endif /* not CRAY2 */
|
||||
#endif /* CRAY */
|
||||
|
||||
#endif /* no alloca */
|
||||
#endif /* not GCC version 2 */
|
||||
1599
src/asm/asmy.y
Normal file
1599
src/asm/asmy.y
Normal file
File diff suppressed because it is too large
Load Diff
204
src/asm/charmap.c
Normal file
204
src/asm/charmap.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright © 2013 stag019 <stag019@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/asm.h"
|
||||
#include "asm/charmap.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/output.h"
|
||||
|
||||
struct Charmap globalCharmap = {0};
|
||||
|
||||
extern struct Section *pCurrentSection;
|
||||
|
||||
int
|
||||
readUTF8Char(char *destination, char *source)
|
||||
{
|
||||
int size;
|
||||
UBYTE first;
|
||||
first = source[0];
|
||||
|
||||
if(first >= 0xFC)
|
||||
{
|
||||
size = 6;
|
||||
}
|
||||
else if(first >= 0xF8)
|
||||
{
|
||||
size = 5;
|
||||
}
|
||||
else if(first >= 0xF0)
|
||||
{
|
||||
size = 4;
|
||||
}
|
||||
else if(first >= 0xE0)
|
||||
{
|
||||
size = 3;
|
||||
}
|
||||
else if(first >= 0xC0)
|
||||
{
|
||||
size = 2;
|
||||
}
|
||||
else if(first != '\0')
|
||||
{
|
||||
size = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = 0;
|
||||
}
|
||||
strncpy(destination, source, size);
|
||||
destination[size] = 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
int
|
||||
charmap_Add(char *input, UBYTE output)
|
||||
{
|
||||
int i, input_length;
|
||||
char temp1i[CHARMAPLENGTH + 1], temp2i[CHARMAPLENGTH + 1], temp1o = 0, temp2o = 0;
|
||||
|
||||
struct Charmap *charmap;
|
||||
|
||||
if(pCurrentSection)
|
||||
{
|
||||
if(pCurrentSection -> charmap)
|
||||
{
|
||||
charmap = pCurrentSection -> charmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
if((charmap = (struct Charmap *) calloc(1, sizeof(struct Charmap))) == NULL)
|
||||
{
|
||||
fatalerror("Not enough memory for charmap");
|
||||
}
|
||||
pCurrentSection -> charmap = charmap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
charmap = &globalCharmap;
|
||||
}
|
||||
|
||||
if(nPass == 2)
|
||||
{
|
||||
return charmap -> count;
|
||||
}
|
||||
|
||||
if(charmap -> count > MAXCHARMAPS || strlen(input) > CHARMAPLENGTH)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
input_length = strlen(input);
|
||||
if(input_length > 1)
|
||||
{
|
||||
i = 0;
|
||||
while(i < charmap -> count + 1)
|
||||
{
|
||||
if(input_length > strlen(charmap -> input[i]))
|
||||
{
|
||||
memcpy(temp1i, charmap -> input[i], CHARMAPLENGTH + 1);
|
||||
memcpy(charmap -> input[i], input, input_length);
|
||||
temp1o = charmap -> output[i];
|
||||
charmap -> output[i] = output;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
while(i < charmap -> count + 1)
|
||||
{
|
||||
memcpy(temp2i, charmap -> input[i], CHARMAPLENGTH + 1);
|
||||
memcpy(charmap -> input[i], temp1i, CHARMAPLENGTH + 1);
|
||||
memcpy(temp1i, temp2i, CHARMAPLENGTH + 1);
|
||||
temp2o = charmap -> output[i];
|
||||
charmap -> output[i] = temp1o;
|
||||
temp1o = temp2o;
|
||||
i++;
|
||||
}
|
||||
memcpy(charmap -> input[charmap -> count + 1], temp1i, CHARMAPLENGTH + 1);
|
||||
charmap -> output[charmap -> count + 1] = temp1o;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(charmap -> input[charmap -> count], input, input_length);
|
||||
charmap -> output[charmap -> count] = output;
|
||||
}
|
||||
return ++charmap -> count;
|
||||
}
|
||||
|
||||
int
|
||||
charmap_Convert(char **input)
|
||||
{
|
||||
struct Charmap *charmap;
|
||||
|
||||
char outchar[CHARMAPLENGTH + 1];
|
||||
char *buffer;
|
||||
int i, j, length;
|
||||
|
||||
if(pCurrentSection && pCurrentSection -> charmap)
|
||||
{
|
||||
charmap = pCurrentSection -> charmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
charmap = &globalCharmap;
|
||||
}
|
||||
|
||||
if((buffer = (char *) malloc(strlen(*input))) == NULL)
|
||||
{
|
||||
fatalerror("Not enough memory for buffer");
|
||||
}
|
||||
|
||||
length = 0;
|
||||
while(**input)
|
||||
{
|
||||
j = 0;
|
||||
for(i = 0; i < charmap -> count; i++)
|
||||
{
|
||||
j = strlen(charmap -> input[i]);
|
||||
if(memcmp(*input, charmap -> input[i], j) == 0)
|
||||
{
|
||||
outchar[0] = charmap -> output[i];
|
||||
outchar[1] = 0;
|
||||
break;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
if(!j)
|
||||
{
|
||||
j = readUTF8Char(outchar, *input);
|
||||
}
|
||||
if(!outchar[0])
|
||||
{
|
||||
buffer[length++] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0; outchar[i]; i++)
|
||||
{
|
||||
buffer[length++] = outchar[i];
|
||||
}
|
||||
}
|
||||
*input += j;
|
||||
}
|
||||
*input = buffer;
|
||||
return length;
|
||||
}
|
||||
|
||||
209
src/asm/fstack.c
209
src/asm/fstack.c
@@ -1,26 +1,24 @@
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* FileStack routines
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/fstack.h"
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "extern/err.h"
|
||||
#include "extern/strl.h"
|
||||
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
*/
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 256
|
||||
#endif
|
||||
|
||||
struct sContext *pFileStack;
|
||||
struct sSymbol *pCurrentMacro;
|
||||
@@ -47,12 +45,8 @@ ULONG ulMacroReturnValue;
|
||||
#define STAT_isREPTBlock 3
|
||||
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Context push and pop
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
pushcontext(void)
|
||||
{
|
||||
@@ -62,8 +56,7 @@ pushcontext(void)
|
||||
while (*ppFileStack)
|
||||
ppFileStack = &((*ppFileStack)->pNext);
|
||||
|
||||
if ((*ppFileStack =
|
||||
(struct sContext *) malloc(sizeof(struct sContext))) != NULL) {
|
||||
if ((*ppFileStack = malloc(sizeof(struct sContext))) != NULL) {
|
||||
(*ppFileStack)->FlexHandle = CurrentFlexHandle;
|
||||
(*ppFileStack)->pNext = NULL;
|
||||
strcpy((char *) (*ppFileStack)->tzFileName,
|
||||
@@ -160,13 +153,10 @@ yywrap(void)
|
||||
{
|
||||
return (popcontext());
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Dump the context stack to stdout
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dump the context stack to stderr
|
||||
*/
|
||||
void
|
||||
fstk_Dump(void)
|
||||
{
|
||||
@@ -175,90 +165,84 @@ fstk_Dump(void)
|
||||
pLastFile = pFileStack;
|
||||
|
||||
while (pLastFile) {
|
||||
printf("%s(%ld) -> ", pLastFile->tzFileName, pLastFile->nLine);
|
||||
fprintf(stderr, "%s(%ld) -> ", pLastFile->tzFileName,
|
||||
pLastFile->nLine);
|
||||
pLastFile = pLastFile->pNext;
|
||||
}
|
||||
|
||||
printf("%s(%ld)", tzCurrentFileName, nLineNo);
|
||||
fprintf(stderr, "%s(%ld)", tzCurrentFileName, nLineNo);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Extra includepath stuff
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Extra includepath stuff
|
||||
*/
|
||||
void
|
||||
fstk_AddIncludePath(char *s)
|
||||
{
|
||||
strcpy(IncludePaths[NextIncPath++], s);
|
||||
}
|
||||
|
||||
void
|
||||
fstk_FindFile(char *s)
|
||||
FILE *
|
||||
fstk_FindFile(char *fname)
|
||||
{
|
||||
char t[_MAX_PATH + 1];
|
||||
SLONG i = -1;
|
||||
char path[PATH_MAX];
|
||||
int i;
|
||||
FILE *f;
|
||||
|
||||
strcpy(t, s);
|
||||
if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) {
|
||||
return f;
|
||||
}
|
||||
|
||||
while (i < NextIncPath) {
|
||||
FILE *f;
|
||||
|
||||
if ((f = fopen(t, "rb")) != NULL) {
|
||||
fclose(f);
|
||||
strcpy(s, t);
|
||||
return;
|
||||
for (i = 0; i < NextIncPath; ++i) {
|
||||
if (strlcpy(path, IncludePaths[i], sizeof path) >=
|
||||
sizeof path) {
|
||||
continue;
|
||||
}
|
||||
i += 1;
|
||||
if (i < NextIncPath) {
|
||||
strcpy(t, IncludePaths[i]);
|
||||
strcat(t, s);
|
||||
if (strlcat(path, fname, sizeof path) >= sizeof path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Set up an include file for parsing
|
||||
*
|
||||
*/
|
||||
|
||||
ULONG
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up an include file for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunInclude(char *tzFileName)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
//printf("INCLUDE: %s\n", s);
|
||||
f = fstk_FindFile(tzFileName);
|
||||
|
||||
fstk_FindFile(tzFileName);
|
||||
//printf("INCLUDING: %s\n", tzFileName);
|
||||
if (f == NULL) {
|
||||
err(1, "Unable to open included file '%s'",
|
||||
tzFileName);
|
||||
}
|
||||
|
||||
if ((f = fopen(tzFileName, "r")) != NULL) {
|
||||
pushcontext();
|
||||
nLineNo = 1;
|
||||
nCurrentStatus = STAT_isInclude;
|
||||
strcpy(tzCurrentFileName, tzFileName);
|
||||
pCurrentFile = f;
|
||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
pushcontext();
|
||||
nLineNo = 1;
|
||||
nCurrentStatus = STAT_isInclude;
|
||||
strcpy(tzCurrentFileName, tzFileName);
|
||||
pCurrentFile = f;
|
||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
|
||||
//Dirty hack to give the INCLUDE directive a linefeed
|
||||
//Dirty hack to give the INCLUDE directive a linefeed
|
||||
|
||||
yyunput('\n');
|
||||
nLineNo -= 1;
|
||||
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
yyunput('\n');
|
||||
nLineNo -= 1;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Set up a macro for parsing
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set up a macro for parsing
|
||||
*/
|
||||
ULONG
|
||||
fstk_RunMacro(char *s)
|
||||
{
|
||||
@@ -271,22 +255,21 @@ fstk_RunMacro(char *s)
|
||||
sym_UseNewMacroArgs();
|
||||
nCurrentStatus = STAT_isMacro;
|
||||
strcpy(tzCurrentFileName, s);
|
||||
if (sym->pMacro == NULL)
|
||||
return 0;
|
||||
pCurrentMacro = sym;
|
||||
CurrentFlexHandle =
|
||||
yy_scan_bytes(pCurrentMacro->pMacro,
|
||||
pCurrentMacro->ulMacroSize);
|
||||
strlen(pCurrentMacro->pMacro));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Set up a macroargument for parsing
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set up a macroargument for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunMacroArg(SLONG s)
|
||||
{
|
||||
@@ -306,13 +289,10 @@ fstk_RunMacroArg(SLONG s)
|
||||
} else
|
||||
fatalerror("No such macroargument");
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Set up a stringequate for parsing
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set up a stringequate for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunString(char *s)
|
||||
{
|
||||
@@ -326,15 +306,12 @@ fstk_RunString(char *s)
|
||||
yy_scan_bytes(pSym->pMacro, strlen(pSym->pMacro));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
} else
|
||||
yyerror("No such string symbol");
|
||||
yyerror("No such string symbol '%s'", s);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Set up a repeat block for parsing
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set up a repeat block for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunRept(ULONG count)
|
||||
{
|
||||
@@ -352,14 +329,11 @@ fstk_RunRept(ULONG count)
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Initialize the filestack routines
|
||||
*
|
||||
*/
|
||||
|
||||
ULONG
|
||||
/*
|
||||
* Initialize the filestack routines
|
||||
*/
|
||||
void
|
||||
fstk_Init(char *s)
|
||||
{
|
||||
char tzFileName[_MAX_PATH + 1];
|
||||
@@ -367,17 +341,16 @@ fstk_Init(char *s)
|
||||
sym_AddString("__FILE__", s);
|
||||
|
||||
strcpy(tzFileName, s);
|
||||
fstk_FindFile(tzFileName);
|
||||
|
||||
pFileStack = NULL;
|
||||
if ((pCurrentFile = fopen(tzFileName, "r")) != NULL) {
|
||||
nMacroCount = 0;
|
||||
nCurrentStatus = STAT_isInclude;
|
||||
strcpy(tzCurrentFileName, tzFileName);
|
||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
nLineNo = 1;
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
pCurrentFile = fopen(tzFileName, "rb");
|
||||
if (pCurrentFile == NULL) {
|
||||
err(1, "Unable to open file '%s'", tzFileName);
|
||||
}
|
||||
|
||||
nMacroCount = 0;
|
||||
nCurrentStatus = STAT_isInclude;
|
||||
strcpy(tzCurrentFileName, tzFileName);
|
||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
nLineNo = 1;
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
%token T_SECT_BSS T_SECT_VRAM T_SECT_CODE T_SECT_HOME T_SECT_HRAM
|
||||
|
||||
%token T_Z80_ADC T_Z80_ADD T_Z80_AND
|
||||
%token T_Z80_BIT
|
||||
%token T_Z80_CALL T_Z80_CCF T_Z80_CP T_Z80_CPL
|
||||
%token T_Z80_DAA T_Z80_DEC T_Z80_DI
|
||||
%token T_Z80_EI T_Z80_EX
|
||||
%token T_Z80_HALT
|
||||
%token T_Z80_INC
|
||||
%token T_Z80_JP T_Z80_JR
|
||||
%token T_Z80_LD
|
||||
%token T_Z80_LDI
|
||||
%token T_Z80_LDD
|
||||
%token T_Z80_LDIO
|
||||
%token T_Z80_NOP
|
||||
%token T_Z80_OR
|
||||
%token T_Z80_POP T_Z80_PUSH
|
||||
%token T_Z80_RES T_Z80_RET T_Z80_RETI T_Z80_RST
|
||||
%token T_Z80_RL T_Z80_RLA T_Z80_RLC T_Z80_RLCA
|
||||
%token T_Z80_RR T_Z80_RRA T_Z80_RRC T_Z80_RRCA
|
||||
%token T_Z80_SBC T_Z80_SCF T_Z80_STOP
|
||||
%token T_Z80_SLA T_Z80_SRA T_Z80_SRL T_Z80_SUB T_Z80_SWAP
|
||||
%token T_Z80_XOR
|
||||
|
||||
%token T_MODE_A T_MODE_B T_MODE_C T_MODE_C_IND T_MODE_D T_MODE_E T_MODE_H T_MODE_L
|
||||
%token T_MODE_AF
|
||||
%token T_MODE_BC T_MODE_BC_IND
|
||||
%token T_MODE_DE T_MODE_DE_IND
|
||||
%token T_MODE_SP T_MODE_SP_IND
|
||||
%token T_MODE_HL T_MODE_HL_IND T_MODE_HL_INDDEC T_MODE_HL_INDINC
|
||||
%token T_CC_NZ T_CC_Z T_CC_NC
|
||||
|
||||
%type <nConstValue> reg_r
|
||||
%type <nConstValue> reg_ss
|
||||
%type <nConstValue> reg_rr
|
||||
%type <nConstValue> reg_tt
|
||||
%type <nConstValue> ccode
|
||||
%type <sVal> op_a_n
|
||||
%type <nConstValue> op_a_r
|
||||
%type <nConstValue> op_hl_ss
|
||||
%type <sVal> op_mem_ind
|
||||
@@ -1,498 +0,0 @@
|
||||
section : T_POP_SECTION string ',' sectiontype
|
||||
{ out_NewSection($2,$4); }
|
||||
| T_POP_SECTION string ',' sectiontype '[' const ']'
|
||||
{
|
||||
if( $6>=0 && $6<0x10000 )
|
||||
out_NewAbsSection($2,$4,$6,-1);
|
||||
else
|
||||
yyerror( "Address must be 16-bit" );
|
||||
}
|
||||
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']'
|
||||
{
|
||||
if( $4==SECT_CODE )
|
||||
{
|
||||
if( $8>=1 && $8<=255 )
|
||||
out_NewAbsSection($2,$4,-1,$8);
|
||||
else
|
||||
yyerror( "BANK value out of range" );
|
||||
}
|
||||
else
|
||||
yyerror( "BANK only allowed for CODE/DATA" );
|
||||
}
|
||||
| T_POP_SECTION string ',' sectiontype '[' const ']' ',' T_OP_BANK '[' const ']'
|
||||
{
|
||||
if( $4==SECT_CODE )
|
||||
{
|
||||
if( $6>=0 && $6<0x10000 )
|
||||
{
|
||||
if( $11>=1 && $11<=255 )
|
||||
out_NewAbsSection($2,$4,$6,$11);
|
||||
else
|
||||
yyerror( "BANK value out of range" );
|
||||
}
|
||||
else
|
||||
yyerror( "Address must be 16-bit" );
|
||||
}
|
||||
else
|
||||
yyerror( "BANK only allowed for CODE/DATA" );
|
||||
}
|
||||
;
|
||||
|
||||
sectiontype : T_SECT_BSS { $$=SECT_BSS; }
|
||||
| T_SECT_VRAM { $$=SECT_VRAM; }
|
||||
| T_SECT_CODE { $$=SECT_CODE; }
|
||||
| T_SECT_HOME { $$=SECT_HOME; }
|
||||
| T_SECT_HRAM { $$=SECT_HRAM; }
|
||||
;
|
||||
|
||||
|
||||
cpu_command : z80_adc
|
||||
| z80_add
|
||||
| z80_and
|
||||
| z80_bit
|
||||
| z80_call
|
||||
| z80_ccf
|
||||
| z80_cp
|
||||
| z80_cpl
|
||||
| z80_daa
|
||||
| z80_dec
|
||||
| z80_di
|
||||
| z80_ei
|
||||
| z80_ex
|
||||
| z80_halt
|
||||
| z80_inc
|
||||
| z80_jp
|
||||
| z80_jr
|
||||
| z80_ld
|
||||
| z80_ldd
|
||||
| z80_ldi
|
||||
| z80_ldio
|
||||
| z80_nop
|
||||
| z80_or
|
||||
| z80_pop
|
||||
| z80_push
|
||||
| z80_res
|
||||
| z80_ret
|
||||
| z80_reti
|
||||
| z80_rl
|
||||
| z80_rla
|
||||
| z80_rlc
|
||||
| z80_rlca
|
||||
| z80_rr
|
||||
| z80_rra
|
||||
| z80_rrc
|
||||
| z80_rrca
|
||||
| z80_rst
|
||||
| z80_sbc
|
||||
| z80_scf
|
||||
| z80_set
|
||||
| z80_sla
|
||||
| z80_sra
|
||||
| z80_srl
|
||||
| z80_stop
|
||||
| z80_sub
|
||||
| z80_swap
|
||||
| z80_xor
|
||||
;
|
||||
|
||||
z80_adc : T_Z80_ADC op_a_n { out_AbsByte(0xCE); out_RelByte(&$2); }
|
||||
| T_Z80_ADC op_a_r { out_AbsByte(0x88|$2); }
|
||||
;
|
||||
|
||||
z80_add : T_Z80_ADD op_a_n { out_AbsByte(0xC6); out_RelByte(&$2); }
|
||||
| T_Z80_ADD op_a_r { out_AbsByte(0x80|$2); }
|
||||
| T_Z80_ADD op_hl_ss { out_AbsByte(0x09|($2<<4)); }
|
||||
| T_Z80_ADD T_MODE_SP comma const_8bit
|
||||
{ out_AbsByte(0xE8); out_RelByte(&$4); }
|
||||
|
||||
;
|
||||
|
||||
z80_and : T_Z80_AND op_a_n { out_AbsByte(0xE6); out_RelByte(&$2); }
|
||||
| T_Z80_AND op_a_r { out_AbsByte(0xA0|$2); }
|
||||
;
|
||||
|
||||
z80_bit : T_Z80_BIT const_3bit comma reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x40|($2<<3)|$4); }
|
||||
;
|
||||
|
||||
z80_call : T_Z80_CALL const_16bit
|
||||
{ out_AbsByte(0xCD); out_RelWord(&$2); }
|
||||
| T_Z80_CALL ccode comma const_16bit
|
||||
{ out_AbsByte(0xC4|($2<<3)); out_RelWord(&$4); }
|
||||
;
|
||||
|
||||
z80_ccf : T_Z80_CCF
|
||||
{ out_AbsByte(0x3F); }
|
||||
;
|
||||
|
||||
z80_cp : T_Z80_CP op_a_n { out_AbsByte(0xFE); out_RelByte(&$2); }
|
||||
| T_Z80_CP op_a_r { out_AbsByte(0xB8|$2); }
|
||||
;
|
||||
|
||||
z80_cpl : T_Z80_CPL { out_AbsByte(0x2F); }
|
||||
;
|
||||
|
||||
z80_daa : T_Z80_DAA { out_AbsByte(0x27); }
|
||||
;
|
||||
|
||||
z80_dec : T_Z80_DEC reg_r
|
||||
{ out_AbsByte(0x05|($2<<3)); }
|
||||
| T_Z80_DEC reg_ss
|
||||
{ out_AbsByte(0x0B|($2<<4)); }
|
||||
;
|
||||
|
||||
z80_di : T_Z80_DI
|
||||
{ out_AbsByte(0xF3); }
|
||||
;
|
||||
|
||||
z80_ei : T_Z80_EI
|
||||
{ out_AbsByte(0xFB); }
|
||||
;
|
||||
|
||||
z80_ex : T_Z80_EX T_MODE_HL comma T_MODE_SP_IND
|
||||
{ out_AbsByte(0xE3); }
|
||||
| T_Z80_EX T_MODE_SP_IND comma T_MODE_HL
|
||||
{ out_AbsByte(0xE3); }
|
||||
;
|
||||
|
||||
z80_halt : T_Z80_HALT
|
||||
{ out_AbsByte(0x76); out_AbsByte(0x00); }
|
||||
;
|
||||
|
||||
z80_inc : T_Z80_INC reg_r
|
||||
{ out_AbsByte(0x04|($2<<3)); }
|
||||
| T_Z80_INC reg_ss
|
||||
{ out_AbsByte(0x03|($2<<4)); }
|
||||
;
|
||||
|
||||
z80_jp : T_Z80_JP const_16bit
|
||||
{ out_AbsByte(0xC3); out_RelWord(&$2); }
|
||||
| T_Z80_JP ccode comma const_16bit
|
||||
{ out_AbsByte(0xC2|($2<<3)); out_RelWord(&$4); }
|
||||
| T_Z80_JP T_MODE_HL_IND
|
||||
{ out_AbsByte(0xE9); }
|
||||
;
|
||||
|
||||
z80_jr : T_Z80_JR const_PCrel
|
||||
{ out_AbsByte(0x18); out_PCRelByte(&$2); }
|
||||
| T_Z80_JR ccode comma const_PCrel
|
||||
{ out_AbsByte(0x20|($2<<3)); out_PCRelByte(&$4); }
|
||||
;
|
||||
|
||||
z80_ldi : T_Z80_LDI T_MODE_HL_IND comma T_MODE_A
|
||||
{ out_AbsByte(0x02|(2<<4)); }
|
||||
| T_Z80_LDI T_MODE_A comma T_MODE_HL
|
||||
{ out_AbsByte(0x0A|(2<<4)); }
|
||||
;
|
||||
|
||||
z80_ldd : T_Z80_LDD T_MODE_HL_IND comma T_MODE_A
|
||||
{ out_AbsByte(0x02|(3<<4)); }
|
||||
| T_Z80_LDD T_MODE_A comma T_MODE_HL
|
||||
{ out_AbsByte(0x0A|(3<<4)); }
|
||||
;
|
||||
|
||||
z80_ldio : T_Z80_LDIO T_MODE_A comma op_mem_ind
|
||||
{
|
||||
rpn_CheckHRAM(&$4,&$4);
|
||||
|
||||
if( (!rpn_isReloc(&$4))
|
||||
&& ($4.nVal<0 || ($4.nVal>0xFF && $4.nVal<0xFF00) || $4.nVal>0xFFFF) )
|
||||
{
|
||||
yyerror( "Source must be in the IO/HRAM area" );
|
||||
}
|
||||
|
||||
out_AbsByte(0xF0);
|
||||
$4.nVal&=0xFF;
|
||||
out_RelByte(&$4);
|
||||
}
|
||||
| T_Z80_LDIO op_mem_ind comma T_MODE_A
|
||||
{
|
||||
rpn_CheckHRAM(&$2,&$2);
|
||||
|
||||
if( (!rpn_isReloc(&$2))
|
||||
&& ($2.nVal<0 || ($2.nVal>0xFF && $2.nVal<0xFF00) || $2.nVal>0xFFFF) )
|
||||
{
|
||||
yyerror( "Destination must be in the IO/HRAM area" );
|
||||
}
|
||||
|
||||
out_AbsByte(0xE0);
|
||||
$2.nVal&=0xFF;
|
||||
out_RelByte(&$2);
|
||||
}
|
||||
;
|
||||
|
||||
z80_ld : z80_ld_mem
|
||||
| z80_ld_cind
|
||||
| z80_ld_rr
|
||||
| z80_ld_ss
|
||||
| z80_ld_hl
|
||||
| z80_ld_sp
|
||||
| z80_ld_r
|
||||
| z80_ld_a
|
||||
;
|
||||
|
||||
z80_ld_hl : T_Z80_LD T_MODE_HL comma '[' T_MODE_SP const_8bit ']'
|
||||
{ out_AbsByte(0xF8); out_RelByte(&$6); }
|
||||
| T_Z80_LD T_MODE_HL comma const_16bit
|
||||
{ out_AbsByte(0x01|(REG_HL<<4)); out_RelWord(&$4); }
|
||||
;
|
||||
z80_ld_sp : T_Z80_LD T_MODE_SP comma T_MODE_HL
|
||||
{ out_AbsByte(0xF9); }
|
||||
| T_Z80_LD T_MODE_SP comma const_16bit
|
||||
{ out_AbsByte(0x01|(REG_SP<<4)); out_RelWord(&$4); }
|
||||
;
|
||||
|
||||
z80_ld_mem : T_Z80_LD op_mem_ind comma T_MODE_SP
|
||||
{ out_AbsByte(0x08); out_RelWord(&$2); }
|
||||
| T_Z80_LD op_mem_ind comma T_MODE_A
|
||||
{
|
||||
if( (!rpn_isReloc(&$2)) && $2.nVal>=0xFF00)
|
||||
{
|
||||
out_AbsByte(0xE0);
|
||||
out_AbsByte($2.nVal&0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_AbsByte(0xEA);
|
||||
out_RelWord(&$2);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
z80_ld_cind : T_Z80_LD T_MODE_C_IND comma T_MODE_A
|
||||
{ out_AbsByte(0xE2); }
|
||||
;
|
||||
|
||||
z80_ld_rr : T_Z80_LD reg_rr comma T_MODE_A
|
||||
{ out_AbsByte(0x02|($2<<4)); }
|
||||
;
|
||||
|
||||
z80_ld_r : T_Z80_LD reg_r comma const_8bit
|
||||
{ out_AbsByte(0x06|($2<<3)); out_RelByte(&$4); }
|
||||
| T_Z80_LD reg_r comma reg_r
|
||||
{
|
||||
if( ($2==REG_HL_IND) && ($4==REG_HL_IND) )
|
||||
{
|
||||
yyerror( "LD (HL),(HL) not allowed" );
|
||||
}
|
||||
else
|
||||
out_AbsByte(0x40|($2<<3)|$4);
|
||||
}
|
||||
;
|
||||
|
||||
z80_ld_a : T_Z80_LD reg_r comma T_MODE_C_IND
|
||||
{
|
||||
if( $2==REG_A )
|
||||
out_AbsByte(0xF2);
|
||||
else
|
||||
{
|
||||
yyerror( "Destination operand must be A" );
|
||||
}
|
||||
}
|
||||
| T_Z80_LD reg_r comma reg_rr
|
||||
{
|
||||
if( $2==REG_A )
|
||||
out_AbsByte(0x0A|($4<<4));
|
||||
else
|
||||
{
|
||||
yyerror( "Destination operand must be A" );
|
||||
}
|
||||
}
|
||||
| T_Z80_LD reg_r comma op_mem_ind
|
||||
{
|
||||
if( $2==REG_A )
|
||||
{
|
||||
if( (!rpn_isReloc(&$4)) && $4.nVal>=0xFF00 )
|
||||
{
|
||||
out_AbsByte(0xF0);
|
||||
out_AbsByte($4.nVal&0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_AbsByte(0xFA);
|
||||
out_RelWord(&$4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
yyerror( "Destination operand must be A" );
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
z80_ld_ss : T_Z80_LD reg_ss comma const_16bit
|
||||
{ out_AbsByte(0x01|($2<<4)); out_RelWord(&$4); }
|
||||
;
|
||||
|
||||
z80_nop : T_Z80_NOP
|
||||
{ out_AbsByte(0x00); }
|
||||
;
|
||||
|
||||
z80_or : T_Z80_OR op_a_n
|
||||
{ out_AbsByte(0xF6); out_RelByte(&$2); }
|
||||
| T_Z80_OR op_a_r
|
||||
{ out_AbsByte(0xB0|$2); }
|
||||
;
|
||||
|
||||
z80_pop : T_Z80_POP reg_tt
|
||||
{ out_AbsByte(0xC1|($2<<4)); }
|
||||
;
|
||||
|
||||
z80_push : T_Z80_PUSH reg_tt
|
||||
{ out_AbsByte(0xC5|($2<<4)); }
|
||||
;
|
||||
|
||||
z80_res : T_Z80_RES const_3bit comma reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x80|($2<<3)|$4); }
|
||||
;
|
||||
|
||||
z80_ret : T_Z80_RET
|
||||
{ out_AbsByte(0xC9); }
|
||||
| T_Z80_RET ccode
|
||||
{ out_AbsByte(0xC0|($2<<3)); }
|
||||
;
|
||||
|
||||
z80_reti : T_Z80_RETI
|
||||
{ out_AbsByte(0xD9); }
|
||||
;
|
||||
|
||||
z80_rl : T_Z80_RL reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x10|$2); }
|
||||
;
|
||||
|
||||
z80_rla : T_Z80_RLA
|
||||
{ out_AbsByte(0x17); }
|
||||
;
|
||||
|
||||
z80_rlc : T_Z80_RLC reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x00|$2); }
|
||||
;
|
||||
|
||||
z80_rlca : T_Z80_RLCA
|
||||
{ out_AbsByte(0x07); }
|
||||
;
|
||||
|
||||
z80_rr : T_Z80_RR reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x18|$2); }
|
||||
;
|
||||
|
||||
z80_rra : T_Z80_RRA
|
||||
{ out_AbsByte(0x1F); }
|
||||
;
|
||||
|
||||
z80_rrc : T_Z80_RRC reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x08|$2); }
|
||||
;
|
||||
|
||||
z80_rrca : T_Z80_RRCA
|
||||
{ out_AbsByte(0x0F); }
|
||||
;
|
||||
|
||||
z80_rst : T_Z80_RST const_8bit
|
||||
{
|
||||
if( rpn_isReloc(&$2) )
|
||||
{
|
||||
yyerror( "Address for RST must be absolute" );
|
||||
}
|
||||
else if( ($2.nVal&0x38)!=$2.nVal )
|
||||
{
|
||||
yyerror( "Invalid address for RST" );
|
||||
}
|
||||
else
|
||||
out_AbsByte(0xC7|$2.nVal);
|
||||
}
|
||||
;
|
||||
|
||||
z80_sbc : T_Z80_SBC op_a_n { out_AbsByte(0xDE); out_RelByte(&$2); }
|
||||
| T_Z80_SBC op_a_r { out_AbsByte(0x98|$2); }
|
||||
;
|
||||
|
||||
z80_scf : T_Z80_SCF
|
||||
{ out_AbsByte(0x37); }
|
||||
;
|
||||
|
||||
z80_set : T_POP_SET const_3bit comma reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0xC0|($2<<3)|$4); }
|
||||
;
|
||||
|
||||
z80_sla : T_Z80_SLA reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x20|$2); }
|
||||
;
|
||||
|
||||
z80_sra : T_Z80_SRA reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x28|$2); }
|
||||
;
|
||||
|
||||
z80_srl : T_Z80_SRL reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x38|$2); }
|
||||
;
|
||||
|
||||
z80_stop : T_Z80_STOP
|
||||
{ out_AbsByte(0x10); out_AbsByte(0x00); }
|
||||
;
|
||||
|
||||
z80_sub : T_Z80_SUB op_a_n { out_AbsByte(0xD6); out_RelByte(&$2); }
|
||||
| T_Z80_SUB op_a_r { out_AbsByte(0x90|$2); }
|
||||
;
|
||||
|
||||
z80_swap : T_Z80_SWAP reg_r
|
||||
{ out_AbsByte(0xCB); out_AbsByte(0x30|$2); }
|
||||
;
|
||||
|
||||
z80_xor : T_Z80_XOR op_a_n { out_AbsByte(0xEE); out_RelByte(&$2); }
|
||||
| T_Z80_XOR op_a_r { out_AbsByte(0xA8|$2); }
|
||||
;
|
||||
|
||||
op_mem_ind : '[' const_16bit ']' { $$ = $2; }
|
||||
;
|
||||
|
||||
op_hl_ss : reg_ss { $$ = $1; }
|
||||
| T_MODE_HL comma reg_ss { $$ = $3; }
|
||||
;
|
||||
|
||||
op_a_r : reg_r { $$ = $1; }
|
||||
| T_MODE_A comma reg_r { $$ = $3; }
|
||||
;
|
||||
|
||||
op_a_n : const_8bit { $$ = $1; }
|
||||
| T_MODE_A comma const_8bit { $$ = $3; }
|
||||
;
|
||||
|
||||
comma : ','
|
||||
;
|
||||
|
||||
ccode : T_CC_NZ { $$ = CC_NZ; }
|
||||
| T_CC_Z { $$ = CC_Z; }
|
||||
| T_CC_NC { $$ = CC_NC; }
|
||||
| T_MODE_C { $$ = CC_C; }
|
||||
;
|
||||
|
||||
reg_r : T_MODE_B { $$ = REG_B; }
|
||||
| T_MODE_C { $$ = REG_C; }
|
||||
| T_MODE_D { $$ = REG_D; }
|
||||
| T_MODE_E { $$ = REG_E; }
|
||||
| T_MODE_H { $$ = REG_H; }
|
||||
| T_MODE_L { $$ = REG_L; }
|
||||
| T_MODE_HL_IND { $$ = REG_HL_IND; }
|
||||
| T_MODE_A { $$ = REG_A; }
|
||||
;
|
||||
|
||||
reg_tt : T_MODE_BC { $$ = REG_BC; }
|
||||
| T_MODE_DE { $$ = REG_DE; }
|
||||
| T_MODE_HL { $$ = REG_HL; }
|
||||
| T_MODE_AF { $$ = REG_AF; }
|
||||
;
|
||||
|
||||
reg_ss : T_MODE_BC { $$ = REG_BC; }
|
||||
| T_MODE_DE { $$ = REG_DE; }
|
||||
| T_MODE_HL { $$ = REG_HL; }
|
||||
| T_MODE_SP { $$ = REG_SP; }
|
||||
;
|
||||
|
||||
reg_rr : T_MODE_BC_IND { $$ = REG_BC_IND; }
|
||||
| T_MODE_DE_IND { $$ = REG_DE_IND; }
|
||||
| T_MODE_HL_INDINC { $$ = REG_HL_INDINC; }
|
||||
| T_MODE_HL_INDDEC { $$ = REG_HL_INDDEC; }
|
||||
;
|
||||
|
||||
%%
|
||||
@@ -7,12 +7,13 @@
|
||||
|
||||
#include "asmy.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
UBYTE oDontExpandStrings = 0;
|
||||
bool oDontExpandStrings = false;
|
||||
SLONG nGBGfxID = -1;
|
||||
SLONG nBinaryID = -1;
|
||||
|
||||
@@ -109,7 +110,7 @@ ascii2bin(char *s)
|
||||
ULONG
|
||||
ParseFixedPoint(char *s, ULONG size)
|
||||
{
|
||||
char dest[256];
|
||||
//char dest[256];
|
||||
ULONG i = 0, dot = 0;
|
||||
|
||||
while (size && dot != 2) {
|
||||
@@ -117,13 +118,13 @@ ParseFixedPoint(char *s, ULONG size)
|
||||
dot += 1;
|
||||
|
||||
if (dot < 2) {
|
||||
dest[i] = s[i];
|
||||
//dest[i] = s[i];
|
||||
size -= 1;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
dest[i] = 0;
|
||||
//dest[i] = 0;
|
||||
|
||||
yyunputbytes(size);
|
||||
|
||||
@@ -160,7 +161,7 @@ ParseSymbol(char *src, ULONG size)
|
||||
if (*src == '@')
|
||||
marg = sym_FindMacroArg(-1);
|
||||
else if (*src >= '0' && *src <= '9')
|
||||
marg = sym_FindMacroArg(*src);
|
||||
marg = sym_FindMacroArg(*src - '0');
|
||||
else {
|
||||
fatalerror("Malformed ID");
|
||||
return (0);
|
||||
@@ -184,7 +185,7 @@ ParseSymbol(char *src, ULONG size)
|
||||
|
||||
dest[copied] = 0;
|
||||
|
||||
if (oDontExpandStrings == 0 && sym_isString(dest)) {
|
||||
if (!oDontExpandStrings && sym_isString(dest)) {
|
||||
char *s;
|
||||
|
||||
yyskipbytes(size_backup);
|
||||
@@ -208,10 +209,14 @@ PutMacroArg(char *src, ULONG size)
|
||||
char *s;
|
||||
|
||||
yyskipbytes(size);
|
||||
if ((s = sym_FindMacroArg(src[1] - '0')) != NULL) {
|
||||
yyunputstr(s);
|
||||
if ((size == 2 && src[1] >= '1' && src[1] <= '9')) {
|
||||
if ((s = sym_FindMacroArg(src[1] - '0')) != NULL) {
|
||||
yyunputstr(s);
|
||||
} else {
|
||||
yyerror("Macro argument not defined");
|
||||
}
|
||||
} else {
|
||||
yyerror("Macro argument not defined");
|
||||
yyerror("Invalid macro argument");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -219,9 +224,14 @@ PutMacroArg(char *src, ULONG size)
|
||||
ULONG
|
||||
PutUniqueArg(char *src, ULONG size)
|
||||
{
|
||||
src = src;
|
||||
char *s;
|
||||
|
||||
yyskipbytes(size);
|
||||
yyunputstr(sym_FindMacroArg(-1));
|
||||
if ((s = sym_FindMacroArg(-1)) != NULL) {
|
||||
yyunputstr(s);
|
||||
} else {
|
||||
yyerror("Macro unique label string not defined");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@@ -258,6 +268,9 @@ struct sLexInitString staticstrings[] = {
|
||||
|
||||
{"bank", T_OP_BANK},
|
||||
|
||||
{"round", T_OP_ROUND},
|
||||
{"ceil", T_OP_CEIL},
|
||||
{"floor", T_OP_FLOOR},
|
||||
{"div", T_OP_FDIV},
|
||||
{"mul", T_OP_FMUL},
|
||||
{"sin", T_OP_SIN},
|
||||
@@ -298,6 +311,7 @@ struct sLexInitString staticstrings[] = {
|
||||
{"rsset", T_POP_RSSET},
|
||||
|
||||
{"incbin", T_POP_INCBIN},
|
||||
{"charmap", T_POP_CHARMAP},
|
||||
|
||||
{"fail", T_POP_FAIL},
|
||||
{"warn", T_POP_WARN},
|
||||
@@ -316,12 +330,17 @@ struct sLexInitString staticstrings[] = {
|
||||
{"else", T_POP_ELSE},
|
||||
{"endc", T_POP_ENDC},
|
||||
|
||||
{"bss", T_SECT_BSS},
|
||||
{"wram0", T_SECT_WRAM0},
|
||||
{"bss", T_SECT_WRAM0}, /* deprecated */
|
||||
{"vram", T_SECT_VRAM},
|
||||
{"code", T_SECT_CODE},
|
||||
{"data", T_SECT_CODE},
|
||||
{"home", T_SECT_HOME},
|
||||
{"code", T_SECT_ROMX}, /* deprecated */
|
||||
{"data", T_SECT_ROMX}, /* deprecated */
|
||||
{"romx", T_SECT_ROMX},
|
||||
{"home", T_SECT_ROM0}, /* deprecated */
|
||||
{"rom0", T_SECT_ROM0},
|
||||
{"hram", T_SECT_HRAM},
|
||||
{"wramx", T_SECT_WRAMX},
|
||||
{"sram", T_SECT_SRAM},
|
||||
|
||||
{NAME_RB, T_POP_RB},
|
||||
{NAME_RW, T_POP_RW},
|
||||
@@ -382,7 +401,7 @@ setuplex(void)
|
||||
|
||||
id = lex_FloatAlloc(&tMacroArgToken);
|
||||
lex_FloatAddFirstRange(id, '\\', '\\');
|
||||
lex_FloatAddSecondRange(id, '0', '9');
|
||||
lex_FloatAddSecondRange(id, '1', '9');
|
||||
id = lex_FloatAlloc(&tMacroUniqueToken);
|
||||
lex_FloatAddFirstRange(id, '\\', '\\');
|
||||
lex_FloatAddSecondRange(id, '@', '@');
|
||||
|
||||
985
src/asm/lexer.c
985
src/asm/lexer.c
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
#include "asm/lexer.h"
|
||||
#include "asm/rpn.h"
|
||||
|
||||
#include "../asmy.h"
|
||||
#include "asmy.h"
|
||||
|
||||
struct sLexInitString localstrings[] = {
|
||||
{"adc", T_Z80_ADC},
|
||||
315
src/asm/main.c
315
src/asm/main.c
@@ -1,12 +1,5 @@
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <getopt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -17,21 +10,17 @@
|
||||
#include "asm/fstack.h"
|
||||
#include "asm/output.h"
|
||||
#include "asm/main.h"
|
||||
#include "extern/err.h"
|
||||
#include "extern/reallocarray.h"
|
||||
|
||||
int yyparse(void);
|
||||
void setuplex(void);
|
||||
|
||||
#ifdef AMIGA
|
||||
__near long __stack = 65536L;
|
||||
int cldefines_index;
|
||||
int cldefines_size;
|
||||
char **cldefines;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
*/
|
||||
char *progname;
|
||||
|
||||
clock_t nStartClock, nEndClock;
|
||||
SLONG nLineNo;
|
||||
@@ -39,13 +28,8 @@ ULONG nTotalLines, nPass, nPC, nIFDepth, nErrors;
|
||||
|
||||
extern int yydebug;
|
||||
|
||||
char temptext[1024];
|
||||
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* Option stack
|
||||
*
|
||||
*/
|
||||
|
||||
struct sOptions DefaultOptions;
|
||||
@@ -136,9 +120,8 @@ opt_Parse(char *s)
|
||||
newopt.gbgfx[2] = s[3];
|
||||
newopt.gbgfx[3] = s[4];
|
||||
} else {
|
||||
fprintf(stderr, "Must specify exactly 4 characters "
|
||||
"for option 'g'\n");
|
||||
exit(1);
|
||||
errx(1, "Must specify exactly 4 characters for "
|
||||
"option 'g'");
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
@@ -146,9 +129,8 @@ opt_Parse(char *s)
|
||||
newopt.binary[0] = s[1];
|
||||
newopt.binary[1] = s[2];
|
||||
} else {
|
||||
fprintf(stderr, "Must specify exactly 2 characters "
|
||||
"for option 'b'\n");
|
||||
exit(1);
|
||||
errx(1, "Must specify exactly 2 characters for option "
|
||||
"'b'");
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
@@ -157,12 +139,10 @@ opt_Parse(char *s)
|
||||
|
||||
result = sscanf(&s[1], "%lx", &newopt.fillchar);
|
||||
if (!((result == EOF) || (result == 1))) {
|
||||
fprintf(stderr,
|
||||
"Invalid argument for option 'z'\n");
|
||||
exit(1);
|
||||
errx(1, "Invalid argument for option 'z'");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument for option 'z'\n");
|
||||
errx(1, "Invalid argument for option 'z'");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
@@ -179,9 +159,7 @@ opt_Push(void)
|
||||
{
|
||||
struct sOptionStackEntry *pOpt;
|
||||
|
||||
if ((pOpt =
|
||||
(struct sOptionStackEntry *)
|
||||
malloc(sizeof(struct sOptionStackEntry))) != NULL) {
|
||||
if ((pOpt = malloc(sizeof(struct sOptionStackEntry))) != NULL) {
|
||||
pOpt->Options = CurrentOptions;
|
||||
pOpt->pNext = pOptionStack;
|
||||
pOptionStack = pOpt;
|
||||
@@ -202,49 +180,87 @@ opt_Pop(void)
|
||||
} else
|
||||
fatalerror("No entries in the option stack");
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* Error handling
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
yyerror(char *s)
|
||||
opt_AddDefine(char *s)
|
||||
{
|
||||
printf("*ERROR*\t");
|
||||
char *value, *equals;
|
||||
if(cldefines_index >= cldefines_size)
|
||||
{
|
||||
cldefines_size *= 2;
|
||||
cldefines = reallocarray(cldefines, cldefines_size,
|
||||
2 * sizeof(void *));
|
||||
if(!cldefines)
|
||||
{
|
||||
fatalerror("No memory for command line defines");
|
||||
}
|
||||
}
|
||||
equals = strchr(s, '=');
|
||||
if(equals)
|
||||
{
|
||||
*equals = '\0';
|
||||
value = equals + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = "1";
|
||||
}
|
||||
cldefines[cldefines_index++] = s;
|
||||
cldefines[cldefines_index++] = value;
|
||||
}
|
||||
|
||||
void
|
||||
opt_ParseDefines()
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < cldefines_index; i += 2)
|
||||
{
|
||||
sym_AddString(cldefines[i], cldefines[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Error handling
|
||||
*/
|
||||
void
|
||||
verror(const char *fmt, va_list args)
|
||||
{
|
||||
fprintf(stderr, "ERROR:\t");
|
||||
fstk_Dump();
|
||||
printf(" :\n\t%s\n", s);
|
||||
fprintf(stderr, " :\n\t");
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
nErrors += 1;
|
||||
}
|
||||
|
||||
void
|
||||
fatalerror(char *s)
|
||||
yyerror(const char *fmt, ...)
|
||||
{
|
||||
yyerror(s);
|
||||
exit(5);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
verror(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* Help text
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
PrintUsage(void)
|
||||
fatalerror(const char *fmt, ...)
|
||||
{
|
||||
printf("RGBAsm v" ASM_VERSION " (part of ASMotor " ASMOTOR_VERSION
|
||||
")\n\n");
|
||||
printf("Usage: rgbasm [-b chars] [-g chars] [-i path] [-o outfile] [-p pad_value] file\n");
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
verror(fmt, args);
|
||||
va_end(args);
|
||||
exit(5);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: rgbasm [-hv] [-b chars] [-Dname[=value]] [-g chars] [-i path]\n"
|
||||
" [-o outfile] [-p pad_value] file.asm\n");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* main
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
@@ -256,8 +272,18 @@ main(int argc, char *argv[])
|
||||
|
||||
char *tzMainfile;
|
||||
|
||||
cldefines_size = 32;
|
||||
cldefines = reallocarray(cldefines, cldefines_size,
|
||||
2 * sizeof(void *));
|
||||
if(!cldefines)
|
||||
{
|
||||
fatalerror("No memory for command line defines");
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
PrintUsage();
|
||||
usage();
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
/* yydebug=1; */
|
||||
|
||||
@@ -268,22 +294,27 @@ main(int argc, char *argv[])
|
||||
DefaultOptions.binary[0] = '0';
|
||||
DefaultOptions.binary[1] = '1';
|
||||
DefaultOptions.fillchar = 0;
|
||||
DefaultOptions.verbose = false;
|
||||
DefaultOptions.haltnop = true;
|
||||
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
newopt = CurrentOptions;
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:g:i:o:p:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "b:D:g:hi:o:p:v")) != -1) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
if (strlen(optarg) == 2) {
|
||||
newopt.binary[0] = optarg[1];
|
||||
newopt.binary[1] = optarg[2];
|
||||
} else {
|
||||
fprintf(stderr, "Must specify exactly "
|
||||
"2 characters for option 'b'\n");
|
||||
exit(1);
|
||||
errx(1, "Must specify exactly 2 characters for "
|
||||
"option 'b'");
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
opt_AddDefine(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
if (strlen(optarg) == 4) {
|
||||
newopt.gbgfx[0] = optarg[1];
|
||||
@@ -291,11 +322,13 @@ main(int argc, char *argv[])
|
||||
newopt.gbgfx[2] = optarg[3];
|
||||
newopt.gbgfx[3] = optarg[4];
|
||||
} else {
|
||||
fprintf(stderr, "Must specify exactly "
|
||||
"4 characters for option 'g'\n");
|
||||
exit(1);
|
||||
errx(1, "Must specify exactly 4 characters for "
|
||||
"option 'g'");
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
newopt.haltnop = false;
|
||||
break;
|
||||
case 'i':
|
||||
fstk_AddIncludePath(optarg);
|
||||
break;
|
||||
@@ -305,18 +338,18 @@ main(int argc, char *argv[])
|
||||
case 'p':
|
||||
newopt.fillchar = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
fprintf(stderr,
|
||||
"Invalid argument for option 'p'\n");
|
||||
exit(1);
|
||||
errx(1, "Invalid argument for option 'p'");
|
||||
}
|
||||
if (newopt.fillchar < 0 || newopt.fillchar > 0xFF) {
|
||||
fprintf(stderr, "Argument for option 'p' "
|
||||
"must be between 0 and 0xFF\n");
|
||||
exit(1);
|
||||
errx(1, "Argument for option 'p' must be "
|
||||
"between 0 and 0xFF");
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
newopt.verbose = true;
|
||||
break;
|
||||
default:
|
||||
PrintUsage();
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
@@ -326,12 +359,16 @@ main(int argc, char *argv[])
|
||||
|
||||
DefaultOptions = CurrentOptions;
|
||||
|
||||
/* tzMainfile=argv[argn++]; argc-=1; */
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
tzMainfile = argv[argc - 1];
|
||||
|
||||
setuplex();
|
||||
|
||||
printf("Assembling %s\n", tzMainfile);
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Assembling %s\n", tzMainfile);
|
||||
}
|
||||
|
||||
nStartClock = clock();
|
||||
|
||||
@@ -342,69 +379,59 @@ main(int argc, char *argv[])
|
||||
nPass = 1;
|
||||
nErrors = 0;
|
||||
sym_PrepPass1();
|
||||
if (fstk_Init(tzMainfile)) {
|
||||
fstk_Init(tzMainfile);
|
||||
opt_ParseDefines();
|
||||
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Pass 1...\n");
|
||||
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
if (yyparse() == 0 && nErrors == 0) {
|
||||
if (nIFDepth == 0) {
|
||||
nTotalLines = 0;
|
||||
nLineNo = 1;
|
||||
nIFDepth = 0;
|
||||
nPC = 0;
|
||||
nPass = 2;
|
||||
nErrors = 0;
|
||||
sym_PrepPass2();
|
||||
out_PrepPass2();
|
||||
fstk_Init(tzMainfile);
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
printf("Pass 2...\n");
|
||||
|
||||
if (yyparse() == 0 && nErrors == 0) {
|
||||
double timespent;
|
||||
|
||||
nEndClock = clock();
|
||||
timespent =
|
||||
((double) (nEndClock - nStartClock))
|
||||
/ (double) CLOCKS_PER_SEC;
|
||||
printf
|
||||
("Success! %ld lines in %d.%02d seconds ",
|
||||
nTotalLines, (int) timespent,
|
||||
((int) (timespent * 100.0)) % 100);
|
||||
if (timespent == 0)
|
||||
printf
|
||||
("(INFINITY lines/minute)\n");
|
||||
else
|
||||
printf("(%d lines/minute)\n",
|
||||
(int) (60 / timespent *
|
||||
nTotalLines));
|
||||
out_WriteObject();
|
||||
} else {
|
||||
printf
|
||||
("Assembly aborted in pass 2 (%ld errors)!\n",
|
||||
nErrors);
|
||||
//sym_PrintSymbolTable();
|
||||
exit(5);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Unterminated IF construct (%ld levels)!\n",
|
||||
nIFDepth);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Assembly aborted in pass 1 (%ld errors)!\n",
|
||||
nErrors);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
printf("File '%s' not found\n", tzMainfile);
|
||||
exit(5);
|
||||
}
|
||||
return (0);
|
||||
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
if (yyparse() != 0 || nErrors != 0) {
|
||||
errx(1, "Assembly aborted in pass 1 (%ld errors)!", nErrors);
|
||||
}
|
||||
|
||||
if (nIFDepth != 0) {
|
||||
errx(1, "Unterminated IF construct (%ld levels)!", nIFDepth);
|
||||
}
|
||||
|
||||
nTotalLines = 0;
|
||||
nLineNo = 1;
|
||||
nIFDepth = 0;
|
||||
nPC = 0;
|
||||
nPass = 2;
|
||||
nErrors = 0;
|
||||
sym_PrepPass2();
|
||||
out_PrepPass2();
|
||||
fstk_Init(tzMainfile);
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
opt_ParseDefines();
|
||||
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Pass 2...\n");
|
||||
}
|
||||
|
||||
if (yyparse() != 0 || nErrors != 0) {
|
||||
errx(1, "Assembly aborted in pass 2 (%ld errors)!", nErrors);
|
||||
}
|
||||
|
||||
double timespent;
|
||||
|
||||
nEndClock = clock();
|
||||
timespent = ((double)(nEndClock - nStartClock))
|
||||
/ (double)CLOCKS_PER_SEC;
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Success! %ld lines in %d.%02d seconds ", nTotalLines,
|
||||
(int) timespent, ((int) (timespent * 100.0)) % 100);
|
||||
if (timespent == 0)
|
||||
printf("(INFINITY lines/minute)\n");
|
||||
else
|
||||
printf("(%d lines/minute)\n",
|
||||
(int) (60 / timespent * nTotalLines));
|
||||
}
|
||||
out_WriteObject();
|
||||
return 0;
|
||||
}
|
||||
|
||||
128
src/asm/math.c
128
src/asm/math.c
@@ -1,14 +1,11 @@
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* Fixedpoint math routines
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
#include "asm/mymath.h"
|
||||
#include "asm/symbol.h"
|
||||
|
||||
@@ -19,24 +16,17 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Define the _PI symbol
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
math_DefinePI(void)
|
||||
{
|
||||
sym_AddEqu("_PI", double2fix(PI));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Print a fixed point value
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Print a fixed point value
|
||||
*/
|
||||
void
|
||||
math_Print(SLONG i)
|
||||
{
|
||||
@@ -47,112 +37,112 @@ math_Print(SLONG i)
|
||||
printf("-%ld.%05ld", (-i) >> 16,
|
||||
((SLONG) (fix2double(-i) * 100000 + 0.5)) % 100000);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Calculate sine
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate sine
|
||||
*/
|
||||
SLONG
|
||||
math_Sin(SLONG i)
|
||||
{
|
||||
return (double2fix(sin(fix2double(i) * 2 * PI / 65536)));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Calculate cosine
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate cosine
|
||||
*/
|
||||
SLONG
|
||||
math_Cos(SLONG i)
|
||||
{
|
||||
return (double2fix(cos(fix2double(i) * 2 * PI / 65536)));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Calculate tangent
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate tangent
|
||||
*/
|
||||
SLONG
|
||||
math_Tan(SLONG i)
|
||||
{
|
||||
return (double2fix(tan(fix2double(i) * 2 * PI / 65536)));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Calculate sine^-1
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate arcsine
|
||||
*/
|
||||
SLONG
|
||||
math_ASin(SLONG i)
|
||||
{
|
||||
return (double2fix(asin(fix2double(i)) / 2 / PI * 65536));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Calculate cosine^-1
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate arccosine
|
||||
*/
|
||||
SLONG
|
||||
math_ACos(SLONG i)
|
||||
{
|
||||
return (double2fix(acos(fix2double(i)) / 2 / PI * 65536));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Calculate tangent^-1
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate arctangent
|
||||
*/
|
||||
SLONG
|
||||
math_ATan(SLONG i)
|
||||
{
|
||||
return (double2fix(atan(fix2double(i)) / 2 / PI * 65536));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Calculate atan2
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate atan2
|
||||
*/
|
||||
SLONG
|
||||
math_ATan2(SLONG i, SLONG j)
|
||||
{
|
||||
return (double2fix
|
||||
(atan2(fix2double(i), fix2double(j)) / 2 / PI * 65536));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Multiplication
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Multiplication
|
||||
*/
|
||||
SLONG
|
||||
math_Mul(SLONG i, SLONG j)
|
||||
{
|
||||
return (double2fix(fix2double(i) * fix2double(j)));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Division
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Division
|
||||
*/
|
||||
SLONG
|
||||
math_Div(SLONG i, SLONG j)
|
||||
{
|
||||
return (double2fix(fix2double(i) / fix2double(j)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Round
|
||||
*/
|
||||
SLONG
|
||||
math_Round(SLONG i)
|
||||
{
|
||||
return double2fix(round(fix2double(i)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ceil
|
||||
*/
|
||||
SLONG
|
||||
math_Ceil(SLONG i)
|
||||
{
|
||||
return double2fix(ceil(fix2double(i)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Floor
|
||||
*/
|
||||
SLONG
|
||||
math_Floor(SLONG i)
|
||||
{
|
||||
return double2fix(floor(fix2double(i)));
|
||||
}
|
||||
|
||||
547
src/asm/output.c
547
src/asm/output.c
@@ -1,31 +1,24 @@
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* Outputs an objectfile
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/asm.h"
|
||||
#include "asm/charmap.h"
|
||||
#include "asm/output.h"
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/mylink.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/rpn.h"
|
||||
#include "asm/fstack.h"
|
||||
#include "extern/err.h"
|
||||
|
||||
#define SECTIONCHUNK 0x4000
|
||||
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Internal structures
|
||||
*
|
||||
*/
|
||||
|
||||
void out_SetCurrentSection(struct Section * pSect);
|
||||
|
||||
struct Patch {
|
||||
@@ -42,39 +35,30 @@ struct PatchSymbol {
|
||||
ULONG ID;
|
||||
struct sSymbol *pSymbol;
|
||||
struct PatchSymbol *pNext;
|
||||
struct PatchSymbol *pBucketNext; // next symbol in hash table bucket
|
||||
};
|
||||
|
||||
struct SectionStackEntry {
|
||||
struct Section *pSection;
|
||||
struct SectionStackEntry *pNext;
|
||||
};
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
*/
|
||||
|
||||
struct PatchSymbol *tHashedPatchSymbols[HASHSIZE];
|
||||
struct Section *pSectionList = NULL, *pCurrentSection = NULL;
|
||||
struct PatchSymbol *pPatchSymbols = NULL;
|
||||
char tzObjectname[_MAX_PATH];
|
||||
struct PatchSymbol **ppPatchSymbolsTail = &pPatchSymbols;
|
||||
char *tzObjectname;
|
||||
struct SectionStackEntry *pSectionStack = NULL;
|
||||
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Section stack routines
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
out_PushSection(void)
|
||||
{
|
||||
struct SectionStackEntry *pSect;
|
||||
|
||||
if ((pSect =
|
||||
(struct SectionStackEntry *)
|
||||
malloc(sizeof(struct SectionStackEntry))) != NULL) {
|
||||
if ((pSect = malloc(sizeof(struct SectionStackEntry))) != NULL) {
|
||||
pSect->pSection = pCurrentSection;
|
||||
pSect->pNext = pSectionStack;
|
||||
pSectionStack = pSect;
|
||||
@@ -95,13 +79,10 @@ out_PopSection(void)
|
||||
} else
|
||||
fatalerror("No entries in the section stack");
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Count the number of symbols used in this object
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Count the number of symbols used in this object
|
||||
*/
|
||||
ULONG
|
||||
countsymbols(void)
|
||||
{
|
||||
@@ -117,13 +98,10 @@ countsymbols(void)
|
||||
|
||||
return (count);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Count the number of sections used in this object
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Count the number of sections used in this object
|
||||
*/
|
||||
ULONG
|
||||
countsections(void)
|
||||
{
|
||||
@@ -139,13 +117,10 @@ countsections(void)
|
||||
|
||||
return (count);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Count the number of patches used in this object
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Count the number of patches used in this object
|
||||
*/
|
||||
ULONG
|
||||
countpatches(struct Section * pSect)
|
||||
{
|
||||
@@ -160,13 +135,10 @@ countpatches(struct Section * pSect)
|
||||
|
||||
return (r);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Write a long to a file (little-endian)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write a long to a file (little-endian)
|
||||
*/
|
||||
void
|
||||
fputlong(ULONG i, FILE * f)
|
||||
{
|
||||
@@ -175,13 +147,10 @@ fputlong(ULONG i, FILE * f)
|
||||
fputc(i >> 16, f);
|
||||
fputc(i >> 24, f);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Write a NULL-terminated string to a file
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write a NULL-terminated string to a file
|
||||
*/
|
||||
void
|
||||
fputstring(char *s, FILE * f)
|
||||
{
|
||||
@@ -189,13 +158,10 @@ fputstring(char *s, FILE * f)
|
||||
fputc(*s++, f);
|
||||
fputc(0, f);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Return a sections ID
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return a section's ID
|
||||
*/
|
||||
ULONG
|
||||
getsectid(struct Section * pSect)
|
||||
{
|
||||
@@ -214,13 +180,10 @@ getsectid(struct Section * pSect)
|
||||
fatalerror("INTERNAL: Unknown section");
|
||||
return ((ULONG) - 1);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Write a patch to a file
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write a patch to a file
|
||||
*/
|
||||
void
|
||||
writepatch(struct Patch * pPatch, FILE * f)
|
||||
{
|
||||
@@ -231,13 +194,10 @@ writepatch(struct Patch * pPatch, FILE * f)
|
||||
fputlong(pPatch->nRPNSize, f);
|
||||
fwrite(pPatch->pRPN, 1, pPatch->nRPNSize, f);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Write a section to a file
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write a section to a file
|
||||
*/
|
||||
void
|
||||
writesection(struct Section * pSect, FILE * f)
|
||||
{
|
||||
@@ -251,8 +211,8 @@ writesection(struct Section * pSect, FILE * f)
|
||||
fputlong(pSect->nBank, f);
|
||||
//RGB1 addition
|
||||
|
||||
if ((pSect->nType == SECT_HOME)
|
||||
|| (pSect->nType == SECT_CODE)) {
|
||||
if ((pSect->nType == SECT_ROM0)
|
||||
|| (pSect->nType == SECT_ROMX)) {
|
||||
struct Patch *pPatch;
|
||||
|
||||
fwrite(pSect->tData, 1, pSect->nPC, f);
|
||||
@@ -265,13 +225,10 @@ writesection(struct Section * pSect, FILE * f)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Write a symbol to a file
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write a symbol to a file
|
||||
*/
|
||||
void
|
||||
writesymbol(struct sSymbol * pSym, FILE * f)
|
||||
{
|
||||
@@ -315,49 +272,43 @@ writesymbol(struct sSymbol * pSym, FILE * f)
|
||||
fputlong(offset, f);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Add a symbol to the object
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add a symbol to the object
|
||||
*/
|
||||
ULONG
|
||||
addsymbol(struct sSymbol * pSym)
|
||||
{
|
||||
struct PatchSymbol *pPSym, **ppPSym;
|
||||
ULONG ID = 0;
|
||||
static ULONG nextID = 0;
|
||||
ULONG hash;
|
||||
|
||||
pPSym = pPatchSymbols;
|
||||
ppPSym = &(pPatchSymbols);
|
||||
hash = calchash(pSym->tzName);
|
||||
ppPSym = &(tHashedPatchSymbols[hash]);
|
||||
|
||||
while (pPSym) {
|
||||
if (pSym == pPSym->pSymbol)
|
||||
return (pPSym->ID);
|
||||
ppPSym = &(pPSym->pNext);
|
||||
pPSym = pPSym->pNext;
|
||||
ID += 1;
|
||||
while ((*ppPSym) != NULL) {
|
||||
if (pSym == (*ppPSym)->pSymbol)
|
||||
return (*ppPSym)->ID;
|
||||
ppPSym = &((*ppPSym)->pBucketNext);
|
||||
}
|
||||
|
||||
if ((*ppPSym = pPSym =
|
||||
(struct PatchSymbol *) malloc(sizeof(struct PatchSymbol))) !=
|
||||
NULL) {
|
||||
if ((*ppPSym = pPSym = malloc(sizeof(struct PatchSymbol))) != NULL) {
|
||||
pPSym->pNext = NULL;
|
||||
pPSym->pBucketNext = NULL;
|
||||
pPSym->pSymbol = pSym;
|
||||
pPSym->ID = ID;
|
||||
return (ID);
|
||||
pPSym->ID = nextID++;
|
||||
} else
|
||||
fatalerror("No memory for patchsymbol");
|
||||
|
||||
return ((ULONG) - 1);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Add all exported symbols to the object
|
||||
*
|
||||
*/
|
||||
*ppPatchSymbolsTail = pPSym;
|
||||
ppPatchSymbolsTail = &(pPSym->pNext);
|
||||
|
||||
return pPSym->ID;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add all exported symbols to the object
|
||||
*/
|
||||
void
|
||||
addexports(void)
|
||||
{
|
||||
@@ -374,43 +325,30 @@ addexports(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Allocate a new patchstructure and link it into the list
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Allocate a new patchstructure and link it into the list
|
||||
*/
|
||||
struct Patch *
|
||||
allocpatch(void)
|
||||
{
|
||||
struct Patch *pPatch, **ppPatch;
|
||||
struct Patch *pPatch;
|
||||
|
||||
pPatch = pCurrentSection->pPatches;
|
||||
ppPatch = &(pCurrentSection->pPatches);
|
||||
|
||||
while (pPatch) {
|
||||
ppPatch = &(pPatch->pNext);
|
||||
pPatch = pPatch->pNext;
|
||||
}
|
||||
|
||||
if ((*ppPatch = pPatch =
|
||||
(struct Patch *) malloc(sizeof(struct Patch))) != NULL) {
|
||||
pPatch->pNext = NULL;
|
||||
if ((pPatch = malloc(sizeof(struct Patch))) != NULL) {
|
||||
pPatch->pNext = pCurrentSection->pPatches;
|
||||
pPatch->nRPNSize = 0;
|
||||
pPatch->pRPN = NULL;
|
||||
} else
|
||||
fatalerror("No memory for patch");
|
||||
|
||||
pCurrentSection->pPatches = pPatch;
|
||||
|
||||
return (pPatch);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Create a new patch (includes the rpn expr)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create a new patch (includes the rpn expr)
|
||||
*/
|
||||
void
|
||||
createpatch(ULONG type, struct Expression * expr)
|
||||
{
|
||||
@@ -448,7 +386,10 @@ createpatch(ULONG type, struct Expression * expr)
|
||||
rpnexpr[rpnptr++] = value >> 16;
|
||||
rpnexpr[rpnptr++] = value >> 24;
|
||||
} else {
|
||||
symptr = addsymbol(sym_FindSymbol(tzSym));
|
||||
struct sSymbol *sym;
|
||||
if ((sym = sym_FindSymbol(tzSym)) == NULL)
|
||||
break;
|
||||
symptr = addsymbol(sym);
|
||||
rpnexpr[rpnptr++] = RPN_SYM;
|
||||
rpnexpr[rpnptr++] = symptr & 0xFF;
|
||||
rpnexpr[rpnptr++] = symptr >> 8;
|
||||
@@ -456,33 +397,34 @@ createpatch(ULONG type, struct Expression * expr)
|
||||
rpnexpr[rpnptr++] = symptr >> 24;
|
||||
}
|
||||
break;
|
||||
case RPN_BANK:
|
||||
case RPN_BANK: {
|
||||
struct sSymbol *sym;
|
||||
symptr = 0;
|
||||
while ((tzSym[symptr++] = rpn_PopByte(expr)) != 0);
|
||||
symptr = addsymbol(sym_FindSymbol(tzSym));
|
||||
if ((sym = sym_FindSymbol(tzSym)) == NULL)
|
||||
break;
|
||||
symptr = addsymbol(sym);
|
||||
rpnexpr[rpnptr++] = RPN_BANK;
|
||||
rpnexpr[rpnptr++] = symptr & 0xFF;
|
||||
rpnexpr[rpnptr++] = symptr >> 8;
|
||||
rpnexpr[rpnptr++] = symptr >> 16;
|
||||
rpnexpr[rpnptr++] = symptr >> 24;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
rpnexpr[rpnptr++] = rpndata;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((pPatch->pRPN = (UBYTE *) malloc(rpnptr)) != NULL) {
|
||||
if ((pPatch->pRPN = malloc(rpnptr)) != NULL) {
|
||||
memcpy(pPatch->pRPN, rpnexpr, rpnptr);
|
||||
pPatch->nRPNSize = rpnptr;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* A quick check to see if we have an initialized section
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* A quick check to see if we have an initialized section
|
||||
*/
|
||||
void
|
||||
checksection(void)
|
||||
{
|
||||
@@ -491,47 +433,49 @@ checksection(void)
|
||||
else
|
||||
fatalerror("Code generation before SECTION directive");
|
||||
}
|
||||
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* A quick check to see if we have an initialized section that can contain
|
||||
* this much initialized data
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
checkcodesection(SLONG size)
|
||||
{
|
||||
checksection();
|
||||
if ((pCurrentSection->nType == SECT_HOME
|
||||
|| pCurrentSection->nType == SECT_CODE)
|
||||
&& (pCurrentSection->nPC + size <= MAXSECTIONSIZE)) {
|
||||
if (((pCurrentSection->nPC % SECTIONCHUNK) >
|
||||
((pCurrentSection->nPC + size) % SECTIONCHUNK))
|
||||
&& (pCurrentSection->nType == SECT_HOME
|
||||
|| pCurrentSection->nType == SECT_CODE)) {
|
||||
if ((pCurrentSection->tData =
|
||||
(UBYTE *) realloc(pCurrentSection->tData,
|
||||
((pCurrentSection->nPC +
|
||||
size) / SECTIONCHUNK +
|
||||
1) * SECTIONCHUNK)) != NULL) {
|
||||
return;
|
||||
} else
|
||||
fatalerror
|
||||
("Not enough memory to expand section");
|
||||
}
|
||||
return;
|
||||
} else
|
||||
fatalerror
|
||||
("Section can't contain initialized data or section limit exceeded");
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Write an objectfile
|
||||
*
|
||||
*/
|
||||
if (pCurrentSection->nType != SECT_ROM0 &&
|
||||
pCurrentSection->nType != SECT_ROMX) {
|
||||
errx(1, "Section '%s' cannot contain code or data (not a "
|
||||
"ROM0 or ROMX)", pCurrentSection->pzName);
|
||||
}
|
||||
if (pCurrentSection->nPC + size > MAXSECTIONSIZE) {
|
||||
/*
|
||||
* N.B.: This check is not sufficient to ensure the section
|
||||
* will fit, because there can be multiple sections of this
|
||||
* type. The definitive check must be done at the linking
|
||||
* stage.
|
||||
*/
|
||||
errx(1, "Section '%s' is too big (old size %d + %d > %d)",
|
||||
pCurrentSection->pzName, pCurrentSection->nPC, size,
|
||||
MAXSECTIONSIZE);
|
||||
}
|
||||
if (((pCurrentSection->nPC % SECTIONCHUNK) >
|
||||
((pCurrentSection->nPC + size) % SECTIONCHUNK)) &&
|
||||
(pCurrentSection->nType == SECT_ROM0 ||
|
||||
pCurrentSection->nType == SECT_ROMX)) {
|
||||
pCurrentSection->tData = realloc(pCurrentSection->tData,
|
||||
((pCurrentSection->nPC + size) / SECTIONCHUNK + 1) *
|
||||
SECTIONCHUNK);
|
||||
|
||||
if (pCurrentSection->tData == NULL) {
|
||||
err(1, "Could not expand section");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write an objectfile
|
||||
*/
|
||||
void
|
||||
out_WriteObject(void)
|
||||
{
|
||||
@@ -562,13 +506,10 @@ out_WriteObject(void)
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Prepare for pass #2
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Prepare for pass #2
|
||||
*/
|
||||
void
|
||||
out_PrepPass2(void)
|
||||
{
|
||||
@@ -582,32 +523,27 @@ out_PrepPass2(void)
|
||||
pCurrentSection = NULL;
|
||||
pSectionStack = NULL;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Set the objectfilename
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the objectfilename
|
||||
*/
|
||||
void
|
||||
out_SetFileName(char *s)
|
||||
{
|
||||
strcpy(tzObjectname, s);
|
||||
printf("Output filename %s\n", s);
|
||||
tzObjectname = s;
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Output filename %s\n", s);
|
||||
}
|
||||
pSectionList = NULL;
|
||||
pCurrentSection = NULL;
|
||||
pPatchSymbols = NULL;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Find a section by name and type. If it doesn't exist, create it
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find a section by name and type. If it doesn't exist, create it
|
||||
*/
|
||||
struct Section *
|
||||
out_FindSection(char *pzName, ULONG secttype, SLONG org,
|
||||
SLONG bank)
|
||||
out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
|
||||
{
|
||||
struct Section *pSect, **ppSect;
|
||||
|
||||
@@ -628,11 +564,8 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org,
|
||||
pSect = pSect->pNext;
|
||||
}
|
||||
|
||||
if ((*ppSect =
|
||||
(pSect =
|
||||
(struct Section *) malloc(sizeof(struct Section)))) != NULL) {
|
||||
if ((pSect->pzName =
|
||||
(char *) malloc(strlen(pzName) + 1)) != NULL) {
|
||||
if ((*ppSect = (pSect = malloc(sizeof(struct Section)))) != NULL) {
|
||||
if ((pSect->pzName = malloc(strlen(pzName) + 1)) != NULL) {
|
||||
strcpy(pSect->pzName, pzName);
|
||||
pSect->nType = secttype;
|
||||
pSect->nPC = 0;
|
||||
@@ -640,10 +573,10 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org,
|
||||
pSect->nBank = bank;
|
||||
pSect->pNext = NULL;
|
||||
pSect->pPatches = NULL;
|
||||
pSect->charmap = NULL;
|
||||
pPatchSymbols = NULL;
|
||||
|
||||
if ((pSect->tData =
|
||||
(UBYTE *) malloc(SECTIONCHUNK)) != NULL) {
|
||||
if ((pSect->tData = malloc(SECTIONCHUNK)) != NULL) {
|
||||
return (pSect);
|
||||
} else
|
||||
fatalerror("Not enough memory for section");
|
||||
@@ -654,13 +587,10 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org,
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Set the current section
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the current section
|
||||
*/
|
||||
void
|
||||
out_SetCurrentSection(struct Section * pSect)
|
||||
{
|
||||
@@ -670,37 +600,28 @@ out_SetCurrentSection(struct Section * pSect)
|
||||
pPCSymbol->nValue = nPC;
|
||||
pPCSymbol->pSection = pCurrentSection;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Set the current section by name and type
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the current section by name and type
|
||||
*/
|
||||
void
|
||||
out_NewSection(char *pzName, ULONG secttype)
|
||||
{
|
||||
out_SetCurrentSection(out_FindSection(pzName, secttype, -1, -1));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Set the current section by name and type
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the current section by name and type
|
||||
*/
|
||||
void
|
||||
out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
|
||||
{
|
||||
out_SetCurrentSection(out_FindSection(pzName, secttype, org, bank));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output an absolute byte
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output an absolute byte
|
||||
*/
|
||||
void
|
||||
out_AbsByte(int b)
|
||||
{
|
||||
@@ -713,19 +634,24 @@ out_AbsByte(int b)
|
||||
nPC += 1;
|
||||
pPCSymbol->nValue += 1;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Skip this many bytes
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
out_AbsByteGroup(char *s, int length)
|
||||
{
|
||||
checkcodesection(length);
|
||||
while (length--)
|
||||
out_AbsByte(*s++);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip this many bytes
|
||||
*/
|
||||
void
|
||||
out_Skip(int skip)
|
||||
{
|
||||
checksection();
|
||||
if (!((pCurrentSection->nType == SECT_HOME)
|
||||
|| (pCurrentSection->nType == SECT_CODE))) {
|
||||
if (!((pCurrentSection->nType == SECT_ROM0)
|
||||
|| (pCurrentSection->nType == SECT_ROMX))) {
|
||||
pCurrentSection->nPC += skip;
|
||||
nPC += skip;
|
||||
pPCSymbol->nValue += skip;
|
||||
@@ -735,13 +661,10 @@ out_Skip(int skip)
|
||||
out_AbsByte(CurrentOptions.fillchar);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output a NULL terminated string (excluding the NULL-character)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output a NULL terminated string (excluding the NULL-character)
|
||||
*/
|
||||
void
|
||||
out_String(char *s)
|
||||
{
|
||||
@@ -749,12 +672,10 @@ out_String(char *s)
|
||||
while (*s)
|
||||
out_AbsByte(*s++);
|
||||
}
|
||||
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output a relocatable byte. Checking will be done to see if it
|
||||
* is an absolute value in disguise.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
@@ -774,13 +695,10 @@ out_RelByte(struct Expression * expr)
|
||||
|
||||
rpn_Reset(expr);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output an absolute word
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output an absolute word
|
||||
*/
|
||||
void
|
||||
out_AbsWord(int b)
|
||||
{
|
||||
@@ -794,14 +712,11 @@ out_AbsWord(int b)
|
||||
nPC += 2;
|
||||
pPCSymbol->nValue += 2;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output a relocatable word. Checking will be done to see if
|
||||
* is an absolute value in disguise.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output a relocatable word. Checking will be done to see if
|
||||
* it's an absolute value in disguise.
|
||||
*/
|
||||
void
|
||||
out_RelWord(struct Expression * expr)
|
||||
{
|
||||
@@ -822,13 +737,10 @@ out_RelWord(struct Expression * expr)
|
||||
out_AbsWord(expr->nVal);
|
||||
rpn_Reset(expr);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output an absolute longword
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output an absolute longword
|
||||
*/
|
||||
void
|
||||
out_AbsLong(SLONG b)
|
||||
{
|
||||
@@ -843,14 +755,11 @@ out_AbsLong(SLONG b)
|
||||
nPC += 4;
|
||||
pPCSymbol->nValue += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output a relocatable longword. Checking will be done to see if
|
||||
* is an absolute value in disguise.
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
out_RelLong(struct Expression * expr)
|
||||
{
|
||||
@@ -873,13 +782,10 @@ out_RelLong(struct Expression * expr)
|
||||
out_AbsLong(expr->nVal);
|
||||
rpn_Reset(expr);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output a PC-relative byte
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output a PC-relative byte
|
||||
*/
|
||||
void
|
||||
out_PCRelByte(struct Expression * expr)
|
||||
{
|
||||
@@ -893,42 +799,39 @@ out_PCRelByte(struct Expression * expr)
|
||||
out_AbsByte(b);
|
||||
rpn_Reset(expr);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Output a binary file
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output a binary file
|
||||
*/
|
||||
void
|
||||
out_BinaryFile(char *s)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
fstk_FindFile(s);
|
||||
f = fstk_FindFile(s);
|
||||
if (f == NULL) {
|
||||
err(1, "Unable to open incbin file '%s'", s);
|
||||
}
|
||||
|
||||
if ((f = fopen(s, "rb")) != NULL) {
|
||||
SLONG fsize;
|
||||
SLONG fsize;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
checkcodesection(fsize);
|
||||
checkcodesection(fsize);
|
||||
|
||||
if (nPass == 2) {
|
||||
SLONG dest = nPC;
|
||||
SLONG todo = fsize;
|
||||
if (nPass == 2) {
|
||||
SLONG dest = nPC;
|
||||
SLONG todo = fsize;
|
||||
|
||||
while (todo--)
|
||||
pCurrentSection->tData[dest++] = fgetc(f);
|
||||
}
|
||||
pCurrentSection->nPC += fsize;
|
||||
nPC += fsize;
|
||||
pPCSymbol->nValue += fsize;
|
||||
fclose(f);
|
||||
} else
|
||||
fatalerror("File not found");
|
||||
while (todo--)
|
||||
pCurrentSection->tData[dest++] = fgetc(f);
|
||||
}
|
||||
pCurrentSection->nPC += fsize;
|
||||
nPC += fsize;
|
||||
pPCSymbol->nValue += fsize;
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -942,36 +845,36 @@ out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length)
|
||||
if (length < 0)
|
||||
fatalerror("Number of bytes to read must be greater than zero");
|
||||
|
||||
fstk_FindFile(s);
|
||||
f = fstk_FindFile(s);
|
||||
if (f == NULL) {
|
||||
err(1, "Unable to open included file '%s'", s);
|
||||
}
|
||||
|
||||
if ((f = fopen(s, "rb")) != NULL) {
|
||||
SLONG fsize;
|
||||
SLONG fsize;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
fsize = ftell(f);
|
||||
|
||||
if (start_pos >= fsize)
|
||||
fatalerror("Specified start position is greater than length of file");
|
||||
if (start_pos >= fsize)
|
||||
fatalerror("Specified start position is greater than length of file");
|
||||
|
||||
if ((start_pos + length) > fsize)
|
||||
fatalerror("Specified range in INCBIN is out of bounds");
|
||||
if ((start_pos + length) > fsize)
|
||||
fatalerror("Specified range in INCBIN is out of bounds");
|
||||
|
||||
fseek(f, start_pos, SEEK_SET);
|
||||
fseek(f, start_pos, SEEK_SET);
|
||||
|
||||
checkcodesection(length);
|
||||
checkcodesection(length);
|
||||
|
||||
if (nPass == 2) {
|
||||
SLONG dest = nPC;
|
||||
SLONG todo = length;
|
||||
if (nPass == 2) {
|
||||
SLONG dest = nPC;
|
||||
SLONG todo = length;
|
||||
|
||||
while (todo--)
|
||||
pCurrentSection->tData[dest++] = fgetc(f);
|
||||
}
|
||||
pCurrentSection->nPC += length;
|
||||
nPC += length;
|
||||
pPCSymbol->nValue += length;
|
||||
while (todo--)
|
||||
pCurrentSection->tData[dest++] = fgetc(f);
|
||||
}
|
||||
pCurrentSection->nPC += length;
|
||||
nPC += length;
|
||||
pPCSymbol->nValue += length;
|
||||
|
||||
fclose(f);
|
||||
} else
|
||||
fatalerror("File not found");
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dd February 26, 2015
|
||||
.Dt RGBASM 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
@@ -6,7 +6,9 @@
|
||||
.Nd Game Boy assembler
|
||||
.Sh SYNOPSIS
|
||||
.Nm rgbasm
|
||||
.Op Fl hv
|
||||
.Op Fl b Ar chars
|
||||
.Op Fl D Ar name Ns Op = Ns Ar value
|
||||
.Op Fl g Ar chars
|
||||
.Op Fl i Ar path
|
||||
.Op Fl o Ar outfile
|
||||
@@ -21,9 +23,26 @@ Its arguments are as follows:
|
||||
.It Fl b Ar chars
|
||||
Change the two characters used for binary constants.
|
||||
The defaults are 01.
|
||||
.It Fl D Ar name Ns Op = Ns Ar value
|
||||
Add string symbol to the compiled source code. This is equivalent to
|
||||
.Ar name
|
||||
.Cm EQUS
|
||||
.Qq Ar "value"
|
||||
in code. If a value is not specified, a value of 1 is given.
|
||||
.It Fl g Ar chars
|
||||
Change the four characters used for binary constants.
|
||||
The defaults are 0123.
|
||||
.It Fl h
|
||||
By default,
|
||||
.Nm
|
||||
inserts a
|
||||
.Sq nop
|
||||
instruction immediately after any
|
||||
.Sq halt
|
||||
instruction.
|
||||
The
|
||||
.Fl h
|
||||
option disables this behavior.
|
||||
.It Fl i Ar path
|
||||
Add an include path.
|
||||
.It Fl o Ar outfile
|
||||
@@ -31,11 +50,13 @@ Write an object file to the given filename.
|
||||
.It Fl p Ar pad_value
|
||||
When padding an image, pad with this value.
|
||||
The default is 0x00.
|
||||
.It Fl v
|
||||
Be verbose.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
Assembling a basic source file is simple:
|
||||
.Pp
|
||||
.D1 $ rgbasm \-o bar.o foo.asm
|
||||
.D1 $ rgbasm -o bar.o foo.asm
|
||||
.Pp
|
||||
The resulting object file is not yet a usable ROM image \(em it must first be
|
||||
run through
|
||||
@@ -43,11 +64,9 @@ run through
|
||||
and
|
||||
.Xr rgbfix 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbds 7 ,
|
||||
.Xr rgbfix 1 ,
|
||||
.Xr rgblib 1 ,
|
||||
.Xr rgblink 1 ,
|
||||
.Xr gbz80 7
|
||||
.Xr rgbds 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally written by Carsten S\(/orensen as part of the ASMotor package,
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* Controls RPN expressions for objectfiles
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/mylink.h"
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/asm.h"
|
||||
#include "asm/main.h"
|
||||
@@ -29,49 +26,26 @@ mergetwoexpressions(struct Expression * expr, struct Expression * src1,
|
||||
#define joinexpr() mergetwoexpressions(expr,src1,src2)
|
||||
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
*/
|
||||
|
||||
//UBYTE rpnexpr[2048];
|
||||
//ULONG rpnptr = 0;
|
||||
//ULONG rpnoutptr = 0;
|
||||
//ULONG reloc = 0;
|
||||
//ULONG pcrel = 0;
|
||||
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* Add a byte to the RPN expression
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
pushbyte(struct Expression * expr, int b)
|
||||
{
|
||||
expr->tRPN[expr->nRPNLength++] = b & 0xFF;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* Reset the RPN module
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reset the RPN module
|
||||
*/
|
||||
void
|
||||
rpn_Reset(struct Expression * expr)
|
||||
{
|
||||
expr->nRPNLength = expr->nRPNOut = expr->isReloc = expr->isPCRel = 0;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* Returns the next rpn byte in expression
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Returns the next rpn byte in expression
|
||||
*/
|
||||
UWORD
|
||||
rpn_PopByte(struct Expression * expr)
|
||||
{
|
||||
@@ -80,37 +54,28 @@ rpn_PopByte(struct Expression * expr)
|
||||
} else
|
||||
return (expr->tRPN[expr->nRPNOut++]);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* Determine if the current expression is relocatable
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine if the current expression is relocatable
|
||||
*/
|
||||
ULONG
|
||||
rpn_isReloc(struct Expression * expr)
|
||||
{
|
||||
return (expr->isReloc);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* Determine if the current expression can be pc-relative
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine if the current expression can be pc-relative
|
||||
*/
|
||||
ULONG
|
||||
rpn_isPCRelative(struct Expression * expr)
|
||||
{
|
||||
return (expr->isPCRel);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - RPN.C - Controls RPN expressions for objectfiles
|
||||
*
|
||||
* Add symbols, constants and operators to expression
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add symbols, constants and operators to expression
|
||||
*/
|
||||
void
|
||||
rpn_Number(struct Expression * expr, ULONG i)
|
||||
{
|
||||
@@ -155,8 +120,7 @@ rpn_Bank(struct Expression * expr, char *tzSym)
|
||||
|
||||
psym = sym_FindSymbol(tzSym);
|
||||
if (nPass == 2 && psym == NULL) {
|
||||
sprintf(temptext, "'%s' not defined", tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' not defined", tzSym);
|
||||
}
|
||||
expr->isReloc = 1;
|
||||
pushbyte(expr, RPN_BANK);
|
||||
@@ -188,6 +152,7 @@ rpn_RangeCheck(struct Expression * expr, struct Expression * src, SLONG low,
|
||||
return (expr->nVal >= low && expr->nVal <= high);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rpn_CheckHRAM(struct Expression * expr, struct Expression * src)
|
||||
{
|
||||
|
||||
427
src/asm/symbol.c
427
src/asm/symbol.c
@@ -1,10 +1,8 @@
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable and macroargs stuff
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* Symboltable and macroargs stuff
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -15,18 +13,10 @@
|
||||
#include "asm/mymath.h"
|
||||
#include "asm/output.h"
|
||||
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
*/
|
||||
|
||||
struct sSymbol *tHashedSymbols[HASHSIZE];
|
||||
struct sSymbol *pScope = NULL;
|
||||
struct sSymbol *pPCSymbol = NULL;
|
||||
struct sSymbol *p_NARGSymbol = NULL;
|
||||
struct sSymbol *p__LINE__Symbol = NULL;
|
||||
char *currentmacroargs[MAXMACROARGS + 1];
|
||||
char *newmacroargs[MAXMACROARGS + 1];
|
||||
char SavedTIME[256];
|
||||
@@ -37,26 +27,15 @@ Callback_NARG(struct sSymbol * sym)
|
||||
{
|
||||
ULONG i = 0;
|
||||
|
||||
sym = sym;
|
||||
while (currentmacroargs[i] && i < MAXMACROARGS)
|
||||
i += 1;
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
SLONG
|
||||
Callback__LINE__(struct sSymbol * sym)
|
||||
{
|
||||
sym = sym;
|
||||
return (nLineNo);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Get the nValue field of a symbol
|
||||
*
|
||||
*/
|
||||
|
||||
SLONG
|
||||
getvaluefield(struct sSymbol * sym)
|
||||
{
|
||||
@@ -65,30 +44,24 @@ getvaluefield(struct sSymbol * sym)
|
||||
} else
|
||||
return (sym->nValue);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Calculate the hash value for a string
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Calculate the hash value for a string
|
||||
*/
|
||||
ULONG
|
||||
calchash(char *s)
|
||||
{
|
||||
ULONG hash = 0;
|
||||
ULONG hash = 5381;
|
||||
|
||||
while (*s != 0)
|
||||
hash += (*s++);
|
||||
hash = (hash * 33) ^ (*s++);
|
||||
|
||||
return (hash % HASHSIZE);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Create a new symbol by name
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Create a new symbol by name
|
||||
*/
|
||||
struct sSymbol *
|
||||
createsymbol(char *s)
|
||||
{
|
||||
@@ -101,8 +74,7 @@ createsymbol(char *s)
|
||||
while ((*ppsym) != NULL)
|
||||
ppsym = &((*ppsym)->pNext);
|
||||
|
||||
if (((*ppsym) =
|
||||
(struct sSymbol *) malloc(sizeof(struct sSymbol))) != NULL) {
|
||||
if (((*ppsym) = malloc(sizeof(struct sSymbol))) != NULL) {
|
||||
strcpy((*ppsym)->tzName, s);
|
||||
(*ppsym)->nValue = 0;
|
||||
(*ppsym)->nType = 0;
|
||||
@@ -118,12 +90,8 @@ createsymbol(char *s)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Find a symbol by name and scope
|
||||
*
|
||||
*/
|
||||
|
||||
struct sSymbol *
|
||||
findsymbol(char *s, struct sSymbol * scope)
|
||||
{
|
||||
@@ -142,13 +110,10 @@ findsymbol(char *s, struct sSymbol * scope)
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Find the pointer to a symbol by name and scope
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find the pointer to a symbol by name and scope
|
||||
*/
|
||||
struct sSymbol **
|
||||
findpsymbol(char *s, struct sSymbol * scope)
|
||||
{
|
||||
@@ -167,13 +132,10 @@ findpsymbol(char *s, struct sSymbol * scope)
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Find a symbol by name and scope
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find a symbol by name and scope
|
||||
*/
|
||||
struct sSymbol *
|
||||
sym_FindSymbol(char *tzName)
|
||||
{
|
||||
@@ -186,13 +148,10 @@ sym_FindSymbol(char *tzName)
|
||||
|
||||
return (findsymbol(tzName, pscope));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Purge a symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Purge a symbol
|
||||
*/
|
||||
void
|
||||
sym_Purge(char *tzName)
|
||||
{
|
||||
@@ -217,17 +176,13 @@ sym_Purge(char *tzName)
|
||||
|
||||
free(pSym);
|
||||
} else {
|
||||
sprintf(temptext, "'%s' not defined", tzName);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' not defined", tzName);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Determine if a symbol has been defined
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine if a symbol has been defined
|
||||
*/
|
||||
ULONG
|
||||
sym_isConstDefined(char *tzName)
|
||||
{
|
||||
@@ -245,10 +200,8 @@ sym_isConstDefined(char *tzName)
|
||||
nType & (SYMF_EQU | SYMF_SET | SYMF_MACRO | SYMF_STRING)) {
|
||||
return (1);
|
||||
} else {
|
||||
sprintf(temptext,
|
||||
"'%s' is not allowed as argument to the DEF function",
|
||||
tzName);
|
||||
fatalerror(temptext);
|
||||
fatalerror("'%s' is not allowed as argument to the "
|
||||
"DEF function", tzName);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
@@ -271,13 +224,10 @@ sym_isDefined(char *tzName)
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Determine if the symbol is a constant
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine if the symbol is a constant
|
||||
*/
|
||||
ULONG
|
||||
sym_isConstant(char *s)
|
||||
{
|
||||
@@ -294,13 +244,10 @@ sym_isConstant(char *s)
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Get a string equate's value
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Get a string equate's value
|
||||
*/
|
||||
char *
|
||||
sym_GetStringValue(char *tzSym)
|
||||
{
|
||||
@@ -309,19 +256,15 @@ sym_GetStringValue(char *tzSym)
|
||||
if ((pSym = sym_FindSymbol(tzSym)) != NULL)
|
||||
return (pSym->pMacro);
|
||||
else {
|
||||
sprintf(temptext, "Stringsymbol '%s' not defined", tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("Stringsymbol '%s' not defined", tzSym);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Return a constant symbols value
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return a constant symbols value
|
||||
*/
|
||||
ULONG
|
||||
sym_GetConstantValue(char *s)
|
||||
{
|
||||
@@ -339,19 +282,15 @@ sym_GetConstantValue(char *s)
|
||||
fatalerror("Expression must have a constant value");
|
||||
}
|
||||
} else {
|
||||
sprintf(temptext, "'%s' not defined", s);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' not defined", s);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Return a symbols value... "estimated" if not defined yet
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return a symbols value... "estimated" if not defined yet
|
||||
*/
|
||||
ULONG
|
||||
sym_GetValue(char *s)
|
||||
{
|
||||
@@ -365,39 +304,32 @@ sym_GetValue(char *s)
|
||||
if ((psym = findsymbol(s, pscope)) != NULL) {
|
||||
if (psym->nType & SYMF_DEFINED) {
|
||||
if (psym->nType & (SYMF_MACRO | SYMF_STRING)) {
|
||||
sprintf(temptext,
|
||||
"'%s' is a macro or string symbol", s);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' is a macro or string symbol", s);
|
||||
}
|
||||
return (getvaluefield(psym));
|
||||
} else {
|
||||
if ((nPass == 1) || (psym->nType & SYMF_IMPORT)) {
|
||||
/* 0x80 seems like a good default value... */
|
||||
return (0x80);
|
||||
} else {
|
||||
sprintf(temptext, "'%s' not defined", s);
|
||||
yyerror(temptext);
|
||||
if (nPass == 2) {
|
||||
/* Assume undefined symbols are imported from somewhere else */
|
||||
psym->nType |= SYMF_IMPORT;
|
||||
}
|
||||
/* 0x80 seems like a good default value... */
|
||||
return (0x80);
|
||||
}
|
||||
} else {
|
||||
if (nPass == 1) {
|
||||
createsymbol(s);
|
||||
return (0x80);
|
||||
} else {
|
||||
sprintf(temptext, "'%s' not defined", s);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' not defined", s);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Return a defined symbols value... aborts if not defined yet
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return a defined symbols value... aborts if not defined yet
|
||||
*/
|
||||
ULONG
|
||||
sym_GetDefinedValue(char *s)
|
||||
{
|
||||
@@ -411,29 +343,22 @@ sym_GetDefinedValue(char *s)
|
||||
if ((psym = findsymbol(s, pscope)) != NULL) {
|
||||
if ((psym->nType & SYMF_DEFINED)) {
|
||||
if (psym->nType & (SYMF_MACRO | SYMF_STRING)) {
|
||||
sprintf(temptext,
|
||||
"'%s' is a macro or string symbol", s);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' is a macro or string symbol", s);
|
||||
}
|
||||
return (getvaluefield(psym));
|
||||
} else {
|
||||
sprintf(temptext, "'%s' not defined", s);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' not defined", s);
|
||||
}
|
||||
} else {
|
||||
sprintf(temptext, "'%s' not defined", s);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' not defined", s);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Macro argument stuff
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Macro argument stuff
|
||||
*/
|
||||
void
|
||||
sym_ShiftCurrentMacroArgs(void)
|
||||
{
|
||||
@@ -452,6 +377,8 @@ sym_FindMacroArg(SLONG i)
|
||||
if (i == -1)
|
||||
i = MAXMACROARGS + 1;
|
||||
|
||||
assert(i-1 >= 0 &&
|
||||
i-1 < sizeof currentmacroargs / sizeof *currentmacroargs);
|
||||
return (currentmacroargs[i - 1]);
|
||||
}
|
||||
|
||||
@@ -509,7 +436,7 @@ sym_AddNewMacroArg(char *s)
|
||||
else
|
||||
newmacroargs[i] = NULL;
|
||||
} else
|
||||
yyerror("A maximum of 9 arguments allowed");
|
||||
yyerror("A maximum of %d arguments allowed", MAXMACROARGS);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -529,25 +456,19 @@ sym_UseCurrentMacroArgs(void)
|
||||
for (i = 1; i <= MAXMACROARGS; i += 1)
|
||||
sym_AddNewMacroArg(sym_FindMacroArg(i));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Find a macro by name
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find a macro by name
|
||||
*/
|
||||
struct sSymbol *
|
||||
sym_FindMacro(char *s)
|
||||
{
|
||||
return (findsymbol(s, NULL));
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Add an equated symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add an equated symbol
|
||||
*/
|
||||
void
|
||||
sym_AddEqu(char *tzSym, SLONG value)
|
||||
{
|
||||
@@ -558,9 +479,7 @@ sym_AddEqu(char *tzSym, SLONG value)
|
||||
|
||||
if ((nsym = findsymbol(tzSym, NULL)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED) {
|
||||
sprintf(temptext, "'%s' already defined",
|
||||
tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
} else
|
||||
nsym = createsymbol(tzSym);
|
||||
@@ -572,13 +491,10 @@ sym_AddEqu(char *tzSym, SLONG value)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Add a string equated symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add a string equated symbol
|
||||
*/
|
||||
void
|
||||
sym_AddString(char *tzSym, char *tzValue)
|
||||
{
|
||||
@@ -586,15 +502,13 @@ sym_AddString(char *tzSym, char *tzValue)
|
||||
|
||||
if ((nsym = findsymbol(tzSym, NULL)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED) {
|
||||
sprintf(temptext, "'%s' already defined", tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
} else
|
||||
nsym = createsymbol(tzSym);
|
||||
|
||||
if (nsym) {
|
||||
if ((nsym->pMacro =
|
||||
(char *) malloc(strlen(tzValue) + 1)) != NULL)
|
||||
if ((nsym->pMacro = malloc(strlen(tzValue) + 1)) != NULL)
|
||||
strcpy(nsym->pMacro, tzValue);
|
||||
else
|
||||
fatalerror("No memory for stringequate");
|
||||
@@ -603,13 +517,10 @@ sym_AddString(char *tzSym, char *tzValue)
|
||||
nsym->pScope = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* check if symbol is a string equated symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* check if symbol is a string equated symbol
|
||||
*/
|
||||
ULONG
|
||||
sym_isString(char *tzSym)
|
||||
{
|
||||
@@ -621,13 +532,10 @@ sym_isString(char *tzSym)
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Alter a SET symbols value
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Alter a SET symbols value
|
||||
*/
|
||||
void
|
||||
sym_AddSet(char *tzSym, SLONG value)
|
||||
{
|
||||
@@ -643,13 +551,10 @@ sym_AddSet(char *tzSym, SLONG value)
|
||||
nsym->pScope = NULL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Add a local (.name) relocatable symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add a local (.name) relocatable symbol
|
||||
*/
|
||||
void
|
||||
sym_AddLocalReloc(char *tzSym)
|
||||
{
|
||||
@@ -661,9 +566,7 @@ sym_AddLocalReloc(char *tzSym)
|
||||
if (pScope) {
|
||||
if ((nsym = findsymbol(tzSym, pScope)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED) {
|
||||
sprintf(temptext,
|
||||
"'%s' already defined", tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
} else
|
||||
nsym = createsymbol(tzSym);
|
||||
@@ -679,13 +582,10 @@ sym_AddLocalReloc(char *tzSym)
|
||||
fatalerror("Local label in main scope");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Add a relocatable symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add a relocatable symbol
|
||||
*/
|
||||
void
|
||||
sym_AddReloc(char *tzSym)
|
||||
{
|
||||
@@ -696,9 +596,7 @@ sym_AddReloc(char *tzSym)
|
||||
|
||||
if ((nsym = findsymbol(tzSym, NULL)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED) {
|
||||
sprintf(temptext, "'%s' already defined",
|
||||
tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
} else
|
||||
nsym = createsymbol(tzSym);
|
||||
@@ -711,15 +609,11 @@ sym_AddReloc(char *tzSym)
|
||||
}
|
||||
}
|
||||
pScope = findsymbol(tzSym, NULL);
|
||||
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Export a symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Export a symbol
|
||||
*/
|
||||
void
|
||||
sym_Export(char *tzSym)
|
||||
{
|
||||
@@ -739,18 +633,14 @@ sym_Export(char *tzSym)
|
||||
if (nsym->nType & SYMF_DEFINED)
|
||||
return;
|
||||
}
|
||||
sprintf(temptext, "'%s' not defined", tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' not defined", tzSym);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Import a symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Import a symbol
|
||||
*/
|
||||
void
|
||||
sym_Import(char *tzSym)
|
||||
{
|
||||
@@ -759,20 +649,16 @@ sym_Import(char *tzSym)
|
||||
struct sSymbol *nsym;
|
||||
|
||||
if (findsymbol(tzSym, NULL)) {
|
||||
sprintf(temptext, "'%s' already defined", tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
if ((nsym = createsymbol(tzSym)) != NULL)
|
||||
nsym->nType |= SYMF_IMPORT;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Globalize a symbol (export if defined, import if not)
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Globalize a symbol (export if defined, import if not)
|
||||
*/
|
||||
void
|
||||
sym_Global(char *tzSym)
|
||||
{
|
||||
@@ -794,13 +680,10 @@ sym_Global(char *tzSym)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Add a macro definition
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add a macro definition
|
||||
*/
|
||||
void
|
||||
sym_AddMacro(char *tzSym)
|
||||
{
|
||||
@@ -811,9 +694,7 @@ sym_AddMacro(char *tzSym)
|
||||
|
||||
if ((nsym = findsymbol(tzSym, NULL)) != NULL) {
|
||||
if (nsym->nType & SYMF_DEFINED) {
|
||||
sprintf(temptext, "'%s' already defined",
|
||||
tzSym);
|
||||
yyerror(temptext);
|
||||
yyerror("'%s' already defined", tzSym);
|
||||
}
|
||||
} else
|
||||
nsym = createsymbol(tzSym);
|
||||
@@ -827,25 +708,19 @@ sym_AddMacro(char *tzSym)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Prepare for pass #1
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Prepare for pass #1
|
||||
*/
|
||||
void
|
||||
sym_PrepPass1(void)
|
||||
{
|
||||
sym_Init();
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Prepare for pass #2
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Prepare for pass #2
|
||||
*/
|
||||
void
|
||||
sym_PrepPass2(void)
|
||||
{
|
||||
@@ -872,14 +747,17 @@ sym_PrepPass2(void)
|
||||
sym_AddString("__TIME__", SavedTIME);
|
||||
sym_AddString("__DATE__", SavedDATE);
|
||||
sym_AddSet("_RS", 0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Initialise the symboltable
|
||||
*
|
||||
*/
|
||||
|
||||
sym_AddEqu("_NARG", 0);
|
||||
p_NARGSymbol = findsymbol("_NARG", NULL);
|
||||
p_NARGSymbol->Callback = Callback_NARG;
|
||||
|
||||
math_DefinePI();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the symboltable
|
||||
*/
|
||||
void
|
||||
sym_Init(void)
|
||||
{
|
||||
@@ -899,11 +777,7 @@ sym_Init(void)
|
||||
sym_AddEqu("_NARG", 0);
|
||||
p_NARGSymbol = findsymbol("_NARG", NULL);
|
||||
p_NARGSymbol->Callback = Callback_NARG;
|
||||
sym_AddEqu("__LINE__", 0);
|
||||
p__LINE__Symbol = findsymbol("__LINE__", NULL);
|
||||
p__LINE__Symbol->Callback = Callback__LINE__;
|
||||
|
||||
sym_AddEqu("__ASM__", (SLONG) (atof(ASM_VERSION) * 65536));
|
||||
sym_AddSet("_RS", 0);
|
||||
|
||||
if (time(&tod) != -1) {
|
||||
@@ -920,72 +794,3 @@ sym_Init(void)
|
||||
math_DefinePI();
|
||||
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* DEBUG: Print the symbol table
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
sym_PrintSymbolTable(void)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < HASHSIZE; i += 1) {
|
||||
struct sSymbol *sym = tHashedSymbols[i];
|
||||
|
||||
if (sym != NULL)
|
||||
printf("\nHashTable #%ld:\n", i);
|
||||
|
||||
while (sym != NULL) {
|
||||
if (sym->nType & SYMF_LOCAL)
|
||||
printf("LOCAL : '%s%s' - %08lX\n",
|
||||
sym->pScope->tzName, sym->tzName,
|
||||
getvaluefield(sym));
|
||||
else if (sym->nType & (SYMF_MACRO | SYMF_STRING)) {
|
||||
ULONG i = 0;
|
||||
|
||||
printf("MACRO : '%s'\n\"", sym->tzName);
|
||||
while (i < sym->ulMacroSize) {
|
||||
if (sym->pMacro[i] == '\n') {
|
||||
printf("\n");
|
||||
i += 1;
|
||||
} else
|
||||
printf("%c", sym->pMacro[i++]);
|
||||
}
|
||||
printf("\"\n");
|
||||
} else if (sym->nType & SYMF_EXPORT)
|
||||
printf("EXPORT: '%s' - %08lX\n", sym->tzName,
|
||||
getvaluefield(sym));
|
||||
else if (sym->nType & SYMF_IMPORT)
|
||||
printf("IMPORT: '%s'\n", sym->tzName);
|
||||
else if (sym->nType & SYMF_EQU)
|
||||
printf("EQU : '%s' - %08lX\n", sym->tzName,
|
||||
getvaluefield(sym));
|
||||
else if (sym->nType & SYMF_SET)
|
||||
printf("SET : '%s' - %08lX\n", sym->tzName,
|
||||
getvaluefield(sym));
|
||||
else
|
||||
printf("SYMBOL: '%s' - %08lX\n", sym->tzName,
|
||||
getvaluefield(sym));
|
||||
|
||||
sym = sym->pNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* DEBUG: Dump the macroargs
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
sym_DumpMacroArgs(void)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < MAXMACROARGS; i += 1)
|
||||
printf("CurrentArg%ld: %s\n", i + 1, currentmacroargs[i]);
|
||||
}
|
||||
|
||||
@@ -1,434 +0,0 @@
|
||||
%{
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/asm.h"
|
||||
#include "asm/output.h"
|
||||
#include "asm/mylink.h"
|
||||
#include "asm/fstack.h"
|
||||
#include "asm/mymath.h"
|
||||
#include "asm/rpn.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/lexer.h"
|
||||
|
||||
char *tzNewMacro;
|
||||
ULONG ulNewMacroSize;
|
||||
|
||||
ULONG symvaluetostring( char *dest, char *sym )
|
||||
{
|
||||
if( sym_isString(sym) )
|
||||
strcpy( dest, sym_GetStringValue(sym) );
|
||||
else
|
||||
sprintf( dest, "$%lX", sym_GetConstantValue(sym) );
|
||||
|
||||
return( strlen(dest) );
|
||||
}
|
||||
|
||||
ULONG str2int( char *s )
|
||||
{
|
||||
ULONG r=0;
|
||||
while( *s )
|
||||
{
|
||||
r<<=8;
|
||||
r|=(UBYTE)(*s++);
|
||||
}
|
||||
return( r );
|
||||
}
|
||||
|
||||
ULONG isWhiteSpace( char s )
|
||||
{
|
||||
return( s==' ' || s=='\t' || s=='\0' || s=='\n' );
|
||||
}
|
||||
|
||||
ULONG isRept( char *s )
|
||||
{
|
||||
return( (strncasecmp(s,"REPT",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
|
||||
}
|
||||
|
||||
ULONG isEndr( char *s )
|
||||
{
|
||||
return( (strncasecmp(s,"Endr",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
|
||||
}
|
||||
|
||||
void copyrept( void )
|
||||
{
|
||||
SLONG level=1, len, instring=0;
|
||||
char *src=pCurrentBuffer->pBuffer;
|
||||
|
||||
while( *src && level )
|
||||
{
|
||||
if( instring==0 )
|
||||
{
|
||||
if( isRept(src) )
|
||||
{
|
||||
level+=1;
|
||||
src+=4;
|
||||
}
|
||||
else if( isEndr(src) )
|
||||
{
|
||||
level-=1;
|
||||
src+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\"' )
|
||||
instring=1;
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\\' )
|
||||
{
|
||||
src+=2;
|
||||
}
|
||||
else if( *src=='\"' )
|
||||
{
|
||||
src+=1;
|
||||
instring=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer-4;
|
||||
|
||||
src=pCurrentBuffer->pBuffer;
|
||||
ulNewMacroSize=len;
|
||||
|
||||
if( (tzNewMacro=(char *)malloc(ulNewMacroSize+1))!=NULL )
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
tzNewMacro[ulNewMacroSize]=0;
|
||||
for( i=0; i<ulNewMacroSize; i+=1 )
|
||||
{
|
||||
if( (tzNewMacro[i]=src[i])=='\n' )
|
||||
nLineNo+=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
fatalerror( "No mem for REPT block" );
|
||||
|
||||
yyskipbytes( ulNewMacroSize+4 );
|
||||
|
||||
}
|
||||
|
||||
ULONG isMacro( char *s )
|
||||
{
|
||||
return( (strncasecmp(s,"MACRO",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[5]) );
|
||||
}
|
||||
|
||||
ULONG isEndm( char *s )
|
||||
{
|
||||
return( (strncasecmp(s,"Endm",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
|
||||
}
|
||||
|
||||
void copymacro( void )
|
||||
{
|
||||
SLONG level=1, len, instring=0;
|
||||
char *src=pCurrentBuffer->pBuffer;
|
||||
|
||||
while( *src && level )
|
||||
{
|
||||
if( instring==0 )
|
||||
{
|
||||
if( isMacro(src) )
|
||||
{
|
||||
level+=1;
|
||||
src+=4;
|
||||
}
|
||||
else if( isEndm(src) )
|
||||
{
|
||||
level-=1;
|
||||
src+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\"' )
|
||||
instring=1;
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\\' )
|
||||
{
|
||||
src+=2;
|
||||
}
|
||||
else if( *src=='\"' )
|
||||
{
|
||||
src+=1;
|
||||
instring=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer-4;
|
||||
|
||||
src=pCurrentBuffer->pBuffer;
|
||||
ulNewMacroSize=len;
|
||||
|
||||
if( (tzNewMacro=(char *)malloc(ulNewMacroSize+2))!=NULL )
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
tzNewMacro[ulNewMacroSize]='\n';
|
||||
tzNewMacro[ulNewMacroSize+1]=0;
|
||||
for( i=0; i<ulNewMacroSize; i+=1 )
|
||||
{
|
||||
if( (tzNewMacro[i]=src[i])=='\n' )
|
||||
nLineNo+=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
fatalerror( "No mem for MACRO definition" );
|
||||
|
||||
yyskipbytes( ulNewMacroSize+4 );
|
||||
}
|
||||
|
||||
ULONG isIf( char *s )
|
||||
{
|
||||
return( (strncasecmp(s,"If",2)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[2]) );
|
||||
}
|
||||
|
||||
ULONG isElse( char *s )
|
||||
{
|
||||
return( (strncasecmp(s,"Else",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
|
||||
}
|
||||
|
||||
ULONG isEndc( char *s )
|
||||
{
|
||||
return( (strncasecmp(s,"Endc",4)==0) && isWhiteSpace(*(s-1)) && isWhiteSpace(s[4]) );
|
||||
}
|
||||
|
||||
void if_skip_to_else( void )
|
||||
{
|
||||
SLONG level=1, len, instring=0;
|
||||
char *src=pCurrentBuffer->pBuffer;
|
||||
|
||||
while( *src && level )
|
||||
{
|
||||
if( *src=='\n' )
|
||||
nLineNo+=1;
|
||||
|
||||
if( instring==0 )
|
||||
{
|
||||
if( isIf(src) )
|
||||
{
|
||||
level+=1;
|
||||
src+=2;
|
||||
}
|
||||
else if( level==1 && isElse(src) )
|
||||
{
|
||||
level-=1;
|
||||
src+=4;
|
||||
}
|
||||
else if( isEndc(src) )
|
||||
{
|
||||
level-=1;
|
||||
if( level!=0 )
|
||||
src+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\"' )
|
||||
instring=1;
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\\' )
|
||||
{
|
||||
src+=2;
|
||||
}
|
||||
else if( *src=='\"' )
|
||||
{
|
||||
src+=1;
|
||||
instring=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer;
|
||||
|
||||
yyskipbytes( len );
|
||||
yyunput( '\n' );
|
||||
nLineNo-=1;
|
||||
}
|
||||
|
||||
void if_skip_to_endc( void )
|
||||
{
|
||||
SLONG level=1, len, instring=0;
|
||||
char *src=pCurrentBuffer->pBuffer;
|
||||
|
||||
while( *src && level )
|
||||
{
|
||||
if( *src=='\n' )
|
||||
nLineNo+=1;
|
||||
|
||||
if( instring==0 )
|
||||
{
|
||||
if( isIf(src) )
|
||||
{
|
||||
level+=1;
|
||||
src+=2;
|
||||
}
|
||||
else if( isEndc(src) )
|
||||
{
|
||||
level-=1;
|
||||
if( level!=0 )
|
||||
src+=4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\"' )
|
||||
instring=1;
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( *src=='\\' )
|
||||
{
|
||||
src+=2;
|
||||
}
|
||||
else if( *src=='\"' )
|
||||
{
|
||||
src+=1;
|
||||
instring=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
src+=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer;
|
||||
|
||||
yyskipbytes( len );
|
||||
yyunput( '\n' );
|
||||
nLineNo-=1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef PCENGINE
|
||||
ULONG ZP( struct Expression *expr )
|
||||
{
|
||||
return( (!rpn_isReloc(expr)) && (expr->nVal>0x1FFF) && (expr->nVal<0x2100) );
|
||||
}
|
||||
|
||||
void out_ZPByte( struct Expression *expr )
|
||||
{
|
||||
if( rpn_isReloc(expr) )
|
||||
{
|
||||
rpn_CheckZP(expr,expr);
|
||||
out_RelByte(expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( ZP(expr) )
|
||||
out_AbsByte(expr->nVal-0x2000);
|
||||
else
|
||||
fatalerror( "Value not in zeropage");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
char tzSym[MAXSYMLEN+1];
|
||||
char tzString[256];
|
||||
struct Expression sVal;
|
||||
SLONG nConstValue;
|
||||
}
|
||||
|
||||
%type <sVal> relocconst
|
||||
%type <nConstValue> const
|
||||
%type <nConstValue> const_3bit
|
||||
%type <sVal> const_8bit
|
||||
%type <sVal> const_16bit
|
||||
%type <sVal> const_PCrel
|
||||
%type <nConstValue> sectiontype
|
||||
|
||||
%type <tzString> string
|
||||
|
||||
%token <nConstValue> T_NUMBER
|
||||
%token <tzString> T_STRING
|
||||
|
||||
%left T_OP_LOGICNOT
|
||||
%left T_OP_LOGICOR T_OP_LOGICAND T_OP_LOGICEQU
|
||||
%left T_OP_LOGICGT T_OP_LOGICLT T_OP_LOGICGE T_OP_LOGICLE T_OP_LOGICNE
|
||||
%left T_OP_ADD T_OP_SUB
|
||||
%left T_OP_OR T_OP_XOR T_OP_AND
|
||||
%left T_OP_SHL T_OP_SHR
|
||||
%left T_OP_MUL T_OP_DIV T_OP_MOD
|
||||
%left T_OP_NOT
|
||||
%left T_OP_DEF
|
||||
%left T_OP_BANK
|
||||
%left T_OP_SIN
|
||||
%left T_OP_COS
|
||||
%left T_OP_TAN
|
||||
%left T_OP_ASIN
|
||||
%left T_OP_ACOS
|
||||
%left T_OP_ATAN
|
||||
%left T_OP_ATAN2
|
||||
%left T_OP_FDIV
|
||||
%left T_OP_FMUL
|
||||
|
||||
%left T_OP_STRCMP
|
||||
%left T_OP_STRIN
|
||||
%left T_OP_STRSUB
|
||||
%left T_OP_STRLEN
|
||||
%left T_OP_STRCAT
|
||||
%left T_OP_STRUPR
|
||||
%left T_OP_STRLWR
|
||||
|
||||
%left NEG /* negation--unary minus */
|
||||
|
||||
%token <tzSym> T_LABEL
|
||||
%token <tzSym> T_ID
|
||||
%token <tzSym> T_POP_EQU
|
||||
%token <tzSym> T_POP_SET
|
||||
%token <tzSym> T_POP_EQUS
|
||||
|
||||
%token T_POP_INCLUDE T_POP_PRINTF T_POP_PRINTT T_POP_PRINTV T_POP_IF T_POP_ELSE T_POP_ENDC
|
||||
%token T_POP_IMPORT T_POP_EXPORT T_POP_GLOBAL
|
||||
%token T_POP_DB T_POP_DS T_POP_DW T_POP_DL
|
||||
%token T_POP_SECTION
|
||||
%token T_POP_RB
|
||||
%token T_POP_RW
|
||||
%token T_POP_RL
|
||||
%token T_POP_MACRO
|
||||
%token T_POP_ENDM
|
||||
%token T_POP_RSRESET T_POP_RSSET
|
||||
%token T_POP_INCBIN T_POP_REPT
|
||||
%token T_POP_SHIFT
|
||||
%token T_POP_ENDR
|
||||
%token T_POP_FAIL
|
||||
%token T_POP_WARN
|
||||
%token T_POP_PURGE
|
||||
%token T_POP_POPS
|
||||
%token T_POP_PUSHS
|
||||
%token T_POP_POPO
|
||||
%token T_POP_PUSHO
|
||||
%token T_POP_OPT
|
||||
@@ -1,538 +0,0 @@
|
||||
%start asmfile
|
||||
|
||||
%%
|
||||
|
||||
asmfile : lines lastline
|
||||
;
|
||||
|
||||
lastline : /* empty */
|
||||
| line
|
||||
{ nLineNo+=1; nTotalLines+=1; }
|
||||
;
|
||||
|
||||
lines : /* empty */
|
||||
| lines line '\n'
|
||||
{ nLineNo+=1; nTotalLines+=1; }
|
||||
;
|
||||
|
||||
line : /* empty */
|
||||
| label
|
||||
| label cpu_command
|
||||
| label macro
|
||||
| label simple_pseudoop
|
||||
| pseudoop
|
||||
;
|
||||
|
||||
label : /* empty */
|
||||
| T_LABEL { if( $1[0]=='.' )
|
||||
sym_AddLocalReloc($1);
|
||||
else
|
||||
sym_AddReloc($1);
|
||||
}
|
||||
| T_LABEL ':' { if( $1[0]=='.' )
|
||||
sym_AddLocalReloc($1);
|
||||
else
|
||||
sym_AddReloc($1);
|
||||
}
|
||||
| T_LABEL ':' ':' { sym_AddReloc($1); sym_Export($1); }
|
||||
;
|
||||
|
||||
macro : T_ID
|
||||
{
|
||||
yy_set_state( LEX_STATE_MACROARGS );
|
||||
}
|
||||
macroargs
|
||||
{
|
||||
yy_set_state( LEX_STATE_NORMAL );
|
||||
|
||||
if( !fstk_RunMacro($1) )
|
||||
{
|
||||
fprintf(stderr, "Macro '%s' not defined", $1);
|
||||
yyerror( "No such macro" );
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
macroargs : /* empty */
|
||||
| macroarg
|
||||
| macroarg ',' macroargs
|
||||
;
|
||||
|
||||
macroarg : T_STRING
|
||||
{ sym_AddNewMacroArg( $1 ); }
|
||||
;
|
||||
|
||||
pseudoop : equ
|
||||
| set
|
||||
| rb
|
||||
| rw
|
||||
| rl
|
||||
| equs
|
||||
| macrodef
|
||||
;
|
||||
|
||||
simple_pseudoop : include
|
||||
| printf
|
||||
| printt
|
||||
| printv
|
||||
| if
|
||||
| else
|
||||
| endc
|
||||
| import
|
||||
| export
|
||||
| global
|
||||
| db
|
||||
| dw
|
||||
| dl
|
||||
| ds
|
||||
| section
|
||||
| rsreset
|
||||
| rsset
|
||||
| incbin
|
||||
| rept
|
||||
| shift
|
||||
| fail
|
||||
| warn
|
||||
| purge
|
||||
| pops
|
||||
| pushs
|
||||
| popo
|
||||
| pusho
|
||||
| opt
|
||||
;
|
||||
|
||||
opt : T_POP_OPT
|
||||
{
|
||||
yy_set_state( LEX_STATE_MACROARGS );
|
||||
}
|
||||
opt_list
|
||||
{
|
||||
yy_set_state( LEX_STATE_NORMAL );
|
||||
}
|
||||
;
|
||||
|
||||
opt_list : opt_list_entry
|
||||
| opt_list_entry ',' opt_list
|
||||
;
|
||||
|
||||
opt_list_entry : T_STRING
|
||||
{
|
||||
opt_Parse($1);
|
||||
}
|
||||
;
|
||||
|
||||
popo : T_POP_POPO
|
||||
{ opt_Pop(); }
|
||||
;
|
||||
|
||||
pusho : T_POP_PUSHO
|
||||
{ opt_Push(); }
|
||||
;
|
||||
|
||||
pops : T_POP_POPS
|
||||
{ out_PopSection(); }
|
||||
;
|
||||
|
||||
pushs : T_POP_PUSHS
|
||||
{ out_PushSection(); }
|
||||
;
|
||||
|
||||
fail : T_POP_FAIL string
|
||||
{ fatalerror($2); }
|
||||
;
|
||||
|
||||
warn : T_POP_WARN string
|
||||
{ yyerror($2); }
|
||||
;
|
||||
|
||||
shift : T_POP_SHIFT
|
||||
{ sym_ShiftCurrentMacroArgs(); }
|
||||
;
|
||||
|
||||
rept : T_POP_REPT const
|
||||
{
|
||||
copyrept();
|
||||
fstk_RunRept( $2 );
|
||||
}
|
||||
;
|
||||
|
||||
macrodef : T_LABEL ':' T_POP_MACRO
|
||||
{
|
||||
copymacro();
|
||||
sym_AddMacro($1);
|
||||
}
|
||||
;
|
||||
|
||||
equs : T_LABEL T_POP_EQUS string
|
||||
{ sym_AddString( $1, $3 ); }
|
||||
;
|
||||
|
||||
rsset : T_POP_RSSET const
|
||||
{ sym_AddSet( "_RS", $2 ); }
|
||||
;
|
||||
|
||||
rsreset : T_POP_RSRESET
|
||||
{ sym_AddSet( "_RS", 0 ); }
|
||||
;
|
||||
|
||||
rl : T_LABEL T_POP_RL const
|
||||
{
|
||||
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
|
||||
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+4*$3 );
|
||||
}
|
||||
;
|
||||
|
||||
rw : T_LABEL T_POP_RW const
|
||||
{
|
||||
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
|
||||
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+2*$3 );
|
||||
}
|
||||
;
|
||||
|
||||
rb : T_LABEL T_POP_RB const
|
||||
{
|
||||
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
|
||||
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+$3 );
|
||||
}
|
||||
;
|
||||
|
||||
ds : T_POP_DS const
|
||||
{ out_Skip( $2 ); }
|
||||
;
|
||||
|
||||
db : T_POP_DB constlist_8bit
|
||||
;
|
||||
|
||||
dw : T_POP_DW constlist_16bit
|
||||
;
|
||||
|
||||
dl : T_POP_DL constlist_32bit
|
||||
;
|
||||
|
||||
purge : T_POP_PURGE
|
||||
{
|
||||
oDontExpandStrings=1;
|
||||
}
|
||||
purge_list
|
||||
{
|
||||
oDontExpandStrings=0;
|
||||
}
|
||||
;
|
||||
|
||||
purge_list : purge_list_entry
|
||||
| purge_list_entry ',' purge_list
|
||||
;
|
||||
|
||||
purge_list_entry : T_ID { sym_Purge($1); }
|
||||
;
|
||||
|
||||
import : T_POP_IMPORT import_list
|
||||
;
|
||||
|
||||
import_list : import_list_entry
|
||||
| import_list_entry ',' import_list
|
||||
;
|
||||
|
||||
import_list_entry : T_ID { sym_Import($1); }
|
||||
;
|
||||
|
||||
export : T_POP_EXPORT export_list
|
||||
;
|
||||
|
||||
export_list : export_list_entry
|
||||
| export_list_entry ',' export_list
|
||||
;
|
||||
|
||||
export_list_entry : T_ID { sym_Export($1); }
|
||||
;
|
||||
|
||||
global : T_POP_GLOBAL global_list
|
||||
;
|
||||
|
||||
global_list : global_list_entry
|
||||
| global_list_entry ',' global_list
|
||||
;
|
||||
|
||||
global_list_entry : T_ID { sym_Global($1); }
|
||||
;
|
||||
|
||||
equ : T_LABEL T_POP_EQU const
|
||||
{ sym_AddEqu( $1, $3 ); }
|
||||
;
|
||||
|
||||
set : T_LABEL T_POP_SET const
|
||||
{ sym_AddSet( $1, $3 ); }
|
||||
;
|
||||
|
||||
include : T_POP_INCLUDE string
|
||||
{
|
||||
if( !fstk_RunInclude($2) )
|
||||
{
|
||||
fprintf(stderr, "Could not open file '%s' : %s\n", $2, strerror(errno));
|
||||
yyerror( "File not found" );
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
incbin : T_POP_INCBIN string
|
||||
{ out_BinaryFile( $2 ); }
|
||||
| T_POP_INCBIN string ',' const ',' const
|
||||
{
|
||||
out_BinaryFileSlice( $2, $4, $6 );
|
||||
}
|
||||
;
|
||||
|
||||
printt : T_POP_PRINTT string
|
||||
{
|
||||
if( nPass==1 )
|
||||
printf( "%s", $2 );
|
||||
}
|
||||
;
|
||||
|
||||
printv : T_POP_PRINTV const
|
||||
{
|
||||
if( nPass==1 )
|
||||
printf( "$%lX", $2 );
|
||||
}
|
||||
;
|
||||
|
||||
printf : T_POP_PRINTF const
|
||||
{
|
||||
if( nPass==1 )
|
||||
math_Print( $2 );
|
||||
}
|
||||
;
|
||||
|
||||
if : T_POP_IF const
|
||||
{
|
||||
nIFDepth+=1;
|
||||
if( !$2 )
|
||||
{
|
||||
if_skip_to_else(); /* will continue parsing just after ELSE or just at ENDC keyword */
|
||||
}
|
||||
}
|
||||
|
||||
else : T_POP_ELSE
|
||||
{
|
||||
if_skip_to_endc(); /* will continue parsing just at ENDC keyword */
|
||||
}
|
||||
;
|
||||
|
||||
endc : T_POP_ENDC
|
||||
{
|
||||
nIFDepth-=1;
|
||||
}
|
||||
;
|
||||
|
||||
const_3bit : const
|
||||
{
|
||||
if( ($1<0) || ($1>7) )
|
||||
{
|
||||
yyerror( "Immediate value must be 3-bit" );
|
||||
}
|
||||
else
|
||||
$$=$1&0x7;
|
||||
}
|
||||
;
|
||||
|
||||
constlist_8bit : constlist_8bit_entry
|
||||
| constlist_8bit_entry ',' constlist_8bit
|
||||
;
|
||||
|
||||
constlist_8bit_entry : { out_Skip( 1 ); }
|
||||
| const_8bit { out_RelByte( &$1 ); }
|
||||
| string { out_String( $1 ); }
|
||||
;
|
||||
|
||||
constlist_16bit : constlist_16bit_entry
|
||||
| constlist_16bit_entry ',' constlist_16bit
|
||||
;
|
||||
|
||||
constlist_16bit_entry : { out_Skip( 2 ); }
|
||||
| const_16bit { out_RelWord( &$1 ); }
|
||||
;
|
||||
|
||||
|
||||
constlist_32bit : constlist_32bit_entry
|
||||
| constlist_32bit_entry ',' constlist_32bit
|
||||
;
|
||||
|
||||
constlist_32bit_entry : { out_Skip( 4 ); }
|
||||
| relocconst { out_RelLong( &$1 ); }
|
||||
;
|
||||
|
||||
|
||||
const_PCrel : relocconst
|
||||
{
|
||||
$$ = $1;
|
||||
if( !rpn_isPCRelative(&$1) )
|
||||
yyerror( "Expression must be PC-relative" );
|
||||
}
|
||||
;
|
||||
|
||||
const_8bit : relocconst
|
||||
{
|
||||
if( (!rpn_isReloc(&$1)) && (($1.nVal<-128) || ($1.nVal>255)) )
|
||||
{
|
||||
yyerror( "Expression must be 8-bit" );
|
||||
}
|
||||
$$=$1;
|
||||
}
|
||||
;
|
||||
|
||||
const_16bit : relocconst
|
||||
{
|
||||
if( (!rpn_isReloc(&$1)) && (($1.nVal<-32768) || ($1.nVal>65535)) )
|
||||
{
|
||||
yyerror( "Expression must be 16-bit" );
|
||||
}
|
||||
$$=$1;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
relocconst : T_ID
|
||||
{ rpn_Symbol(&$$,$1); $$.nVal = sym_GetValue($1); }
|
||||
| T_NUMBER
|
||||
{ rpn_Number(&$$,$1); $$.nVal = $1; }
|
||||
| string
|
||||
{ ULONG r; r=str2int($1); rpn_Number(&$$,r); $$.nVal=r; }
|
||||
| T_OP_LOGICNOT relocconst %prec NEG
|
||||
{ rpn_LOGNOT(&$$,&$2); }
|
||||
| relocconst T_OP_LOGICOR relocconst
|
||||
{ rpn_LOGOR(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_LOGICAND relocconst
|
||||
{ rpn_LOGAND(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_LOGICEQU relocconst
|
||||
{ rpn_LOGEQU(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_LOGICGT relocconst
|
||||
{ rpn_LOGGT(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_LOGICLT relocconst
|
||||
{ rpn_LOGLT(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_LOGICGE relocconst
|
||||
{ rpn_LOGGE(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_LOGICLE relocconst
|
||||
{ rpn_LOGLE(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_LOGICNE relocconst
|
||||
{ rpn_LOGNE(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_ADD relocconst
|
||||
{ rpn_ADD(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_SUB relocconst
|
||||
{ rpn_SUB(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_XOR relocconst
|
||||
{ rpn_XOR(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_OR relocconst
|
||||
{ rpn_OR(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_AND relocconst
|
||||
{ rpn_AND(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_SHL relocconst
|
||||
{ rpn_SHL(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_SHR relocconst
|
||||
{ rpn_SHR(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_MUL relocconst
|
||||
{ rpn_MUL(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_DIV relocconst
|
||||
{ rpn_DIV(&$$,&$1,&$3); }
|
||||
| relocconst T_OP_MOD relocconst
|
||||
{ rpn_MOD(&$$,&$1,&$3); }
|
||||
| T_OP_ADD relocconst %prec NEG
|
||||
{ $$ = $2; }
|
||||
| T_OP_SUB relocconst %prec NEG
|
||||
{ rpn_UNNEG(&$$,&$2); }
|
||||
| T_OP_NOT relocconst %prec NEG
|
||||
{ rpn_UNNOT(&$$,&$2); }
|
||||
| T_OP_BANK '(' T_ID ')'
|
||||
{ rpn_Bank(&$$,$3); $$.nVal = 0; }
|
||||
| T_OP_DEF '(' T_ID ')'
|
||||
{ rpn_Number(&$$,sym_isConstDefined($3)); }
|
||||
| T_OP_FDIV '(' const ',' const ')' { rpn_Number(&$$,math_Div($3,$5)); }
|
||||
| T_OP_FMUL '(' const ',' const ')' { rpn_Number(&$$,math_Mul($3,$5)); }
|
||||
| T_OP_SIN '(' const ')' { rpn_Number(&$$,math_Sin($3)); }
|
||||
| T_OP_COS '(' const ')' { rpn_Number(&$$,math_Cos($3)); }
|
||||
| T_OP_TAN '(' const ')' { rpn_Number(&$$,math_Tan($3)); }
|
||||
| T_OP_ASIN '(' const ')' { rpn_Number(&$$,math_ASin($3)); }
|
||||
| T_OP_ACOS '(' const ')' { rpn_Number(&$$,math_ACos($3)); }
|
||||
| T_OP_ATAN '(' const ')' { rpn_Number(&$$,math_ATan($3)); }
|
||||
| T_OP_ATAN2 '(' const ',' const ')' { rpn_Number(&$$,math_ATan2($3,$5)); }
|
||||
| T_OP_STRCMP '(' string ',' string ')' { rpn_Number(&$$,strcmp($3,$5)); }
|
||||
| T_OP_STRIN '(' string ',' string ')'
|
||||
{
|
||||
char *p;
|
||||
if( (p=strstr($3,$5))!=NULL )
|
||||
{
|
||||
rpn_Number(&$$,p-$3+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
rpn_Number(&$$,0);
|
||||
}
|
||||
}
|
||||
| T_OP_STRLEN '(' string ')' { rpn_Number(&$$,strlen($3)); }
|
||||
| '(' relocconst ')'
|
||||
{ $$ = $2; }
|
||||
;
|
||||
|
||||
const : T_ID { $$ = sym_GetConstantValue($1); }
|
||||
| T_NUMBER { $$ = $1; }
|
||||
| string { $$ = str2int($1); }
|
||||
| T_OP_LOGICNOT const %prec NEG { $$ = !$2; }
|
||||
| const T_OP_LOGICOR const { $$ = $1 || $3; }
|
||||
| const T_OP_LOGICAND const { $$ = $1 && $3; }
|
||||
| const T_OP_LOGICEQU const { $$ = $1 == $3; }
|
||||
| const T_OP_LOGICGT const { $$ = $1 > $3; }
|
||||
| const T_OP_LOGICLT const { $$ = $1 < $3; }
|
||||
| const T_OP_LOGICGE const { $$ = $1 >= $3; }
|
||||
| const T_OP_LOGICLE const { $$ = $1 <= $3; }
|
||||
| const T_OP_LOGICNE const { $$ = $1 != $3; }
|
||||
| const T_OP_ADD const { $$ = $1 + $3; }
|
||||
| const T_OP_SUB const { $$ = $1 - $3; }
|
||||
| T_ID T_OP_SUB T_ID { $$ = sym_GetDefinedValue($1) - sym_GetDefinedValue($3); }
|
||||
| const T_OP_XOR const { $$ = $1 ^ $3; }
|
||||
| const T_OP_OR const { $$ = $1 | $3; }
|
||||
| const T_OP_AND const { $$ = $1 & $3; }
|
||||
| const T_OP_SHL const { $$ = $1 << $3; }
|
||||
| const T_OP_SHR const { $$ = $1 >> $3; }
|
||||
| const T_OP_MUL const { $$ = $1 * $3; }
|
||||
| const T_OP_DIV const { $$ = $1 / $3; }
|
||||
| const T_OP_MOD const { $$ = $1 % $3; }
|
||||
| T_OP_ADD const %prec NEG { $$ = +$2; }
|
||||
| T_OP_SUB const %prec NEG { $$ = -$2; }
|
||||
| T_OP_NOT const %prec NEG { $$ = 0xFFFFFFFF^$2; }
|
||||
| T_OP_FDIV '(' const ',' const ')' { $$ = math_Div($3,$5); }
|
||||
| T_OP_FMUL '(' const ',' const ')' { $$ = math_Mul($3,$5); }
|
||||
| T_OP_SIN '(' const ')' { $$ = math_Sin($3); }
|
||||
| T_OP_COS '(' const ')' { $$ = math_Cos($3); }
|
||||
| T_OP_TAN '(' const ')' { $$ = math_Tan($3); }
|
||||
| T_OP_ASIN '(' const ')' { $$ = math_ASin($3); }
|
||||
| T_OP_ACOS '(' const ')' { $$ = math_ACos($3); }
|
||||
| T_OP_ATAN '(' const ')' { $$ = math_ATan($3); }
|
||||
| T_OP_ATAN2 '(' const ',' const ')' { $$ = math_ATan2($3,$5); }
|
||||
| T_OP_DEF '(' T_ID ')' { $$ = sym_isConstDefined($3); }
|
||||
| T_OP_STRCMP '(' string ',' string ')' { $$ = strcmp( $3, $5 ); }
|
||||
| T_OP_STRIN '(' string ',' string ')'
|
||||
{
|
||||
char *p;
|
||||
if( (p=strstr($3,$5))!=NULL )
|
||||
{
|
||||
$$ = p-$3+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$$ = 0;
|
||||
}
|
||||
}
|
||||
| T_OP_STRLEN '(' string ')' { $$ = strlen($3); }
|
||||
| '(' const ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
string : T_STRING
|
||||
{ strcpy($$,$1); }
|
||||
| T_OP_STRSUB '(' string ',' const ',' const ')'
|
||||
{ strncpy($$,$3+$5-1,$7); $$[$7]=0; }
|
||||
| T_OP_STRCAT '(' string ',' string ')'
|
||||
{ strcpy($$,$3); strcat($$,$5); }
|
||||
| T_OP_STRUPR '(' string ')'
|
||||
{ strcpy($$,$3); strupr($$); }
|
||||
| T_OP_STRLWR '(' string ')'
|
||||
{ strcpy($$,$3); strlwr($$); }
|
||||
;
|
||||
90
src/extern/err.c
vendored
Normal file
90
src/extern/err.c
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright © 2005-2013 Rich Felker, et al.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include "extern/err.h"
|
||||
|
||||
extern char *progname;
|
||||
|
||||
void rgbds_vwarn(const char *fmt, va_list ap)
|
||||
{
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
if (fmt) {
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputs (": ", stderr);
|
||||
}
|
||||
perror(0);
|
||||
}
|
||||
|
||||
void rgbds_vwarnx(const char *fmt, va_list ap)
|
||||
{
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
if (fmt) vfprintf(stderr, fmt, ap);
|
||||
putc('\n', stderr);
|
||||
}
|
||||
|
||||
noreturn void rgbds_verr(int status, const char *fmt, va_list ap)
|
||||
{
|
||||
vwarn(fmt, ap);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
noreturn void rgbds_verrx(int status, const char *fmt, va_list ap)
|
||||
{
|
||||
vwarnx(fmt, ap);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void rgbds_warn(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vwarn(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void rgbds_warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vwarnx(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
noreturn void rgbds_err(int status, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
verr(status, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
noreturn void rgbds_errx(int status, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
verrx(status, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
38
src/extern/reallocarray.c
vendored
Normal file
38
src/extern/reallocarray.c
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
|
||||
* if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
|
||||
*/
|
||||
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
|
||||
|
||||
void *
|
||||
rgbds_reallocarray(void *optr, size_t nmemb, size_t size)
|
||||
{
|
||||
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
|
||||
nmemb > 0 && SIZE_MAX / nmemb < size) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
return realloc(optr, size * nmemb);
|
||||
}
|
||||
55
src/extern/strlcat.c
vendored
Normal file
55
src/extern/strlcat.c
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/* $OpenBSD: strlcat.c,v 1.14 2015/01/15 03:54:12 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size dsize (unlike strncat, dsize is the
|
||||
* full size of dst, not space left). At most dsize-1 characters
|
||||
* will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(dsize, strlen(initial dst)).
|
||||
* If retval >= dsize, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
rgbds_strlcat(char *dst, const char *src, size_t dsize)
|
||||
{
|
||||
const char *odst = dst;
|
||||
const char *osrc = src;
|
||||
size_t n = dsize;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end. */
|
||||
while (n-- != 0 && *dst != '\0')
|
||||
dst++;
|
||||
dlen = dst - odst;
|
||||
n = dsize - dlen;
|
||||
|
||||
if (n-- == 0)
|
||||
return(dlen + strlen(src));
|
||||
while (*src != '\0') {
|
||||
if (n != 0) {
|
||||
*dst++ = *src;
|
||||
n--;
|
||||
}
|
||||
src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
|
||||
return(dlen + (src - osrc)); /* count does not include NUL */
|
||||
}
|
||||
50
src/extern/strlcpy.c
vendored
Normal file
50
src/extern/strlcpy.c
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Copy string src to buffer dst of size dsize. At most dsize-1
|
||||
* chars will be copied. Always NUL terminates (unless dsize == 0).
|
||||
* Returns strlen(src); if retval >= dsize, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
rgbds_strlcpy(char *dst, const char *src, size_t dsize)
|
||||
{
|
||||
const char *osrc = src;
|
||||
size_t nleft = dsize;
|
||||
|
||||
/* Copy as many bytes as will fit. */
|
||||
if (nleft != 0) {
|
||||
while (--nleft != 0) {
|
||||
if ((*dst++ = *src++) == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src. */
|
||||
if (nleft == 0) {
|
||||
if (dsize != 0)
|
||||
*dst = '\0'; /* NUL-terminate dst */
|
||||
while (*src++)
|
||||
;
|
||||
}
|
||||
|
||||
return(src - osrc - 1); /* count does not include NUL */
|
||||
}
|
||||
150
src/fix/main.c
150
src/fix/main.c
@@ -14,7 +14,6 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
@@ -22,13 +21,18 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: rgbfix [-Ccjsv] [-i game_id] [-k licensee_str] "
|
||||
"[-l licensee_id]\n" " [-m mbc_type] [-n rom_version] "
|
||||
"[-p pad_value] [-r ram_size]\n"
|
||||
" [-t title_str] file.gb\n");
|
||||
printf(
|
||||
"usage: rgbfix [-Ccjsv] [-i game_id] [-k licensee_str] [-l licensee_id]\n"
|
||||
" [-m mbc_type] [-n rom_version] [-p pad_value] [-r ram_size]\n"
|
||||
" [-t title_str] file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -38,19 +42,6 @@ main(int argc, char *argv[])
|
||||
int ch;
|
||||
char *ep;
|
||||
|
||||
/*
|
||||
* Open the ROM file
|
||||
*/
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
||||
if ((rom = fopen(argv[argc - 1], "rb+")) == NULL) {
|
||||
fprintf(stderr, "Error opening file %s: \n", argv[argc - 1]);
|
||||
perror(NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse command-line options
|
||||
*/
|
||||
@@ -70,15 +61,17 @@ main(int argc, char *argv[])
|
||||
bool resize = false;
|
||||
bool setversion = false;
|
||||
|
||||
char *title = NULL; /* game title in ASCII */
|
||||
char *id = NULL; /* game ID in ASCII */
|
||||
char *newlicensee = NULL; /* new licensee ID, two ASCII characters */
|
||||
char *title; /* game title in ASCII */
|
||||
char *id; /* game ID in ASCII */
|
||||
char *newlicensee; /* new licensee ID, two ASCII characters */
|
||||
|
||||
int licensee = -1; /* old licensee ID */
|
||||
int cartridge = -1; /* cartridge hardware ID */
|
||||
int ramsize = -1; /* RAM size ID */
|
||||
int version = -1; /* mask ROM version number */
|
||||
int padvalue = -1; /* to pad the rom with if it changes size */
|
||||
int licensee; /* old licensee ID */
|
||||
int cartridge; /* cartridge hardware ID */
|
||||
int ramsize; /* RAM size ID */
|
||||
int version; /* mask ROM version number */
|
||||
int padvalue; /* to pad the rom with if it changes size */
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
while ((ch = getopt(argc, argv, "Cci:jk:l:m:n:p:sr:t:v")) != -1) {
|
||||
switch (ch) {
|
||||
@@ -92,9 +85,8 @@ main(int argc, char *argv[])
|
||||
setid = true;
|
||||
|
||||
if (strlen(optarg) != 4) {
|
||||
fprintf(stderr, "Game ID %s must be exactly 4 "
|
||||
"characters\n", optarg);
|
||||
exit(1);
|
||||
errx(1, "Game ID %s must be exactly 4 "
|
||||
"characters", optarg);
|
||||
}
|
||||
|
||||
id = optarg;
|
||||
@@ -106,10 +98,8 @@ main(int argc, char *argv[])
|
||||
setnewlicensee = true;
|
||||
|
||||
if (strlen(optarg) != 2) {
|
||||
fprintf(stderr,
|
||||
"New licensee code %s is not the correct "
|
||||
"length of 2 characters\n", optarg);
|
||||
exit(1);
|
||||
errx(1, "New licensee code %s is not the "
|
||||
"correct length of 2 characters", optarg);
|
||||
}
|
||||
|
||||
newlicensee = optarg;
|
||||
@@ -119,15 +109,11 @@ main(int argc, char *argv[])
|
||||
|
||||
licensee = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
fprintf(stderr,
|
||||
"Invalid argument for option 'l'\n");
|
||||
exit(1);
|
||||
errx(1, "Invalid argument for option 'l'");
|
||||
}
|
||||
if (licensee < 0 || licensee > 0xFF) {
|
||||
fprintf(stderr,
|
||||
"Argument for option 'l' must be "
|
||||
"between 0 and 255\n");
|
||||
exit(1);
|
||||
errx(1, "Argument for option 'l' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
@@ -135,15 +121,11 @@ main(int argc, char *argv[])
|
||||
|
||||
cartridge = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
fprintf(stderr,
|
||||
"Invalid argument for option 'm'\n");
|
||||
exit(1);
|
||||
errx(1, "Invalid argument for option 'm'");
|
||||
}
|
||||
if (cartridge < 0 || cartridge > 0xFF) {
|
||||
fprintf(stderr,
|
||||
"Argument for option 'm' must be "
|
||||
"between 0 and 255\n");
|
||||
exit(1);
|
||||
errx(1, "Argument for option 'm' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
@@ -151,15 +133,11 @@ main(int argc, char *argv[])
|
||||
|
||||
version = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
fprintf(stderr,
|
||||
"Invalid argument for option 'n'\n");
|
||||
exit(1);
|
||||
errx(1, "Invalid argument for option 'n'");
|
||||
}
|
||||
if (version < 0 || version > 0xFF) {
|
||||
fprintf(stderr,
|
||||
"Argument for option 'n' must be "
|
||||
"between 0 and 255\n");
|
||||
exit(1);
|
||||
errx(1, "Argument for option 'n' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
@@ -167,15 +145,11 @@ main(int argc, char *argv[])
|
||||
|
||||
padvalue = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
fprintf(stderr,
|
||||
"Invalid argument for option 'p'\n");
|
||||
exit(1);
|
||||
errx(1, "Invalid argument for option 'p'");
|
||||
}
|
||||
if (padvalue < 0 || padvalue > 0xFF) {
|
||||
fprintf(stderr,
|
||||
"Argument for option 'p' must be "
|
||||
"between 0 and 255\n");
|
||||
exit(1);
|
||||
errx(1, "Argument for option 'p' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
@@ -183,14 +157,11 @@ main(int argc, char *argv[])
|
||||
|
||||
ramsize = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
fprintf(stderr,
|
||||
"Invalid argument for option 'r'\n");
|
||||
errx(1, "Invalid argument for option 'r'");
|
||||
}
|
||||
if (ramsize < 0 || ramsize > 0xFF) {
|
||||
fprintf(stderr,
|
||||
"Argument for option 'r' must be "
|
||||
"between 0 and 255\n");
|
||||
exit(1);
|
||||
errx(1, "Argument for option 'r' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
@@ -200,15 +171,13 @@ main(int argc, char *argv[])
|
||||
settitle = true;
|
||||
|
||||
if (strlen(optarg) > 16) {
|
||||
fprintf(stderr, "Title %s is greater than the "
|
||||
"maximum of 16 characters\n", optarg);
|
||||
exit(1);
|
||||
errx(1, "Title %s is greater than the "
|
||||
"maximum of 16 characters", optarg);
|
||||
}
|
||||
|
||||
if (strlen(optarg) == 16)
|
||||
fprintf(stderr,
|
||||
"Title %s is 16 chars, it is best "
|
||||
"to keep it to 15 or fewer\n", optarg);
|
||||
warnx("Title %s is 16 chars, it is best to "
|
||||
"keep it to 15 or fewer", optarg);
|
||||
|
||||
title = optarg;
|
||||
break;
|
||||
@@ -220,9 +189,21 @@ main(int argc, char *argv[])
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
/*
|
||||
* Open the ROM file
|
||||
*/
|
||||
|
||||
if ((rom = fopen(argv[argc - 1], "rb+")) == NULL) {
|
||||
err(1, "Error opening file %s", argv[argc - 1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write changes to ROM
|
||||
*/
|
||||
@@ -314,8 +295,7 @@ main(int argc, char *argv[])
|
||||
byte |= 1 << 6;
|
||||
|
||||
if (byte & 0x3F)
|
||||
fprintf(stderr,
|
||||
"Color flag conflicts with game title\n");
|
||||
warnx("Color flag conflicts with game title");
|
||||
|
||||
fseek(rom, 0x143, SEEK_SET);
|
||||
fputc(byte, rom);
|
||||
@@ -352,9 +332,8 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
|
||||
if (!setlicensee)
|
||||
fprintf(stderr,
|
||||
"You should probably set both '-s' and "
|
||||
"'-l 0x33'\n");
|
||||
warnx("You should probably set both '-s' and "
|
||||
"'-l 0x33'");
|
||||
|
||||
fseek(rom, 0x146, SEEK_SET);
|
||||
fputc(3, rom);
|
||||
@@ -378,7 +357,9 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
|
||||
/* We will pad the ROM to match the size given in the header. */
|
||||
int romsize, newsize, headbyte;
|
||||
long romsize, newsize;
|
||||
int headbyte;
|
||||
uint8_t *buf;
|
||||
fseek(rom, 0, SEEK_END);
|
||||
romsize = ftell(rom);
|
||||
newsize = 0x8000;
|
||||
@@ -389,14 +370,17 @@ main(int argc, char *argv[])
|
||||
headbyte++;
|
||||
}
|
||||
|
||||
while (newsize != ftell(rom)) /* ROM needs resizing */
|
||||
fputc(padvalue, rom);
|
||||
|
||||
if (newsize > 0x800000) /* ROM is bigger than 8MiB */
|
||||
fprintf(stderr, "ROM size is bigger than 8MiB\n");
|
||||
warnx("ROM size is bigger than 8MiB");
|
||||
|
||||
buf = malloc(newsize - romsize);
|
||||
memset(buf, padvalue, newsize - romsize);
|
||||
fwrite(buf, 1, newsize - romsize, rom);
|
||||
|
||||
fseek(rom, 0x148, SEEK_SET);
|
||||
fputc(headbyte, rom);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
if (setramsize) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dd February 26, 2015
|
||||
.Dt RGBFIX 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
@@ -41,7 +41,7 @@ flag are set,
|
||||
takes precedence.
|
||||
.It Fl i Ar game_id
|
||||
Set the game ID string
|
||||
.Pq Ad 0x13F No Ns \(en Ns Ad 0x142
|
||||
.Pq Ad 0x13F Ns \(en Ns Ad 0x142
|
||||
to a given string of exactly 4 characters.
|
||||
If both this and the title are set, the game ID will overwrite the
|
||||
overlapping portion of the title.
|
||||
@@ -51,7 +51,7 @@ Set the non-Japanese region flag:
|
||||
= 1.
|
||||
.It Fl k Ar licensee_str
|
||||
Set the new licensee string
|
||||
.Pq Ad 0x144 No Ns \(en Ns Ad 0x145
|
||||
.Pq Ad 0x144 Ns \(en Ns Ad 0x145
|
||||
to a given string, truncated to at most two characters.
|
||||
.It Fl l Ar licensee_id
|
||||
Set the old licensee code,
|
||||
@@ -84,7 +84,7 @@ Set the SGB flag:
|
||||
= 3.
|
||||
.It Fl t Ar title
|
||||
Set the title string
|
||||
.Pq Ad 0x134 No Ns \(en Ns Ad 0x143
|
||||
.Pq Ad 0x134 Ns \(en Ns Ad 0x143
|
||||
to a given string, truncated to at most 16 characters.
|
||||
It is recommended to use 15 characters instead, to avoid clashing with the CGB
|
||||
flag
|
||||
@@ -93,23 +93,23 @@ If both this and the game ID are set, the game ID will overwrite the
|
||||
overlapping portion of the title.
|
||||
.It Fl v
|
||||
Validate the header and fix checksums: the Nintendo character area
|
||||
.Pq Ad 0x104 No Ns \(en Ns Ad 0x133 ,
|
||||
.Pq Ad 0x104 Ns \(en Ns Ad 0x133 ,
|
||||
the header checksum
|
||||
.Pq Ad 0x14D ,
|
||||
and the global checksum
|
||||
.Pq Ad 0x14E No Ns \(en Ns Ad 0x14F .
|
||||
.Pq Ad 0x14E Ns \(en Ns Ad 0x14F .
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
Most values in the ROM header are only cosmetic.
|
||||
The bare minimum requirements for a workable image are checksums, the Nintendo
|
||||
logo, and (if needed) the CGB/SGB flags.
|
||||
It is a good idea to pad the image to a valid size as well
|
||||
.Pq Dq valid No meaning a multiple of 32KiB .
|
||||
.Pq Do valid Dc meaning a multiple of 32KiB .
|
||||
.Pp
|
||||
The following will make a plain, no-color Game Boy game without checking for
|
||||
a valid size:
|
||||
.Pp
|
||||
.D1 $ rgbfix \-v foo.gb
|
||||
.D1 $ rgbfix -v foo.gb
|
||||
.Pp
|
||||
The following will make a SGB-enabled, color-enabled game with a title of
|
||||
.Dq foobar ,
|
||||
@@ -119,20 +119,19 @@ The Game Boy itself does not use the title, but some emulators or ROM managers
|
||||
might.
|
||||
.Pc
|
||||
.Pp
|
||||
.D1 $ rgbfix \-vcs \-l 0x33 \-p 0 \-t foobar baz.gb
|
||||
.D1 $ rgbfix -vcs -l 0x33 -p 0 -t foobar baz.gb
|
||||
.Pp
|
||||
The following will duplicate the header
|
||||
.Pq sans global checksum
|
||||
of the game
|
||||
.Dq Survival Kids :
|
||||
.Pp
|
||||
.D1 $ rgbfix \-cjsv \-k A4 \-l 0x33 \-m 0x1B \-p 0xFF \-r 3 \-t SURVIVALKIDAVKE SurvivalKids.gbc
|
||||
.D1 $ rgbfix -cjsv -k A4 -l 0x33 -m 0x1B -p 0xFF -r 3 -t SURVIVALKIDAVKE \
|
||||
SurvivalKids.gbc
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbds 7 ,
|
||||
.Xr rgbasm 1 ,
|
||||
.Xr rgblib 1 ,
|
||||
.Xr rgblink 1 ,
|
||||
.Xr gbz80 7
|
||||
.Xr rgbds 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally released by Carsten S\(/orensen as a standalone program called
|
||||
|
||||
@@ -1,306 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/types.h"
|
||||
#include "lib/libwrap.h"
|
||||
|
||||
SLONG
|
||||
file_Length(FILE * f)
|
||||
{
|
||||
ULONG r, p;
|
||||
|
||||
p = ftell(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
r = ftell(f);
|
||||
fseek(f, p, SEEK_SET);
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
SLONG
|
||||
file_ReadASCIIz(char *b, FILE * f)
|
||||
{
|
||||
SLONG r = 0;
|
||||
|
||||
while ((*b++ = fgetc(f)) != 0)
|
||||
r += 1;
|
||||
|
||||
return (r + 1);
|
||||
}
|
||||
|
||||
void
|
||||
file_WriteASCIIz(char *b, FILE * f)
|
||||
{
|
||||
while (*b)
|
||||
fputc(*b++, f);
|
||||
|
||||
fputc(0, f);
|
||||
}
|
||||
|
||||
UWORD
|
||||
file_ReadWord(FILE * f)
|
||||
{
|
||||
UWORD r;
|
||||
|
||||
r = fgetc(f);
|
||||
r |= fgetc(f) << 8;
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
file_WriteWord(UWORD w, FILE * f)
|
||||
{
|
||||
fputc(w, f);
|
||||
fputc(w >> 8, f);
|
||||
}
|
||||
|
||||
ULONG
|
||||
file_ReadLong(FILE * f)
|
||||
{
|
||||
ULONG r;
|
||||
|
||||
r = fgetc(f);
|
||||
r |= fgetc(f) << 8;
|
||||
r |= fgetc(f) << 16;
|
||||
r |= fgetc(f) << 24;
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
file_WriteLong(UWORD w, FILE * f)
|
||||
{
|
||||
fputc(w, f);
|
||||
fputc(w >> 8, f);
|
||||
fputc(w >> 16, f);
|
||||
fputc(w >> 24, f);
|
||||
}
|
||||
|
||||
sLibrary *
|
||||
lib_ReadLib0(FILE * f, SLONG size)
|
||||
{
|
||||
if (size) {
|
||||
sLibrary *l = NULL, *first = NULL;
|
||||
|
||||
while (size > 0) {
|
||||
if (l == NULL) {
|
||||
l = malloc(sizeof *l);
|
||||
if (!l) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
first = l;
|
||||
} else {
|
||||
l->pNext = malloc(sizeof *l->pNext);
|
||||
if (!l->pNext) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
l = l->pNext;
|
||||
}
|
||||
|
||||
size -= file_ReadASCIIz(l->tName, f);
|
||||
l->uwTime = file_ReadWord(f);
|
||||
size -= 2;
|
||||
l->uwDate = file_ReadWord(f);
|
||||
size -= 2;
|
||||
l->nByteLength = file_ReadLong(f);
|
||||
size -= 4;
|
||||
if ((l->pData = malloc(l->nByteLength))) {
|
||||
fread(l->pData, sizeof(UBYTE), l->nByteLength,
|
||||
f);
|
||||
size -= l->nByteLength;
|
||||
} else {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
l->pNext = NULL;
|
||||
}
|
||||
return (first);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
sLibrary *
|
||||
lib_Read(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
if ((f = fopen(filename, "rb"))) {
|
||||
SLONG size;
|
||||
char ID[5];
|
||||
|
||||
size = file_Length(f);
|
||||
if (size == 0) {
|
||||
fclose(f);
|
||||
return (NULL);
|
||||
}
|
||||
fread(ID, sizeof(char), 4, f);
|
||||
ID[4] = 0;
|
||||
size -= 4;
|
||||
|
||||
if (strcmp(ID, "XLB0") == 0) {
|
||||
sLibrary *r;
|
||||
|
||||
r = lib_ReadLib0(f, size);
|
||||
fclose(f);
|
||||
printf("Library '%s' opened\n", filename);
|
||||
return (r);
|
||||
} else {
|
||||
fclose(f);
|
||||
fprintf(stderr, "Not a valid xLib library\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
printf
|
||||
("Library '%s' not found, it will be created if necessary\n",
|
||||
filename);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
BBOOL
|
||||
lib_Write(sLibrary * lib, char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
if ((f = fopen(filename, "wb"))) {
|
||||
fwrite("XLB0", sizeof(char), 4, f);
|
||||
while (lib) {
|
||||
file_WriteASCIIz(lib->tName, f);
|
||||
file_WriteWord(lib->uwTime, f);
|
||||
file_WriteWord(lib->uwDate, f);
|
||||
file_WriteLong(lib->nByteLength, f);
|
||||
fwrite(lib->pData, sizeof(UBYTE), lib->nByteLength, f);
|
||||
lib = lib->pNext;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
printf("Library '%s' closed\n", filename);
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
sLibrary *
|
||||
lib_Find(sLibrary * lib, char *filename)
|
||||
{
|
||||
if (strlen(filename) >= MAXNAMELENGTH) {
|
||||
fprintf(stderr, "Module name too long: %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (lib) {
|
||||
if (strcmp(lib->tName, filename) == 0)
|
||||
break;
|
||||
|
||||
lib = lib->pNext;
|
||||
}
|
||||
|
||||
return (lib);
|
||||
}
|
||||
|
||||
sLibrary *
|
||||
lib_AddReplace(sLibrary * lib, char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
if ((f = fopen(filename, "rb"))) {
|
||||
sLibrary *module;
|
||||
|
||||
if (strlen(filename) >= MAXNAMELENGTH) {
|
||||
fprintf(stderr, "Module name too long: %s\n",
|
||||
filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((module = lib_Find(lib, filename)) == NULL) {
|
||||
module = malloc(sizeof *module);
|
||||
if (!module) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
module->pNext = lib;
|
||||
lib = module;
|
||||
} else {
|
||||
/* Module already exists */
|
||||
free(module->pData);
|
||||
}
|
||||
|
||||
module->nByteLength = file_Length(f);
|
||||
strcpy(module->tName, filename);
|
||||
module->pData = malloc(module->nByteLength);
|
||||
if (!module->pData) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fread(module->pData, sizeof(UBYTE), module->nByteLength, f);
|
||||
|
||||
printf("Added module '%s'\n", filename);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
return (lib);
|
||||
}
|
||||
|
||||
sLibrary *
|
||||
lib_DeleteModule(sLibrary * lib, char *filename)
|
||||
{
|
||||
sLibrary **pp, **first;
|
||||
BBOOL found = 0;
|
||||
|
||||
pp = &lib;
|
||||
first = pp;
|
||||
|
||||
if (strlen(filename) >= MAXNAMELENGTH) {
|
||||
fprintf(stderr, "Module name too long: %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while ((*pp) && (!found)) {
|
||||
if (strcmp((*pp)->tName, filename) == 0) {
|
||||
sLibrary *t;
|
||||
|
||||
t = *pp;
|
||||
|
||||
if (t->pData)
|
||||
free(t->pData);
|
||||
|
||||
*pp = t->pNext;
|
||||
|
||||
free(t);
|
||||
found = 1;
|
||||
}
|
||||
pp = &((*pp)->pNext);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
fprintf(stderr, "Module not found\n");
|
||||
exit(1);
|
||||
} else
|
||||
printf("Module '%s' deleted from library\n", filename);
|
||||
|
||||
return (*first);
|
||||
}
|
||||
|
||||
void
|
||||
lib_Free(sLibrary * lib)
|
||||
{
|
||||
while (lib) {
|
||||
sLibrary *l;
|
||||
|
||||
if (lib->pData)
|
||||
free(lib->pData);
|
||||
|
||||
l = lib;
|
||||
lib = lib->pNext;
|
||||
free(l);
|
||||
}
|
||||
}
|
||||
120
src/lib/main.c
120
src/lib/main.c
@@ -1,120 +0,0 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asmotor.h"
|
||||
|
||||
#include "lib/types.h"
|
||||
#include "lib/library.h"
|
||||
|
||||
/*
|
||||
* Print the usagescreen
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("RGBLib v" LIB_VERSION " (part of ASMotor " ASMOTOR_VERSION ")\n\n");
|
||||
printf("usage: rgblib file [add | delete | extract | list] [module ...]\n");
|
||||
exit(1);
|
||||
}
|
||||
/*
|
||||
* The main routine
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
SLONG argn = 0;
|
||||
char *libname;
|
||||
|
||||
argc -= 1;
|
||||
argn += 1;
|
||||
|
||||
if (argc >= 2) {
|
||||
sLibrary *lib;
|
||||
|
||||
lib = lib_Read(libname = argv[argn++]);
|
||||
argc -= 1;
|
||||
|
||||
if (strcmp(argv[argn], "add") == 0) {
|
||||
argn += 1;
|
||||
argc -= 1;
|
||||
|
||||
while (argc) {
|
||||
lib = lib_AddReplace(lib, argv[argn++]);
|
||||
argc -= 1;
|
||||
}
|
||||
lib_Write(lib, libname);
|
||||
lib_Free(lib);
|
||||
} else if (strcmp(argv[argn], "delete") == 0) {
|
||||
argn += 1;
|
||||
argc -= 1;
|
||||
|
||||
while (argc) {
|
||||
lib =
|
||||
lib_DeleteModule(lib, argv[argn++]);
|
||||
argc -= 1;
|
||||
}
|
||||
lib_Write(lib, libname);
|
||||
lib_Free(lib);
|
||||
} else if (strcmp(argv[argn], "extract") == 0) {
|
||||
argn += 1;
|
||||
argc -= 1;
|
||||
|
||||
while (argc) {
|
||||
sLibrary *l;
|
||||
|
||||
l = lib_Find(lib, argv[argn]);
|
||||
if (l) {
|
||||
FILE *f;
|
||||
|
||||
if ((f = fopen(argv[argn], "wb"))) {
|
||||
fwrite(l->pData,
|
||||
sizeof(UBYTE),
|
||||
l->nByteLength,
|
||||
f);
|
||||
fclose(f);
|
||||
printf
|
||||
("Extracted module '%s'\n",
|
||||
argv[argn]);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Unable to write module '%s': ", argv[argn]);
|
||||
perror(NULL);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Module not found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
argn += 1;
|
||||
argc -= 1;
|
||||
}
|
||||
lib_Free(lib);
|
||||
} else if (strcmp(argv[argn], "list") == 0) {
|
||||
argn += 1;
|
||||
argc -= 1;
|
||||
|
||||
sLibrary *l;
|
||||
|
||||
l = lib;
|
||||
|
||||
while (l) {
|
||||
printf("%10ld %s\n",
|
||||
l->nByteLength,
|
||||
l->tName);
|
||||
l = l->pNext;
|
||||
}
|
||||
} else
|
||||
usage();
|
||||
} else
|
||||
usage();
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dt RGBLIB 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
.Nm rgblib
|
||||
.Nd Game Boy library manager
|
||||
.Sh SYNOPSIS
|
||||
.Nm rgblib
|
||||
.Ar library
|
||||
.Op add | delete | extract | list
|
||||
.Ar module ...
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
program manages libraries for use with
|
||||
.Xr rgblink 1 .
|
||||
.Bl -tag -width Ds
|
||||
.It add
|
||||
Add the given modules to the library.
|
||||
.It delete
|
||||
Delete the given modules from the library.
|
||||
.It extract
|
||||
Extract the given modules from the library.
|
||||
.It list
|
||||
List all the modules in the library.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbds 7 ,
|
||||
.Xr rgbasm 1 ,
|
||||
.Xr rgbfix 1 ,
|
||||
.Xr rgblink 1 ,
|
||||
.Xr gbz80 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally released by Carsten S\(/orensen as part of the ASMotor package,
|
||||
and was later packaged in RGBDS by Justin Lloyd.
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/main.h"
|
||||
#include "link/symbol.h"
|
||||
@@ -15,8 +16,14 @@ struct sFreeArea {
|
||||
struct sFreeArea *BankFree[MAXBANKS];
|
||||
SLONG MaxAvail[MAXBANKS];
|
||||
SLONG MaxBankUsed;
|
||||
SLONG MaxWBankUsed;
|
||||
SLONG MaxSBankUsed;
|
||||
SLONG MaxVBankUsed;
|
||||
|
||||
#define DOMAXBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
|
||||
#define DOMAXWBANK(x) {if( (x)>MaxWBankUsed ) MaxWBankUsed=(x);}
|
||||
#define DOMAXSBANK(x) {if( (x)>MaxSBankUsed ) MaxSBankUsed=(x);}
|
||||
#define DOMAXVBANK(x) {if( (x)>MaxVBankUsed ) MaxVBankUsed=(x);}
|
||||
|
||||
SLONG
|
||||
area_Avail(SLONG bank)
|
||||
@@ -57,7 +64,6 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
||||
struct sFreeArea *pNewArea;
|
||||
|
||||
if ((pNewArea =
|
||||
(struct sFreeArea *)
|
||||
malloc(sizeof(struct sFreeArea)))
|
||||
!= NULL) {
|
||||
*pNewArea = *pArea;
|
||||
@@ -71,9 +77,7 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
||||
|
||||
return (org);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,11 +90,51 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocAbsCODEAnyBank(SLONG org, SLONG size)
|
||||
area_AllocAbsSRAMAnyBank(SLONG org, SLONG size)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (area_AllocAbs(&BankFree[BANK_SRAM + i], org, size) == org) {
|
||||
return BANK_SRAM + i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocAbsWRAMAnyBank(SLONG org, SLONG size)
|
||||
{
|
||||
SLONG i;
|
||||
|
||||
for (i = 1; i <= 255; i += 1) {
|
||||
for (i = 1; i <= 7; i += 1) {
|
||||
if (area_AllocAbs(&BankFree[BANK_WRAMX + i - 1], org, size) == org) {
|
||||
return BANK_WRAMX + i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocAbsVRAMAnyBank(SLONG org, SLONG size)
|
||||
{
|
||||
if (area_AllocAbs(&BankFree[BANK_VRAM], org, size) == org) {
|
||||
return BANK_VRAM;
|
||||
}
|
||||
if (area_AllocAbs(&BankFree[BANK_VRAM + 1], org, size) == org) {
|
||||
return BANK_VRAM + 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocAbsROMXAnyBank(SLONG org, SLONG size)
|
||||
{
|
||||
SLONG i;
|
||||
|
||||
for (i = 1; i <= 511; i += 1) {
|
||||
if (area_AllocAbs(&BankFree[i], org, size) == org)
|
||||
return (i);
|
||||
}
|
||||
@@ -122,11 +166,11 @@ area_Alloc(struct sFreeArea ** ppArea, SLONG size)
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocCODEAnyBank(SLONG size)
|
||||
area_AllocVRAMAnyBank(SLONG size)
|
||||
{
|
||||
SLONG i, org;
|
||||
|
||||
for (i = 1; i <= 255; i += 1) {
|
||||
for (i = BANK_VRAM; i <= BANK_VRAM + 1; i += 1) {
|
||||
if ((org = area_Alloc(&BankFree[i], size)) != -1)
|
||||
return ((i << 16) | org);
|
||||
}
|
||||
@@ -134,6 +178,103 @@ area_AllocCODEAnyBank(SLONG size)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocSRAMAnyBank(SLONG size)
|
||||
{
|
||||
SLONG i, org;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if ((org = area_Alloc(&BankFree[BANK_SRAM + i], size)) != -1) {
|
||||
return (i << 16) | org;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocWRAMAnyBank(SLONG size)
|
||||
{
|
||||
SLONG i, org;
|
||||
|
||||
for (i = 1; i <= 7; i += 1) {
|
||||
if ((org = area_Alloc(&BankFree[BANK_WRAMX + i - 1], size)) != -1) {
|
||||
return (i << 16) | org;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocROMXAnyBank(SLONG size)
|
||||
{
|
||||
SLONG i, org;
|
||||
|
||||
for (i = 1; i <= 511; i += 1) {
|
||||
if ((org = area_Alloc(&BankFree[i], size)) != -1)
|
||||
return ((i << 16) | org);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
struct sSection *
|
||||
FindLargestWRAM(void)
|
||||
{
|
||||
struct sSection *pSection, *r = NULL;
|
||||
SLONG nLargest = 0;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == SECT_WRAMX) {
|
||||
if (pSection->nByteSize > nLargest) {
|
||||
nLargest = pSection->nByteSize;
|
||||
r = pSection;
|
||||
}
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
struct sSection *
|
||||
FindLargestVRAM(void)
|
||||
{
|
||||
struct sSection *pSection, *r = NULL;
|
||||
SLONG nLargest = 0;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == SECT_VRAM) {
|
||||
if (pSection->nByteSize > nLargest) {
|
||||
nLargest = pSection->nByteSize;
|
||||
r = pSection;
|
||||
}
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
struct sSection *
|
||||
FindLargestSRAM(void)
|
||||
{
|
||||
struct sSection *pSection, *r = NULL;
|
||||
SLONG nLargest = 0;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == SECT_SRAM) {
|
||||
if (pSection->nByteSize > nLargest) {
|
||||
nLargest = pSection->nByteSize;
|
||||
r = pSection;
|
||||
}
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
struct sSection *
|
||||
FindLargestCode(void)
|
||||
{
|
||||
@@ -142,7 +283,7 @@ FindLargestCode(void)
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == SECT_CODE) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == SECT_ROMX) {
|
||||
if (pSection->nByteSize > nLargest) {
|
||||
nLargest = pSection->nByteSize;
|
||||
r = pSection;
|
||||
@@ -153,6 +294,65 @@ FindLargestCode(void)
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
AssignVRAMSections(void)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
|
||||
while ((pSection = FindLargestVRAM())) {
|
||||
SLONG org;
|
||||
|
||||
if ((org = area_AllocVRAMAnyBank(pSection->nByteSize)) != -1) {
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXVBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place VRAM section anywhere");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AssignSRAMSections(void)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
|
||||
while ((pSection = FindLargestSRAM())) {
|
||||
SLONG org;
|
||||
|
||||
if ((org = area_AllocSRAMAnyBank(pSection->nByteSize)) != -1) {
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
pSection->nBank += BANK_SRAM;
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXSBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place SRAM section anywhere");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AssignWRAMSections(void)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
|
||||
while ((pSection = FindLargestWRAM())) {
|
||||
SLONG org;
|
||||
|
||||
if ((org = area_AllocWRAMAnyBank(pSection->nByteSize)) != -1) {
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
pSection->nBank += BANK_WRAMX - 1;
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXWBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place WRAMX section anywhere");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AssignCodeSections(void)
|
||||
{
|
||||
@@ -161,15 +361,13 @@ AssignCodeSections(void)
|
||||
while ((pSection = FindLargestCode())) {
|
||||
SLONG org;
|
||||
|
||||
if ((org = area_AllocCODEAnyBank(pSection->nByteSize)) != -1) {
|
||||
if ((org = area_AllocROMXAnyBank(pSection->nByteSize)) != -1) {
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->nBank);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Unable to place CODE section anywhere\n");
|
||||
exit(1);
|
||||
errx(1, "Unable to place ROMX section anywhere");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,11 +389,11 @@ AssignSections(void)
|
||||
BankFree[i] = malloc(sizeof *BankFree[i]);
|
||||
|
||||
if (!BankFree[i]) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
/* ROM0 bank */
|
||||
BankFree[i]->nOrg = 0x0000;
|
||||
if (options & OPT_SMALL) {
|
||||
BankFree[i]->nSize = 0x8000;
|
||||
@@ -204,7 +402,8 @@ AssignSections(void)
|
||||
BankFree[i]->nSize = 0x4000;
|
||||
MaxAvail[i] = 0x4000;
|
||||
}
|
||||
} else if (i >= 1 && i <= 255) {
|
||||
} else if (i >= 1 && i <= 511) {
|
||||
/* Swappable ROM bank */
|
||||
BankFree[i]->nOrg = 0x4000;
|
||||
/*
|
||||
* Now, this shouldn't really be necessary... but for
|
||||
@@ -217,15 +416,28 @@ AssignSections(void)
|
||||
BankFree[i]->nSize = 0x4000;
|
||||
MaxAvail[i] = 0x4000;
|
||||
}
|
||||
} else if (i == BANK_BSS) {
|
||||
} else if (i == BANK_WRAM0) {
|
||||
/* WRAM */
|
||||
BankFree[i]->nOrg = 0xC000;
|
||||
BankFree[i]->nSize = 0x1000;
|
||||
MaxAvail[i] = 0x1000;
|
||||
} else if (i >= BANK_SRAM && i <= BANK_SRAM + 3) {
|
||||
/* Swappable SRAM bank */
|
||||
BankFree[i]->nOrg = 0xA000;
|
||||
BankFree[i]->nSize = 0x2000;
|
||||
MaxAvail[i] = 0x2000;
|
||||
} else if (i == BANK_VRAM) {
|
||||
} else if (i >= BANK_WRAMX && i <= BANK_WRAMX + 6) {
|
||||
/* Swappable WRAM bank */
|
||||
BankFree[i]->nOrg = 0xD000;
|
||||
BankFree[i]->nSize = 0x1000;
|
||||
MaxAvail[i] = 0x1000;
|
||||
} else if (i == BANK_VRAM || i == BANK_VRAM + 1) {
|
||||
/* Swappable VRAM bank */
|
||||
BankFree[i]->nOrg = 0x8000;
|
||||
BankFree[i]->nSize = 0x2000;
|
||||
MaxAvail[i] = 0x2000;
|
||||
} else if (i == BANK_HRAM) {
|
||||
/* HRAM */
|
||||
BankFree[i]->nOrg = 0xFF80;
|
||||
BankFree[i]->nSize = 0x007F;
|
||||
MaxAvail[i] = 0x007F;
|
||||
@@ -247,55 +459,191 @@ AssignSections(void)
|
||||
/* User wants to have a say... */
|
||||
|
||||
switch (pSection->Type) {
|
||||
case SECT_BSS:
|
||||
case SECT_WRAM0:
|
||||
if (area_AllocAbs
|
||||
(&BankFree[BANK_BSS], pSection->nOrg,
|
||||
(&BankFree[BANK_WRAM0], pSection->nOrg,
|
||||
pSection->nByteSize) != pSection->nOrg) {
|
||||
fprintf(stderr,
|
||||
"Unable to load fixed BSS section "
|
||||
"at $%lX\n", pSection->nOrg);
|
||||
exit(1);
|
||||
errx(1,
|
||||
"Unable to load fixed WRAM0 "
|
||||
"section at $%lX", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
pSection->nBank = BANK_BSS;
|
||||
pSection->nBank = BANK_WRAM0;
|
||||
break;
|
||||
case SECT_HRAM:
|
||||
if (area_AllocAbs
|
||||
(&BankFree[BANK_HRAM], pSection->nOrg,
|
||||
pSection->nByteSize) != pSection->nOrg) {
|
||||
fprintf(stderr, "Unable to load fixed "
|
||||
"HRAM section at $%lX\n",
|
||||
pSection->nOrg);
|
||||
exit(1);
|
||||
errx(1, "Unable to load fixed HRAM "
|
||||
"section at $%lX", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
pSection->nBank = BANK_HRAM;
|
||||
break;
|
||||
case SECT_SRAM:
|
||||
if (pSection->nBank == -1) {
|
||||
/*
|
||||
* User doesn't care which bank.
|
||||
* Therefore he must here be specifying
|
||||
* position within the bank.
|
||||
* Defer until later.
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
/*
|
||||
* User specified which bank to use.
|
||||
* Does he also care about position
|
||||
* within the bank?
|
||||
*/
|
||||
if (pSection->nOrg == -1) {
|
||||
/*
|
||||
* Nope, any position will do
|
||||
* Again, we'll do that later
|
||||
*
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
/*
|
||||
* Bank and position within the
|
||||
* bank are hardcoded.
|
||||
*/
|
||||
|
||||
if (pSection->nBank >= 0
|
||||
&& pSection->nBank <= 3) {
|
||||
pSection->nBank +=
|
||||
BANK_SRAM;
|
||||
if (area_AllocAbs
|
||||
(&BankFree
|
||||
[pSection->nBank],
|
||||
pSection->nOrg,
|
||||
pSection->nByteSize)
|
||||
!= pSection->nOrg) {
|
||||
errx(1,
|
||||
"Unable to load fixed SRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
DOMAXVBANK(pSection->
|
||||
nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
errx(1,
|
||||
"Unable to load fixed SRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SECT_WRAMX:
|
||||
if (pSection->nBank == -1) {
|
||||
/*
|
||||
* User doesn't care which bank.
|
||||
* Therefore he must here be specifying
|
||||
* position within the bank.
|
||||
* Defer until later.
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
/*
|
||||
* User specified which bank to use.
|
||||
* Does he also care about position
|
||||
* within the bank?
|
||||
*/
|
||||
if (pSection->nOrg == -1) {
|
||||
/*
|
||||
* Nope, any position will do
|
||||
* Again, we'll do that later
|
||||
*
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
/*
|
||||
* Bank and position within the
|
||||
* bank are hardcoded.
|
||||
*/
|
||||
|
||||
if (pSection->nBank >= 0
|
||||
&& pSection->nBank <= 6) {
|
||||
pSection->nBank +=
|
||||
BANK_WRAMX;
|
||||
if (area_AllocAbs
|
||||
(&BankFree
|
||||
[pSection->nBank],
|
||||
pSection->nOrg,
|
||||
pSection->nByteSize)
|
||||
!= pSection->nOrg) {
|
||||
errx(1,
|
||||
"Unable to load fixed WRAMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
DOMAXWBANK(pSection->
|
||||
nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
errx(1,
|
||||
"Unable to load fixed WRAMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SECT_VRAM:
|
||||
if (pSection->nBank == -1) {
|
||||
/*
|
||||
* User doesn't care which bank.
|
||||
* Therefore he must here be specifying
|
||||
* position within the bank.
|
||||
* Defer until later.
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
/*
|
||||
* User specified which bank to use.
|
||||
* Does he also care about position
|
||||
* within the bank?
|
||||
*/
|
||||
if (pSection->nOrg == -1) {
|
||||
/*
|
||||
* Nope, any position will do
|
||||
* Again, we'll do that later
|
||||
*
|
||||
*/
|
||||
;
|
||||
} else {
|
||||
/*
|
||||
* Bank and position within the
|
||||
* bank are hardcoded.
|
||||
*/
|
||||
|
||||
if (pSection->nBank >= 0
|
||||
&& pSection->nBank <= 1) {
|
||||
pSection->nBank +=
|
||||
BANK_VRAM;
|
||||
if (area_AllocAbs
|
||||
(&BankFree
|
||||
[pSection->nBank],
|
||||
pSection->nOrg,
|
||||
pSection->nByteSize)
|
||||
!= pSection->nOrg) {
|
||||
errx(1,
|
||||
"Unable to load fixed VRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
DOMAXVBANK(pSection->
|
||||
nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
errx(1,
|
||||
"Unable to load fixed VRAM section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SECT_ROM0:
|
||||
if (area_AllocAbs
|
||||
(&BankFree[BANK_VRAM], pSection->nOrg,
|
||||
(&BankFree[BANK_ROM0], pSection->nOrg,
|
||||
pSection->nByteSize) != pSection->nOrg) {
|
||||
fprintf(stderr, "Unable to load fixed "
|
||||
"VRAM section at $%lX\n",
|
||||
pSection->nOrg);
|
||||
exit(1);
|
||||
errx(1, "Unable to load fixed ROM0 "
|
||||
"section at $%lX", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
pSection->nBank = BANK_VRAM;
|
||||
pSection->nBank = BANK_ROM0;
|
||||
break;
|
||||
case SECT_HOME:
|
||||
if (area_AllocAbs
|
||||
(&BankFree[BANK_HOME], pSection->nOrg,
|
||||
pSection->nByteSize) != pSection->nOrg) {
|
||||
fprintf(stderr, "Unable to load fixed "
|
||||
"HOME section at $%lX\n",
|
||||
pSection->nOrg);
|
||||
exit(1);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
pSection->nBank = BANK_HOME;
|
||||
break;
|
||||
case SECT_CODE:
|
||||
case SECT_ROMX:
|
||||
if (pSection->nBank == -1) {
|
||||
/*
|
||||
* User doesn't care which bank, so he must want to
|
||||
@@ -327,7 +675,7 @@ AssignSections(void)
|
||||
*/
|
||||
|
||||
if (pSection->nBank >= 1
|
||||
&& pSection->nBank <= 255) {
|
||||
&& pSection->nBank <= 511) {
|
||||
if (area_AllocAbs
|
||||
(&BankFree
|
||||
[pSection->nBank],
|
||||
@@ -335,15 +683,15 @@ AssignSections(void)
|
||||
pSection->
|
||||
nByteSize) !=
|
||||
pSection->nOrg) {
|
||||
fprintf(stderr, "Unable to load fixed CODE/DATA section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
|
||||
exit(1);
|
||||
errx(1,
|
||||
"Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
DOMAXBANK(pSection->
|
||||
nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
fprintf(stderr, "Unable to load fixed CODE/DATA section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank);
|
||||
exit(1);
|
||||
errx(1,
|
||||
"Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,54 +703,139 @@ AssignSections(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Next, let's assign all the bankfixed ONLY CODE sections...
|
||||
* Next, let's assign all the bankfixed ONLY ROMX sections...
|
||||
*
|
||||
*/
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_CODE
|
||||
&& pSection->Type == SECT_ROMX
|
||||
&& pSection->nOrg == -1 && pSection->nBank != -1) {
|
||||
/* User wants to have a say... and he's pissed */
|
||||
if (pSection->nBank >= 1 && pSection->nBank <= 255) {
|
||||
if (pSection->nBank >= 1 && pSection->nBank <= 511) {
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[pSection->nBank],
|
||||
pSection->nByteSize)) == -1) {
|
||||
fprintf(stderr, "Unable to load fixed CODE/DATA section into bank $%02lX\n", pSection->nBank);
|
||||
exit(1);
|
||||
errx(1,
|
||||
"Unable to load fixed ROMX section into bank $%02lX", pSection->nBank);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->nBank);
|
||||
} else {
|
||||
fprintf(stderr, "Unable to load fixed CODE/DATA section into bank $%02lX\n", pSection->nBank);
|
||||
exit(1);
|
||||
errx(1, "Unable to load fixed ROMX section into bank $%02lX", pSection->nBank);
|
||||
}
|
||||
} else if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_SRAM
|
||||
&& pSection->nOrg == -1 && pSection->nBank != -1) {
|
||||
pSection->nBank += BANK_SRAM;
|
||||
/* User wants to have a say... and he's pissed */
|
||||
if (pSection->nBank >= BANK_SRAM && pSection->nBank <= BANK_SRAM + 3) {
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[pSection->nBank],
|
||||
pSection->nByteSize)) == -1) {
|
||||
errx(1, "Unable to load fixed SRAM section into bank $%02lX", pSection->nBank);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXSBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank);
|
||||
}
|
||||
} else if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_VRAM
|
||||
&& pSection->nOrg == -1 && pSection->nBank != -1) {
|
||||
pSection->nBank += BANK_VRAM;
|
||||
/* User wants to have a say... and he's pissed */
|
||||
if (pSection->nBank >= BANK_VRAM && pSection->nBank <= BANK_VRAM + 1) {
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[pSection->nBank],
|
||||
pSection->nByteSize)) == -1) {
|
||||
errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXVBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to load fixed VRAM section into bank $%02lX", pSection->nBank);
|
||||
}
|
||||
} else if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_WRAMX
|
||||
&& pSection->nOrg == -1 && pSection->nBank != -1) {
|
||||
pSection->nBank += BANK_WRAMX;
|
||||
/* User wants to have a say... and he's pissed */
|
||||
if (pSection->nBank >= BANK_WRAMX && pSection->nBank <= BANK_WRAMX + 6) {
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[pSection->nBank],
|
||||
pSection->nByteSize)) == -1) {
|
||||
errx(1, "Unable to load fixed WRAMX section into bank $%02lX", pSection->nBank - BANK_WRAMX);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXWBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to load fixed WRAMX section into bank $%02lX", pSection->nBank - BANK_WRAMX);
|
||||
}
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, let's assign all the floating bank but fixed CODE sections...
|
||||
* Now, let's assign all the floating bank but fixed ROMX sections...
|
||||
*
|
||||
*/
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_CODE
|
||||
&& pSection->Type == SECT_ROMX
|
||||
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
||||
/* User wants to have a say... and he's back with a
|
||||
* vengeance */
|
||||
if ((pSection->nBank =
|
||||
area_AllocAbsCODEAnyBank(pSection->nOrg,
|
||||
area_AllocAbsROMXAnyBank(pSection->nOrg,
|
||||
pSection->nByteSize)) ==
|
||||
-1) {
|
||||
fprintf(stderr, "Unable to load fixed CODE/DATA section at $%lX into any bank\n", pSection->nOrg);
|
||||
exit(1);
|
||||
errx(1, "Unable to load fixed ROMX section at $%lX into any bank", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->nBank);
|
||||
} else if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_VRAM
|
||||
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
||||
/* User wants to have a say... and he's back with a
|
||||
* vengeance */
|
||||
if ((pSection->nBank =
|
||||
area_AllocAbsVRAMAnyBank(pSection->nOrg,
|
||||
pSection->nByteSize)) ==
|
||||
-1) {
|
||||
errx(1, "Unable to load fixed VRAM section at $%lX into any bank", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXVBANK(pSection->nBank);
|
||||
} else if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_SRAM
|
||||
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
||||
/* User wants to have a say... and he's back with a
|
||||
* vengeance */
|
||||
if ((pSection->nBank =
|
||||
area_AllocAbsSRAMAnyBank(pSection->nOrg,
|
||||
pSection->nByteSize)) ==
|
||||
-1) {
|
||||
errx(1, "Unable to load fixed SRAM section at $%lX into any bank", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXSBANK(pSection->nBank);
|
||||
} else if (pSection->oAssigned == 0
|
||||
&& pSection->Type == SECT_WRAMX
|
||||
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
||||
/* User wants to have a say... and he's back with a
|
||||
* vengeance */
|
||||
if ((pSection->nBank =
|
||||
area_AllocAbsWRAMAnyBank(pSection->nOrg,
|
||||
pSection->nByteSize)) ==
|
||||
-1) {
|
||||
errx(1, "Unable to load fixed WRAMX section at $%lX into any bank", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXWBANK(pSection->nBank);
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
@@ -417,51 +850,43 @@ AssignSections(void)
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0) {
|
||||
switch (pSection->Type) {
|
||||
case SECT_BSS:
|
||||
case SECT_WRAM0:
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[BANK_BSS],
|
||||
area_Alloc(&BankFree[BANK_WRAM0],
|
||||
pSection->nByteSize)) == -1) {
|
||||
fprintf(stderr, "BSS section too large\n");
|
||||
exit(1);
|
||||
errx(1, "WRAM0 section too large");
|
||||
}
|
||||
pSection->nBank = BANK_BSS;
|
||||
pSection->nBank = BANK_WRAM0;
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
case SECT_HRAM:
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[BANK_HRAM],
|
||||
pSection->nByteSize)) == -1) {
|
||||
fprintf(stderr, "HRAM section too large\n");
|
||||
exit(1);
|
||||
errx(1, "HRAM section too large");
|
||||
}
|
||||
pSection->nBank = BANK_HRAM;
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
case SECT_SRAM:
|
||||
break;
|
||||
case SECT_VRAM:
|
||||
break;
|
||||
case SECT_WRAMX:
|
||||
break;
|
||||
case SECT_ROM0:
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[BANK_VRAM],
|
||||
area_Alloc(&BankFree[BANK_ROM0],
|
||||
pSection->nByteSize)) == -1) {
|
||||
fprintf(stderr, "VRAM section too large\n");
|
||||
exit(1);
|
||||
errx(1, "ROM0 section too large");
|
||||
}
|
||||
pSection->nBank = BANK_VRAM;
|
||||
pSection->nBank = BANK_ROM0;
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
case SECT_HOME:
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[BANK_HOME],
|
||||
pSection->nByteSize)) == -1) {
|
||||
fprintf(stderr, "HOME section too large\n");
|
||||
exit(1);
|
||||
}
|
||||
pSection->nBank = BANK_HOME;
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
case SECT_CODE:
|
||||
case SECT_ROMX:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "(INTERNAL) Unknown section type!\n");
|
||||
exit(1);
|
||||
errx(1, "(INTERNAL) Unknown section type!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -469,6 +894,9 @@ AssignSections(void)
|
||||
}
|
||||
|
||||
AssignCodeSections();
|
||||
AssignVRAMSections();
|
||||
AssignWRAMSections();
|
||||
AssignSRAMSections();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "link/types.h"
|
||||
#include "extern/err.h"
|
||||
#include "types.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/main.h"
|
||||
|
||||
@@ -91,9 +92,8 @@ AddNeededModules(void)
|
||||
}
|
||||
if (options & OPT_SMART_C_LINK) {
|
||||
if (!addmodulecontaining(smartlinkstartsymbol)) {
|
||||
fprintf(stderr, "Can't find start symbol '%s'\n",
|
||||
errx(1, "Can't find start symbol '%s'",
|
||||
smartlinkstartsymbol);
|
||||
exit(1);
|
||||
} else
|
||||
printf("Smart linking with symbol '%s'\n",
|
||||
smartlinkstartsymbol);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#include <getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "asmotor.h"
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/object.h"
|
||||
#include "link/output.h"
|
||||
#include "link/assign.h"
|
||||
@@ -26,6 +24,8 @@ SLONG options = 0;
|
||||
SLONG fillchar = 0;
|
||||
char smartlinkstartsymbol[256];
|
||||
|
||||
char *progname;
|
||||
|
||||
/*
|
||||
* Print the usagescreen
|
||||
*
|
||||
@@ -34,11 +34,9 @@ char smartlinkstartsymbol[256];
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("RGBLink v" LINK_VERSION " (part of ASMotor " ASMOTOR_VERSION
|
||||
")\n\n");
|
||||
printf("usage: rgblink [-t] [-l library] [-m mapfile] [-n symfile] [-o outfile]\n");
|
||||
printf("\t [-s symbol] [-z pad_value] objectfile [...]\n");
|
||||
|
||||
printf(
|
||||
"usage: rgblink [-t] [-m mapfile] [-n symfile] [-o outfile] [-p pad_value]\n"
|
||||
" [-s symbol] file [...]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -56,11 +54,10 @@ main(int argc, char *argv[])
|
||||
if (argc == 1)
|
||||
usage();
|
||||
|
||||
while ((ch = getopt(argc, argv, "l:m:n:o:p:s:t")) != -1) {
|
||||
progname = argv[0];
|
||||
|
||||
while ((ch = getopt(argc, argv, "m:n:o:p:s:t")) != -1) {
|
||||
switch (ch) {
|
||||
case 'l':
|
||||
lib_Readfile(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
SetMapfileName(optarg);
|
||||
break;
|
||||
@@ -73,8 +70,7 @@ main(int argc, char *argv[])
|
||||
case 'p':
|
||||
fillchar = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
fprintf(stderr, "Invalid argument for option 'p'\n");
|
||||
exit(1);
|
||||
errx(1, "Invalid argument for option 'p'");
|
||||
}
|
||||
if (fillchar < 0 || fillchar > 0xFF) {
|
||||
fprintf(stderr, "Argument for option 'p' must be between 0 and 0xFF");
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asmotor.h"
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/main.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/assign.h"
|
||||
@@ -20,9 +19,7 @@ SetMapfileName(char *name)
|
||||
mf = fopen(name, "w");
|
||||
|
||||
if (mf == NULL) {
|
||||
fprintf(stderr, "Cannot open mapfile '%s': ", name);
|
||||
perror(NULL);
|
||||
exit(1);
|
||||
err(1, "Cannot open mapfile '%s'", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +29,10 @@ SetSymfileName(char *name)
|
||||
sf = fopen(name, "w");
|
||||
|
||||
if (sf == NULL) {
|
||||
fprintf(stderr, "Cannot open symfile '%s'\n", name);
|
||||
exit(1);
|
||||
err(1, "Cannot open symfile '%s'", name);
|
||||
}
|
||||
|
||||
fprintf(sf, ";File generated by xLink v" LINK_VERSION "\n\n");
|
||||
fprintf(sf, ";File generated by rgblink\n\n");
|
||||
}
|
||||
|
||||
void
|
||||
@@ -57,33 +53,49 @@ MapfileInitBank(SLONG bank)
|
||||
{
|
||||
if (mf) {
|
||||
currentbank = bank;
|
||||
if (bank == 0)
|
||||
fprintf(mf, "Bank #0 (HOME):\n");
|
||||
else if (bank <= 255)
|
||||
fprintf(mf, "Bank #%ld:\n", bank);
|
||||
else if (bank == BANK_BSS)
|
||||
fprintf(mf, "BSS:\n");
|
||||
if (bank == BANK_ROM0)
|
||||
fprintf(mf, "ROM Bank #0 (HOME):\n");
|
||||
else if (bank < BANK_WRAM0)
|
||||
fprintf(mf, "ROM Bank #%ld:\n", bank);
|
||||
else if (bank == BANK_WRAM0)
|
||||
fprintf(mf, "WRAM Bank #0:\n");
|
||||
else if (bank < BANK_VRAM)
|
||||
fprintf(mf, "WRAM Bank #%ld:\n", bank - BANK_WRAMX + 1);
|
||||
else if (bank == BANK_HRAM)
|
||||
fprintf(mf, "HRAM:\n");
|
||||
else if (bank == BANK_VRAM)
|
||||
fprintf(mf, "VRAM:\n");
|
||||
else if (bank == BANK_VRAM || bank == BANK_VRAM + 1)
|
||||
fprintf(mf, "VRAM Bank #%ld:\n", bank - BANK_VRAM);
|
||||
else if (bank < MAXBANKS)
|
||||
fprintf(mf, "SRAM Bank #%ld:\n", bank - BANK_SRAM);
|
||||
}
|
||||
if (sf) {
|
||||
sfbank = (bank >= 1 && bank <= 255) ? bank : 0;
|
||||
if (bank < BANK_WRAM0)
|
||||
sfbank = bank;
|
||||
else if (bank == BANK_WRAM0)
|
||||
sfbank = 0;
|
||||
else if (bank < BANK_VRAM)
|
||||
sfbank = bank - BANK_WRAMX + 1;
|
||||
else if (bank == BANK_HRAM)
|
||||
sfbank = 0;
|
||||
else if (bank == BANK_VRAM || bank == BANK_VRAM + 1)
|
||||
sfbank = bank - BANK_VRAM;
|
||||
else if (bank < MAXBANKS)
|
||||
sfbank = bank - BANK_SRAM;
|
||||
else
|
||||
sfbank = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MapfileWriteSection(struct sSection * pSect)
|
||||
{
|
||||
if (!mf && !sf)
|
||||
return;
|
||||
|
||||
SLONG i;
|
||||
|
||||
fprintf(mf, " SECTION: $%04lX-$%04lX ($%04lX bytes)\n",
|
||||
pSect->nOrg, pSect->nOrg + pSect->nByteSize - 1,
|
||||
pSect->nByteSize);
|
||||
if (mf) {
|
||||
fprintf(mf, " SECTION: $%04lX-$%04lX ($%04lX bytes)\n",
|
||||
pSect->nOrg, pSect->nOrg + pSect->nByteSize - 1,
|
||||
pSect->nByteSize);
|
||||
}
|
||||
|
||||
for (i = 0; i < pSect->nNumberOfSymbols; i += 1) {
|
||||
struct sSymbol *pSym;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/main.h"
|
||||
|
||||
@@ -80,8 +81,7 @@ AllocSection(void)
|
||||
|
||||
*ppSections = malloc(sizeof **ppSections);
|
||||
if (!*ppSections) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
(*ppSections)->tSymbols = tSymbols;
|
||||
(*ppSections)->pNext = NULL;
|
||||
@@ -102,15 +102,13 @@ obj_ReadSymbol(FILE * f)
|
||||
|
||||
pSym = malloc(sizeof *pSym);
|
||||
if (!pSym) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
readasciiz(s, f);
|
||||
pSym->pzName = malloc(strlen(s) + 1);
|
||||
if (!pSym->pzName) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
strcpy(pSym->pzName, s);
|
||||
@@ -139,10 +137,10 @@ obj_ReadRGB0Section(FILE * f)
|
||||
|
||||
/* does the user want the -s mode? */
|
||||
|
||||
if ((options & OPT_SMALL) && (pSection->Type == SECT_CODE)) {
|
||||
pSection->Type = SECT_HOME;
|
||||
if ((options & OPT_SMALL) && (pSection->Type == SECT_ROMX)) {
|
||||
pSection->Type = SECT_ROM0;
|
||||
}
|
||||
if ((pSection->Type == SECT_CODE) || (pSection->Type == SECT_HOME)) {
|
||||
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
|
||||
/*
|
||||
* These sectiontypes contain data...
|
||||
*
|
||||
@@ -150,7 +148,7 @@ obj_ReadRGB0Section(FILE * f)
|
||||
if (pSection->nByteSize) {
|
||||
pSection->pData = malloc(pSection->nByteSize);
|
||||
if (!pSection->pData) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
SLONG nNumberOfPatches;
|
||||
@@ -169,7 +167,7 @@ obj_ReadRGB0Section(FILE * f)
|
||||
while (nNumberOfPatches--) {
|
||||
pPatch = malloc(sizeof *pPatch);
|
||||
if (!pPatch) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
*ppPatch = pPatch;
|
||||
@@ -177,7 +175,7 @@ obj_ReadRGB0Section(FILE * f)
|
||||
|
||||
pPatch->pzFilename = malloc(strlen(s) + 1);
|
||||
if (!pPatch->pzFilename) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
strcpy(pPatch->pzFilename, s);
|
||||
@@ -193,8 +191,7 @@ obj_ReadRGB0Section(FILE * f)
|
||||
if ((pPatch->nRPNSize = readlong(f)) > 0) {
|
||||
pPatch->pRPN = malloc(pPatch->nRPNSize);
|
||||
if (!pPatch->pRPN) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
fread(pPatch->pRPN, sizeof(UBYTE),
|
||||
@@ -228,8 +225,7 @@ obj_ReadRGB0(FILE * pObjfile)
|
||||
if (nNumberOfSymbols) {
|
||||
tSymbols = malloc(nNumberOfSymbols * sizeof(struct sSymbol *));
|
||||
if (!tSymbols) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < nNumberOfSymbols; i += 1)
|
||||
@@ -294,10 +290,10 @@ obj_ReadRGB1Section(FILE * f)
|
||||
|
||||
/* does the user want the -s mode? */
|
||||
|
||||
if ((options & OPT_SMALL) && (pSection->Type == SECT_CODE)) {
|
||||
pSection->Type = SECT_HOME;
|
||||
if ((options & OPT_SMALL) && (pSection->Type == SECT_ROMX)) {
|
||||
pSection->Type = SECT_ROM0;
|
||||
}
|
||||
if ((pSection->Type == SECT_CODE) || (pSection->Type == SECT_HOME)) {
|
||||
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
|
||||
/*
|
||||
* These sectiontypes contain data...
|
||||
*
|
||||
@@ -305,8 +301,7 @@ obj_ReadRGB1Section(FILE * f)
|
||||
if (pSection->nByteSize) {
|
||||
pSection->pData = malloc(pSection->nByteSize);
|
||||
if (!pSection->pData) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
exit(1);
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
SLONG nNumberOfPatches;
|
||||
@@ -325,14 +320,14 @@ obj_ReadRGB1Section(FILE * f)
|
||||
while (nNumberOfPatches--) {
|
||||
pPatch = malloc(sizeof *pPatch);
|
||||
if (!pPatch) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
*ppPatch = pPatch;
|
||||
readasciiz(s, f);
|
||||
pPatch->pzFilename = malloc(strlen(s) + 1);
|
||||
if (!pPatch->pzFilename) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
strcpy(pPatch->pzFilename, s);
|
||||
@@ -342,7 +337,7 @@ obj_ReadRGB1Section(FILE * f)
|
||||
if ((pPatch->nRPNSize = readlong(f)) > 0) {
|
||||
pPatch->pRPN = malloc(pPatch->nRPNSize);
|
||||
if (!pPatch->pRPN) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
fread(pPatch->pRPN, sizeof(UBYTE),
|
||||
@@ -376,7 +371,7 @@ obj_ReadRGB1(FILE * pObjfile)
|
||||
if (nNumberOfSymbols) {
|
||||
tSymbols = malloc(nNumberOfSymbols * sizeof *tSymbols);
|
||||
if (!tSymbols) {
|
||||
fprintf(stderr, "Out of memory!\n");
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < nNumberOfSymbols; i += 1)
|
||||
@@ -440,14 +435,10 @@ obj_ReadOpenFile(FILE * pObjfile, char *tzObjectfile)
|
||||
obj_ReadRGB1(pObjfile);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "'%s' is an unsupported version",
|
||||
tzObjectfile);
|
||||
exit(1);
|
||||
break;
|
||||
errx(1, "'%s' is an unsupported version", tzObjectfile);
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "'%s' is not a valid object\n", tzObjectfile);
|
||||
exit(1);
|
||||
errx(1, "'%s' is not a valid object", tzObjectfile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,10 +454,7 @@ obj_Readfile(char *tzObjectfile)
|
||||
|
||||
pObjfile = fopen(tzObjectfile, "rb");
|
||||
if (pObjfile == NULL) {
|
||||
fprintf(stderr, "Unable to open object '%s': ",
|
||||
tzObjectfile);
|
||||
perror(NULL);
|
||||
exit(1);
|
||||
err(1, "Unable to open object '%s'", tzObjectfile);
|
||||
}
|
||||
obj_ReadOpenFile(pObjfile, tzObjectfile);
|
||||
fclose(pObjfile);
|
||||
@@ -506,34 +494,3 @@ lib_ReadXLB0(FILE * f)
|
||||
obj_ReadOpenFile(f, name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lib_Readfile(char *tzLibfile)
|
||||
{
|
||||
FILE *pObjfile;
|
||||
|
||||
oReadLib = 1;
|
||||
|
||||
pObjfile = fopen(tzLibfile, "rb");
|
||||
if (pObjfile == NULL) {
|
||||
fprintf(stderr, "Unable to open object '%s': ", tzLibfile);
|
||||
perror(NULL);
|
||||
exit(1);
|
||||
}
|
||||
if (!pObjfile) {
|
||||
fprintf(stderr, "Unable to open '%s'\n", tzLibfile);
|
||||
exit(1);
|
||||
}
|
||||
char tzHeader[5];
|
||||
|
||||
fread(tzHeader, sizeof(char), 4, pObjfile);
|
||||
tzHeader[4] = 0;
|
||||
if (strcmp(tzHeader, "XLB0") == 0)
|
||||
lib_ReadXLB0(pObjfile);
|
||||
else {
|
||||
fprintf(stderr, "'%s' is an invalid library\n",
|
||||
tzLibfile);
|
||||
exit(1);
|
||||
}
|
||||
fclose(pObjfile);
|
||||
}
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
#include "link/main.h"
|
||||
#include "link/assign.h"
|
||||
|
||||
char tzOutname[_MAX_PATH];
|
||||
BBOOL oOutput = 0;
|
||||
char *tzOutname;
|
||||
|
||||
void
|
||||
writehome(FILE * f)
|
||||
@@ -16,16 +15,16 @@ writehome(FILE * f)
|
||||
struct sSection *pSect;
|
||||
UBYTE *mem;
|
||||
|
||||
mem = malloc(MaxAvail[BANK_HOME]);
|
||||
mem = malloc(MaxAvail[BANK_ROM0]);
|
||||
if (!mem)
|
||||
return;
|
||||
|
||||
memset(mem, fillchar, MaxAvail[BANK_HOME]);
|
||||
memset(mem, fillchar, MaxAvail[BANK_ROM0]);
|
||||
MapfileInitBank(0);
|
||||
|
||||
pSect = pSections;
|
||||
while (pSect) {
|
||||
if (pSect->Type == SECT_HOME) {
|
||||
if (pSect->Type == SECT_ROM0) {
|
||||
memcpy(mem + pSect->nOrg, pSect->pData,
|
||||
pSect->nByteSize);
|
||||
MapfileWriteSection(pSect);
|
||||
@@ -35,7 +34,7 @@ writehome(FILE * f)
|
||||
|
||||
MapfileCloseBank(area_Avail(0));
|
||||
|
||||
fwrite(mem, 1, MaxAvail[BANK_HOME], f);
|
||||
fwrite(mem, 1, MaxAvail[BANK_ROM0], f);
|
||||
free(mem);
|
||||
}
|
||||
|
||||
@@ -54,7 +53,7 @@ writebank(FILE * f, SLONG bank)
|
||||
|
||||
pSect = pSections;
|
||||
while (pSect) {
|
||||
if (pSect->Type == SECT_CODE && pSect->nBank == bank) {
|
||||
if (pSect->Type == SECT_ROMX && pSect->nBank == bank) {
|
||||
memcpy(mem + pSect->nOrg - 0x4000, pSect->pData,
|
||||
pSect->nByteSize);
|
||||
MapfileWriteSection(pSect);
|
||||
@@ -71,8 +70,7 @@ writebank(FILE * f, SLONG bank)
|
||||
void
|
||||
out_Setname(char *tzOutputfile)
|
||||
{
|
||||
strcpy(tzOutname, tzOutputfile);
|
||||
oOutput = 1;
|
||||
tzOutname = tzOutputfile;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -88,7 +86,7 @@ Output(void)
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
for (i = 256; i < MAXBANKS; i += 1) {
|
||||
for (i = BANK_WRAM0; i < MAXBANKS; i++) {
|
||||
struct sSection *pSect;
|
||||
MapfileInitBank(i);
|
||||
pSect = pSections;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/assign.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/symbol.h"
|
||||
#include "link/main.h"
|
||||
@@ -46,26 +48,34 @@ getsymvalue(SLONG symid)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "*INTERNAL* UNKNOWN SYMBOL TYPE\n");
|
||||
exit(1);
|
||||
errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
|
||||
}
|
||||
|
||||
SLONG
|
||||
getsymbank(SLONG symid)
|
||||
{
|
||||
SLONG nBank;
|
||||
|
||||
switch (pCurrentSection->tSymbols[symid]->Type) {
|
||||
case SYM_IMPORT:
|
||||
return (sym_GetBank(pCurrentSection->tSymbols[symid]->pzName));
|
||||
case SYM_IMPORT:
|
||||
nBank = sym_GetBank(pCurrentSection->tSymbols[symid]->pzName);
|
||||
break;
|
||||
case SYM_EXPORT:
|
||||
case SYM_LOCAL:
|
||||
return (pCurrentSection->tSymbols[symid]->pSection->nBank);
|
||||
//return (pCurrentSection->nBank);
|
||||
default:
|
||||
nBank = pCurrentSection->tSymbols[symid]->pSection->nBank;
|
||||
break;
|
||||
default:
|
||||
errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
|
||||
}
|
||||
fprintf(stderr, "*INTERNAL* UNKNOWN SYMBOL TYPE\n");
|
||||
exit(1);
|
||||
|
||||
if (nBank >= BANK_WRAMX && nBank <= (BANK_WRAMX+6))
|
||||
return nBank - BANK_WRAMX + 1;
|
||||
if (nBank >= BANK_VRAM && nBank <= (BANK_VRAM+1))
|
||||
return nBank - BANK_VRAM;
|
||||
if (nBank >= BANK_SRAM && nBank <= (BANK_SRAM+3))
|
||||
return nBank - BANK_SRAM;
|
||||
|
||||
return nBank;
|
||||
}
|
||||
|
||||
SLONG
|
||||
@@ -159,20 +169,18 @@ calcrpn(struct sPatch * pPatch)
|
||||
t = rpnpop();
|
||||
rpnpush(t & 0xFF);
|
||||
if (t < 0 || (t > 0xFF && t < 0xFF00) || t > 0xFFFF) {
|
||||
fprintf(stderr,
|
||||
"%s(%ld) : Value must be in the HRAM area\n",
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be in the HRAM area",
|
||||
pPatch->pzFilename, pPatch->nLineNo);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case RPN_PCEZP:
|
||||
t = rpnpop();
|
||||
rpnpush(t & 0xFF);
|
||||
if (t < 0x2000 || t > 0x20FF) {
|
||||
fprintf(stderr,
|
||||
"%s(%ld) : Value must be in the ZP area\n",
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be in the ZP area",
|
||||
pPatch->pzFilename, pPatch->nLineNo);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case RPN_CONST:
|
||||
@@ -217,11 +225,10 @@ calcrpn(struct sPatch * pPatch)
|
||||
high |= (*rpn++) << 24;
|
||||
t = rpnpop();
|
||||
if (t < low || t > high) {
|
||||
fprintf(stderr,
|
||||
"%s(%ld) : Value must be in the range [%ld;%ld]\n",
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be in the range [%ld;%ld]",
|
||||
pPatch->pzFilename,
|
||||
pPatch->nLineNo, low, high);
|
||||
exit(1);
|
||||
}
|
||||
rpnpush(t);
|
||||
size -= 8;
|
||||
@@ -255,11 +262,10 @@ Patch(void)
|
||||
pSect->pData[pPatch->nOffset] =
|
||||
(UBYTE) t;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"%s(%ld) : Value must be 8-bit\n",
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be 8-bit",
|
||||
pPatch->pzFilename,
|
||||
pPatch->nLineNo);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case PATCH_WORD_L:
|
||||
@@ -280,11 +286,10 @@ Patch(void)
|
||||
1] = t & 0xFF;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"%s(%ld) : Value must be 16-bit\n",
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be 16-bit",
|
||||
pPatch->pzFilename,
|
||||
pPatch->nLineNo);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case PATCH_LONG_L:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dd February 26, 2015
|
||||
.Dt RGBLINK 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
@@ -7,7 +7,6 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm rgblink
|
||||
.Op Fl t
|
||||
.Op Fl l Ar library
|
||||
.Op Fl m Ar mapfile
|
||||
.Op Fl n Ar symfile
|
||||
.Op Fl o Ar outfile
|
||||
@@ -21,20 +20,14 @@ program links objects created by
|
||||
.Xr rgbasm 1
|
||||
into a single Game Boy ROM file.
|
||||
.Pp
|
||||
By default, HOME sections created by the assembler are placed in the 16KiB
|
||||
bank 0, and CODE/DATA sections are placed in any bank except bank 0.
|
||||
By default, ROM0 sections created by the assembler are placed in the 16KiB
|
||||
bank 0, and ROMX sections are placed in any bank except bank 0.
|
||||
If your ROM will only be 32KiB, you can use the
|
||||
.Fl t
|
||||
option to override this.
|
||||
.Pp
|
||||
The arguments are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl l Ar library
|
||||
Include a referenced library module created with
|
||||
.Xr rgblib 1 .
|
||||
Note that specified libraries will be included only if needed\(emthat is, if
|
||||
a SECTION from a library is referenced by an object file.
|
||||
Only the relevant SECTION will be included, rather than the entire module.
|
||||
.It Fl m Ar mapfile
|
||||
Write a mapfile to the given filename.
|
||||
.It Fl n Ar symfile
|
||||
@@ -50,14 +43,14 @@ The default is 0x00.
|
||||
Write a tiny
|
||||
.Pq 32KiB
|
||||
ROM file.
|
||||
This forces all DATA/CODE sections to be of type HOME, and increases the HOME
|
||||
This forces all ROMX sections to be of type ROM0, and increases the ROM0
|
||||
section size from 16KiB to 32KiB.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
All you need for a basic ROM is an object file, which can be made into a ROM
|
||||
image like so:
|
||||
.Pp
|
||||
.D1 $ rgblink \-o bar.gb foo.o
|
||||
.D1 $ rgblink -o bar.gb foo.o
|
||||
.Pp
|
||||
The resulting bar.gb will not have correct checksums
|
||||
.Pq unless you put them in the assembly source .
|
||||
@@ -65,13 +58,11 @@ You should use
|
||||
.Xr rgbfix 1
|
||||
to fix these so that the program will actually run in a Game Boy:
|
||||
.Pp
|
||||
.D1 $ rgbfix \-v bar.gb
|
||||
.D1 $ rgbfix -v bar.gb
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbds 7 ,
|
||||
.Xr rgbasm 1 ,
|
||||
.Xr rgbfix 1 ,
|
||||
.Xr rgblib 1 ,
|
||||
.Xr gbz80 7
|
||||
.Xr rgbds 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally written by Carsten S\(/orensen as part of the ASMotor package,
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/main.h"
|
||||
#include "link/patch.h"
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
#define HASHSIZE 73
|
||||
|
||||
@@ -53,8 +54,7 @@ sym_GetValue(char *tzName)
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown symbol '%s'\n", tzName);
|
||||
exit(1);
|
||||
errx(1, "Unknown symbol '%s'", tzName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,12 +72,11 @@ sym_GetBank(char *tzName)
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Unknown symbol '%s'\n", tzName);
|
||||
exit(1);
|
||||
errx(1, "Unknown symbol '%s'", tzName);
|
||||
}
|
||||
|
||||
void
|
||||
sym_CreateSymbol(char *tzName, SLONG nValue, SBYTE nBank)
|
||||
sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank)
|
||||
{
|
||||
if (strcmp(tzName, "@") == 0)
|
||||
return;
|
||||
@@ -93,10 +92,7 @@ sym_CreateSymbol(char *tzName, SLONG nValue, SBYTE nBank)
|
||||
if (nBank == -1)
|
||||
return;
|
||||
|
||||
fprintf(stderr,
|
||||
"Symbol '%s' defined more than once\n",
|
||||
tzName);
|
||||
exit(1);
|
||||
errx(1, "Symbol '%s' defined more than once", tzName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ To get a working ROM image from a single assembly source file:
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbasm 1 ,
|
||||
.Xr rgbfix 1 ,
|
||||
.Xr rgblib 1 ,
|
||||
.Xr rgblink 1 ,
|
||||
.Xr gbz80 7
|
||||
.Sh HISTORY
|
||||
|
||||
2
test/asm/bank-noexist.asm
Normal file
2
test/asm/bank-noexist.asm
Normal file
@@ -0,0 +1,2 @@
|
||||
SECTION "sec", ROM0
|
||||
db BANK(noexist)
|
||||
2
test/asm/bank-noexist.out
Normal file
2
test/asm/bank-noexist.out
Normal file
@@ -0,0 +1,2 @@
|
||||
ERROR: bank-noexist.asm(2) :
|
||||
'noexist' not defined
|
||||
2
test/asm/divzero-instr.asm
Normal file
2
test/asm/divzero-instr.asm
Normal file
@@ -0,0 +1,2 @@
|
||||
SECTION "sec", ROM0
|
||||
ld a, 1/0
|
||||
2
test/asm/divzero-instr.out
Normal file
2
test/asm/divzero-instr.out
Normal file
@@ -0,0 +1,2 @@
|
||||
ERROR: divzero-instr.asm(2) :
|
||||
division by zero
|
||||
1
test/asm/divzero-section-bank.asm
Normal file
1
test/asm/divzero-section-bank.asm
Normal file
@@ -0,0 +1 @@
|
||||
SECTION "sec", ROMX[$/0]
|
||||
2
test/asm/divzero-section-bank.out
Normal file
2
test/asm/divzero-section-bank.out
Normal file
@@ -0,0 +1,2 @@
|
||||
ERROR: divzero-section-bank.asm(1) :
|
||||
division by zero
|
||||
1
test/asm/macro-@.asm
Normal file
1
test/asm/macro-@.asm
Normal file
@@ -0,0 +1 @@
|
||||
foo @bar
|
||||
2
test/asm/macro-@.out
Normal file
2
test/asm/macro-@.out
Normal file
@@ -0,0 +1,2 @@
|
||||
ERROR: macro-@.asm(1) -> @(-1) :
|
||||
Macro '@' not defined
|
||||
BIN
test/asm/null-in-macro.asm
Normal file
BIN
test/asm/null-in-macro.asm
Normal file
Binary file not shown.
0
test/asm/null-in-macro.out
Normal file
0
test/asm/null-in-macro.out
Normal file
6
test/asm/test.sh
Normal file
6
test/asm/test.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
fname=$(mktemp)
|
||||
|
||||
for i in *.asm; do
|
||||
../../rgbasm $i >$fname 2>&1
|
||||
diff -u $fname ${i%.asm}.out
|
||||
done
|
||||
3
test/asm/undefined-dot.asm
Normal file
3
test/asm/undefined-dot.asm
Normal file
@@ -0,0 +1,3 @@
|
||||
SECTION "sec", ROM0
|
||||
foo:
|
||||
add sp, .
|
||||
2
test/asm/undefined-dot.out
Normal file
2
test/asm/undefined-dot.out
Normal file
@@ -0,0 +1,2 @@
|
||||
ERROR: undefined-dot.asm(3) :
|
||||
'.' not defined
|
||||
36
test/link/ram-bank-numbers.asm
Normal file
36
test/link/ram-bank-numbers.asm
Normal file
@@ -0,0 +1,36 @@
|
||||
; this should generate a rom consisting of the following bytes:
|
||||
; 01 02 03 04 05 06 07 00 01 02 03 00 01
|
||||
|
||||
section "x",rom0
|
||||
db bank(w1),bank(w2),bank(w3),bank(w4),bank(w5),bank(w6),bank(w7)
|
||||
db bank(s0),bank(s1),bank(s2),bank(s3)
|
||||
db bank(v0),bank(v1)
|
||||
|
||||
section "wa",wramx,bank[1]
|
||||
w1:
|
||||
section "wb",wramx,bank[2]
|
||||
w2:
|
||||
section "wc",wramx,bank[3]
|
||||
w3:
|
||||
section "wd",wramx,bank[4]
|
||||
w4:
|
||||
section "we",wramx,bank[5]
|
||||
w5:
|
||||
section "wf",wramx,bank[6]
|
||||
w6:
|
||||
section "wg",wramx,bank[7]
|
||||
w7:
|
||||
|
||||
section "sa",sram,bank[0]
|
||||
s0:
|
||||
section "sb",sram,bank[1]
|
||||
s1:
|
||||
section "sc",sram,bank[2]
|
||||
s2:
|
||||
section "sd",sram,bank[3]
|
||||
s3:
|
||||
|
||||
section "v00",vram,bank[0]
|
||||
v0:
|
||||
section "v01",vram,bank[1]
|
||||
v1:
|
||||
Reference in New Issue
Block a user