mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7b8d4de35c | ||
|
|
c7fe281c86 | ||
|
|
fa8f25a4de | ||
|
|
7c2cae7a32 | ||
|
|
92b81b1d5a | ||
|
|
42b5be24b4 | ||
|
|
14fea5f659 | ||
|
|
1e16a0ff85 | ||
|
|
7adf1dd502 | ||
|
|
0588e42520 | ||
|
|
2eb748278b | ||
|
|
9be7c4c849 | ||
|
|
c485ad94f2 | ||
|
|
998cfe1bdd | ||
|
|
5ee058f217 | ||
|
|
38372c59ed | ||
|
|
420ea638a7 | ||
|
|
951c9b66f4 | ||
|
|
0a66e14307 | ||
|
|
b40c567aee | ||
|
|
547abfefc1 | ||
|
|
06f0472f81 | ||
|
|
defd4f589e | ||
|
|
dc4a98048d | ||
|
|
efaa6d9ff7 | ||
|
|
ab19dab899 | ||
|
|
e86a70d2cb | ||
|
|
a91187d8dc | ||
|
|
0b5e074591 | ||
|
|
f8531ed410 | ||
|
|
0a8401741d | ||
|
|
a079a69b7c | ||
|
|
d86cb41972 | ||
|
|
95cd960b3b | ||
|
|
bed43d2530 | ||
|
|
c02b04f7d2 | ||
|
|
2339f0fbae | ||
|
|
6e0aca47d4 | ||
|
|
a8c603a7e8 | ||
|
|
97a31c8fc0 | ||
|
|
c3c31138dd | ||
|
|
fbb825af3b | ||
|
|
330a39596c | ||
|
|
e241137508 | ||
|
|
deb44eaeef | ||
|
|
338c176b37 | ||
|
|
1a15ee5363 | ||
|
|
2ea2e47231 | ||
|
|
31294d6d9d | ||
|
|
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 | ||
|
|
b2d523acde |
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
rgbasm
|
||||
rgblink
|
||||
rgbfix
|
||||
rgbgfx
|
||||
*.o
|
||||
*.exe
|
||||
*.html
|
||||
6
GNUmakefile
Normal file
6
GNUmakefile
Normal file
@@ -0,0 +1,6 @@
|
||||
# GNU Make 3.x doesn't support the "!=" shell syntax, so here's an alternative
|
||||
|
||||
PKG_CONFIG = pkg-config
|
||||
PNGFLAGS = $(shell ${PKG_CONFIG} --cflags libpng)
|
||||
|
||||
include Makefile
|
||||
9
LICENSE
9
LICENSE
@@ -18,8 +18,17 @@ 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.
|
||||
|
||||
rgbgfx was written by stag019, and is released under the ISC license.
|
||||
|
||||
The UTF-8 decoder in src/asm/charmap.c was written by Björn Höhrmann and is
|
||||
released under the MIT license. The remainder of charmap.c was written by
|
||||
stag019, and is released under the ISC 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.
|
||||
|
||||
41
Makefile
41
Makefile
@@ -1,7 +1,7 @@
|
||||
.POSIX:
|
||||
|
||||
WARNFLAGS = -Wall -Werror=implicit-int
|
||||
REALCFLAGS = ${CFLAGS} ${WARNFLAGS} -Iinclude -g \
|
||||
PKG_CONFIG = pkg-config
|
||||
WARNFLAGS = -Wall -Werror=implicit
|
||||
PNGFLAGS != ${PKG_CONFIG} --cflags libpng
|
||||
REALCFLAGS = ${CFLAGS} ${WARNFLAGS} ${PNGFLAGS} -Iinclude -g \
|
||||
-std=c99 -D_POSIX_C_SOURCE=200809L
|
||||
|
||||
# User-defined variables
|
||||
@@ -10,13 +10,7 @@ BINPREFIX = ${PREFIX}/bin
|
||||
MANPREFIX = ${PREFIX}/man
|
||||
Q = @
|
||||
|
||||
yacc_pre := \
|
||||
src/asm/yaccprt1.y\
|
||||
src/asm/yaccprt2.y\
|
||||
src/asm/yaccprt3.y\
|
||||
src/asm/yaccprt4.y
|
||||
|
||||
rgbasm_obj := \
|
||||
rgbasm_obj = \
|
||||
src/asm/asmy.o \
|
||||
src/asm/charmap.o \
|
||||
src/asm/fstack.o \
|
||||
@@ -29,10 +23,11 @@ rgbasm_obj := \
|
||||
src/asm/symbol.o \
|
||||
src/asm/locallex.o \
|
||||
src/extern/err.o \
|
||||
src/extern/reallocarray.o \
|
||||
src/extern/strlcpy.o \
|
||||
src/extern/strlcat.o
|
||||
|
||||
rgblink_obj := \
|
||||
rgblink_obj = \
|
||||
src/link/assign.o \
|
||||
src/link/library.o \
|
||||
src/link/main.o \
|
||||
@@ -43,17 +38,24 @@ rgblink_obj := \
|
||||
src/link/symbol.o \
|
||||
src/extern/err.o
|
||||
|
||||
rgbfix_obj := \
|
||||
rgbfix_obj = \
|
||||
src/fix/main.o \
|
||||
src/extern/err.o
|
||||
|
||||
all: rgbasm rgblink rgbfix
|
||||
rgbgfx_obj = \
|
||||
src/gfx/gb.o \
|
||||
src/gfx/main.o \
|
||||
src/gfx/makepng.o \
|
||||
src/extern/err.o
|
||||
|
||||
all: rgbasm rgblink rgbfix rgbgfx
|
||||
|
||||
clean:
|
||||
$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 rgbgfx rgbgfx.exe ${rgbgfx_obj} rgbgfx.html
|
||||
$Qrm -rf src/asm/asmy.c src/asm/asmy.h
|
||||
|
||||
install: all
|
||||
@@ -61,11 +63,13 @@ install: all
|
||||
$Qinstall -s -m 555 rgbasm ${BINPREFIX}/rgbasm
|
||||
$Qinstall -s -m 555 rgbfix ${BINPREFIX}/rgbfix
|
||||
$Qinstall -s -m 555 rgblink ${BINPREFIX}/rgblink
|
||||
$Qinstall -s -m 555 rgbgfx ${BINPREFIX}/rgbgfx
|
||||
$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
|
||||
$Qinstall -m 444 src/gfx/rgbgfx.1 ${MANPREFIX}/man1/rgbgfx.1
|
||||
|
||||
rgbasm: ${rgbasm_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgbasm_obj} -lm
|
||||
@@ -76,6 +80,9 @@ rgblink: ${rgblink_obj}
|
||||
rgbfix: ${rgbfix_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgbfix_obj}
|
||||
|
||||
rgbgfx: ${rgbgfx_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgbgfx_obj} `${PKG_CONFIG} --libs libpng`
|
||||
|
||||
.y.c:
|
||||
$Q${YACC} -d ${YFLAGS} -o $@ $<
|
||||
|
||||
@@ -91,12 +98,12 @@ src/asm/asmy.h: src/asm/asmy.c
|
||||
# install instructions instead.
|
||||
mingw:
|
||||
$Qenv PATH=/usr/local/mingw32/bin:/bin:/usr/bin:/usr/local/bin \
|
||||
make CC=gcc CFLAGS="-I/usr/local/mingw32/include \
|
||||
-D__progname=\\\"\\\" \
|
||||
make WARNFLAGS= CC=gcc CFLAGS="-I/usr/local/mingw32/include \
|
||||
${CFLAGS}"
|
||||
$Qmv rgbasm rgbasm.exe
|
||||
$Qmv rgblink rgblink.exe
|
||||
$Qmv rgbfix rgbfix.exe
|
||||
$Qmv rgbgfx rgbgfx.exe
|
||||
|
||||
# Below is a target for the project maintainer to easily create web manuals.
|
||||
# It relies on mandoc: http://mdocml.bsd.lv
|
||||
@@ -111,3 +118,5 @@ wwwman:
|
||||
rgbfix.html
|
||||
$Qmandoc ${MANDOC} src/link/rgblink.1 | sed s/OpenBSD/General/ > \
|
||||
rgblink.html
|
||||
$Qmandoc ${MANDOC} src/gfx/rgbgfx.1 | sed s/OpenBSD/General/ > \
|
||||
rgbgfx.html
|
||||
|
||||
58
README
58
README
@@ -1,58 +0,0 @@
|
||||
----------------
|
||||
RGBDS README
|
||||
----------------
|
||||
|
||||
RGBDS (Rednex Game Boy Development System) is a free assembler/linker package
|
||||
for the Game Boy and Game Boy Color. It consists of:
|
||||
|
||||
- rgbasm (assembler)
|
||||
- rgblink (linker)
|
||||
- rgbfix (checksum/header fixer)
|
||||
|
||||
rgbds-linux is a fork of the original RGBDS which aims to make the programs
|
||||
more like other UNIX tools.
|
||||
|
||||
|
||||
Installing RGBDS (UNIX)
|
||||
=========================
|
||||
|
||||
To build the programs on a UNIX or UNIX-like system, just run in your terminal:
|
||||
|
||||
make
|
||||
|
||||
Then to install the compiled programs and manual pages, run (with appropriate
|
||||
privileges):
|
||||
|
||||
make install
|
||||
|
||||
After installation, you can read the manuals with the man(1) command. E.g.,
|
||||
|
||||
man 1 rgbasm
|
||||
|
||||
|
||||
Note: the variables described below can affect installation behavior when given
|
||||
on the make command line. For example, to install rgbds in your home directory
|
||||
instead of systemwide, run the following:
|
||||
|
||||
mkdir -p $HOME/{bin,man/man1,man/man7}
|
||||
make install PREFIX=$HOME
|
||||
|
||||
|
||||
PREFIX: Location where RGBDS will be installed. Defaults to /usr/local.
|
||||
|
||||
BINPREFIX: Location where the RGBDS programs will be installed. Defaults
|
||||
to ${PREFIX}/bin.
|
||||
|
||||
MANPREFIX: Location where the RGBDS man pages will be installed. Defaults
|
||||
to ${PREFIX}/man.
|
||||
|
||||
Q: Whether to quiet the build or not. To make the build more verbose, clear
|
||||
this variable. Defaults to @.
|
||||
|
||||
|
||||
Installing RGBDS (Windows)
|
||||
============================
|
||||
|
||||
Windows builds are available here: http://anthony.bentley.name/rgbds/
|
||||
|
||||
Copy the .exe files to C:\Windows\ or similar.
|
||||
70
README.md
Normal file
70
README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# RGBDS
|
||||
|
||||
RGBDS (Rednex Game Boy Development System) is a free assembler/linker package
|
||||
for the Game Boy and Game Boy Color. It consists of:
|
||||
|
||||
- rgbasm (assembler)
|
||||
- rgblink (linker)
|
||||
- rgbfix (checksum/header fixer)
|
||||
- rgbgfx (PNG‐to‐Game Boy graphics converter)
|
||||
|
||||
rgbds-linux is a fork of the original RGBDS which aims to make the programs
|
||||
more like other UNIX tools.
|
||||
|
||||
|
||||
## Installing RGBDS (UNIX)
|
||||
|
||||
RGBDS requires libpng and pkg-config to be installed.
|
||||
|
||||
On Mac OS X, install them with [Homebrew](http://brew.sh/). On other Unixes,
|
||||
use the built-in package manager.
|
||||
|
||||
You can test if they're installed by running `pkg-config --cflags libpng`:
|
||||
if the output is a path, then you're good, and if it outputs an error then
|
||||
you need to install them via a package manager.
|
||||
|
||||
To build the programs on a UNIX or UNIX-like system, just run in your terminal:
|
||||
|
||||
```sh
|
||||
make
|
||||
```
|
||||
|
||||
Then to install the compiled programs and manual pages, run (with appropriate
|
||||
privileges):
|
||||
|
||||
```sh
|
||||
make install
|
||||
```
|
||||
|
||||
After installation, you can read the manuals with the man(1) command. E.g.,
|
||||
|
||||
```sh
|
||||
man 1 rgbasm
|
||||
```
|
||||
|
||||
Note: the variables described below can affect installation behavior when given
|
||||
on the make command line. For example, to install rgbds in your home directory
|
||||
instead of systemwide, run the following:
|
||||
|
||||
```sh
|
||||
mkdir -p $HOME/{bin,man/man1,man/man7}
|
||||
make install PREFIX=$HOME
|
||||
```
|
||||
|
||||
`PREFIX`: Location where RGBDS will be installed. Defaults to /usr/local.
|
||||
|
||||
`BINPREFIX`: Location where the RGBDS programs will be installed. Defaults
|
||||
to ${PREFIX}/bin.
|
||||
|
||||
`MANPREFIX`: Location where the RGBDS man pages will be installed. Defaults
|
||||
to ${PREFIX}/man.
|
||||
|
||||
`Q`: Whether to quiet the build or not. To make the build more verbose, clear
|
||||
this variable. Defaults to @.
|
||||
|
||||
|
||||
## Installing RGBDS (Windows)
|
||||
|
||||
Windows builds are available here: https://github.com/bentley/rgbds/releases
|
||||
|
||||
Copy the .exe files to C:\Windows\ or similar.
|
||||
129
doc/asm.htm
129
doc/asm.htm
@@ -1,129 +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>xAsm</title>
|
||||
<link rel="stylesheet" type="text/css" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>xAsm Documentation</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<h3>General stuff</h3>
|
||||
<ul>
|
||||
<li><a href="asm/history.htm">History</a>
|
||||
<li><a href="asm/usage.htm">Usage</a>
|
||||
<li><a href="asm/opt.htm">Changing options while assembling</a>
|
||||
<li><a href="asm/popo.htm">The option stack</a>
|
||||
<li><a href="asm/syntax.htm">Syntax and comments</a>
|
||||
<li><a href="asm/section.htm">Sections</a>
|
||||
</ul>
|
||||
|
||||
<h3>Symbols</h3>
|
||||
<ul>
|
||||
<li><a href="asm/symbols.htm">Symbols</a>
|
||||
<li><a href="asm/export.htm">Exporting and importing symbols</a>
|
||||
<li><a href="asm/purge.htm">Purging symbols</a>
|
||||
<li><a href="asm/presym.htm">Predeclared symbols</a>
|
||||
</ul>
|
||||
|
||||
<h3>The macrolanguage</h3>
|
||||
<ul>
|
||||
<li><a href="asm/print.htm">Printing out things during assembling</a>
|
||||
<li><a href="asm/rept.htm">Automatically repeating blocks of code</a>
|
||||
<li><a href="asm/fail.htm">Aborting the assembly process</a>
|
||||
<li><a href="asm/include.htm">Including other sourcefiles</a>
|
||||
<li><a href="asm/if.htm">Conditional assembling</a>
|
||||
<li><a href="asm/expr_int.htm">Integer and Boolean expressions</a>
|
||||
<li><a href="asm/expr_fix.htm">Fixed-point expressions and functions</a>
|
||||
<li><a href="asm/expr_str.htm">String expressions, functions and formatting</a>
|
||||
<li><a href="asm/miscfunc.htm">Other functions</a>
|
||||
</ul>
|
||||
|
||||
<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 RAM section</a>
|
||||
<li><a href="asm/incbin.htm">Including binary files</a>
|
||||
</ul>
|
||||
|
||||
<h3>Target specific information</h3>
|
||||
<ul>
|
||||
<li><a href="asm/trg_gb.htm">The Gameboy</a>
|
||||
</ul>
|
||||
|
||||
<h3>Alphabetical list of the macro-language instructions and functions</h3>
|
||||
<ul>
|
||||
<li><a href="asm/presym.htm">@</a>
|
||||
<li><a href="asm/presym.htm">__DATE__</a>
|
||||
<li><a href="asm/presym.htm">__LINE__</a>
|
||||
<li><a href="asm/presym.htm">__TIME__</a>
|
||||
<li><a href="asm/presym.htm">_NARG</a>
|
||||
<li><a href="asm/presym.htm">_PI</a>
|
||||
<li><a href="asm/presym.htm">_RS</a>
|
||||
<li><a href="asm/expr_fix.htm">ACOS</a>
|
||||
<li><a href="asm/expr_fix.htm">ASIN</a>
|
||||
<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/expr_fix.htm">COS</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>
|
||||
<li><a href="asm/ds.htm">DS</a>
|
||||
<li><a href="asm/db.htm">DW</a>
|
||||
<li><a href="asm/if.htm">ELSE</a>
|
||||
<li><a href="asm/if.htm">ENDC</a>
|
||||
<li><a href="asm/macro.htm">ENDM</a>
|
||||
<li><a href="asm/rept.htm">ENDR</a>
|
||||
<li><a href="asm/equ.htm">EQU</a>
|
||||
<li><a href="asm/equs.htm">EQUS</a>
|
||||
<li><a href="asm/export.htm">EXPORT</a>
|
||||
<li><a href="asm/fail.htm">FAIL</a>
|
||||
<li><a href="asm/export.htm">GLOBAL</a>
|
||||
<li><a href="asm/section.htm">HRAM</a>
|
||||
<li><a href="asm/if.htm">IF</a>
|
||||
<li><a href="asm/export.htm">IMPORT</a>
|
||||
<li><a href="asm/incbin.htm">INCBIN</a>
|
||||
<li><a href="asm/include.htm">INCLUDE</a>
|
||||
<li><a href="asm/macro.htm">MACRO</a>
|
||||
<li><a href="asm/expr_fix.htm">MUL</a>
|
||||
<li><a href="asm/opt.htm">OPT</a>
|
||||
<li><a href="asm/popo.htm">POPO</a>
|
||||
<li><a href="asm/pops.htm">POPS</a>
|
||||
<li><a href="asm/print.htm">PRINTF</a>
|
||||
<li><a href="asm/print.htm">PRINTT</a>
|
||||
<li><a href="asm/print.htm">PRINTV</a>
|
||||
<li><a href="asm/purge.htm">PURGE</a>
|
||||
<li><a href="asm/popo.htm">PUSHO</a>
|
||||
<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>
|
||||
<li><a href="asm/section.htm">SECTION</a>
|
||||
<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>
|
||||
<li><a href="asm/expr_str.htm">STRLEN</a>
|
||||
<li><a href="asm/expr_str.htm">STRLWR</a>
|
||||
<li><a href="asm/expr_str.htm">STRSUB</a>
|
||||
<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>
|
||||
</ul>
|
||||
|
||||
<p>Last updated 20 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,26 +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>xAsm DB, DW</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>DB, DW</h1>
|
||||
<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 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 RAM section</a>
|
||||
<li><a href="miscfunc.htm">Other functions</a>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<p>Last updated 02 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,20 +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>xAsm DS</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</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">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>
|
||||
<li><a href="db.htm">Defining constant data (DB/DW)</a>
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 02 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,21 +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>xAsm EQU</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>EQU</h1>
|
||||
<p>EQUates are constant symbols. They can for example be used for things such as bit-definitions of hardware-registers.</p>
|
||||
<pre>DONUT_ISGOOD EQU $01
|
||||
DONUT_ISBAD EQU $02</pre>
|
||||
<p>Note that a colon (:) following the label-name is not allowed. EQUates can be <a href="export.htm">exported and imported</a>. They don't change their value during the link process.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +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>xAsm EQUS</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>EQUS</h1>
|
||||
<p>EQUS is used to define string-symbols. Wherever the assembler meets a string symbol its name is replaced with its value. If you are familiar with C you can think of it as the same as #define.</p>
|
||||
<pre>COUNTREG EQUS "[hl+]"
|
||||
|
||||
ld a,COUNTREG</pre>
|
||||
<p>(Note that : following the label-name is not allowed.)</p>
|
||||
<p>This will be interpreted as:</p>
|
||||
<pre> ld a,[hl+]</pre>
|
||||
<p>String-symbols can also be used to define small one-line macros:</p>
|
||||
<pre>PUSHA EQUS "push af\npush bc\npush de\npush hl\n"</pre>
|
||||
<p>Note that a colon (:) following the label-name is not allowed. String equates can't be exported or imported.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_str.htm">String expressions, functions and formatting</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +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>xAsm EXPORT/XREF, IMPORT/XDEF, GLOBAL</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>EXPORT/XREF, IMPORT/XDEF, GLOBAL</h1>
|
||||
<p>Importing and exporting of symbols is a feature that is very useful when your project spans many source-files and for example you need to jump to a routine defined in another file.</p>
|
||||
<table>
|
||||
<caption>Import/export commands</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Command</th>
|
||||
<th scope="col">Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>IMPORT (or XREF) <i>label</i>[,<i>label</i>,...]</td>
|
||||
<td>This instructs the assembler to define label as if it were present
|
||||
in the current file but leave the address calculation to the linker.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>EXPORT (or XDEF) <i>label</i>[,<i>label</i>,...]</td>
|
||||
<td>The assembler will make <i>label</i> accessible to other files during the link process.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>GLOBAL <i>label</i>[,<i>label</i>,...]</td>
|
||||
<td>If <i>label</i> is defined during the assembly it will be exported, if not it will be imported. Handy (very!) for include-files.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body></html>
|
||||
@@ -1,76 +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>xAsm Fixed-point expression</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Fixed‐point Expressions</h1>
|
||||
<p>Fixed point constants are basically normal 32-bit constants where the upper 16 bits are used for the integer part and the lower 16 bits are used for the fraction (65536ths). This means that you can use them in normal integer expression and indeed some integer operators like plus and minus don't care whether the operands are integer or fixed-point. You can easily convert a fixed-point number to an integer by shifting it right 16 bits. It follows that you can convert an integer to a fixed-point number by shifting it left.</p>
|
||||
<p>Some things are different for fixed-point math though. Which is why you have the following functions to use:</p>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Operation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>DIV(x,y)</td>
|
||||
<td>x/y</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>MUL(x,y)</td>
|
||||
<td>x*y</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SIN(x)</td>
|
||||
<td>sin(x)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>COS(x)</td>
|
||||
<td>cos(x)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TAN(x)</td>
|
||||
<td>tan(x)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ASIN(x)</td>
|
||||
<td>sin<SUP>-1</SUP>(x)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ACOS(x)</td>
|
||||
<td>cos<SUP>-1</SUP>(x)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ATAN(x)</td>
|
||||
<td>tan<SUP>-1</SUP>(x)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ATAN2(x,y)</td>
|
||||
<td>(x,y) angle</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>These functions are extremely useful for automatic generation of various tables. A circle has 65536.0 degrees. Sine values are between [-1.0;1.0]</p>
|
||||
<pre>; --
|
||||
; -- Generate a 256 byte sine table with values between 0 and 128
|
||||
; --
|
||||
ANGLE SET 0.0
|
||||
REPT 256
|
||||
DB (MUL(64.0,SIN(ANGLE))+64.0)>>16
|
||||
ANGLE SET ANGLE+256.0
|
||||
ENDR</pre>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="symbols.htm">Symbols</a>
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
<li><a href="expr_str.htm">String expressions, functions and formatting</a>
|
||||
<li><a href="miscfunc.htm">Other functions</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,92 +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>xAsm Integer/Boolean expressions</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Integer and Boolean expressions</h1>
|
||||
<p>An expression can be composed of many things. Expressions are always evaluated using signed 32-bit math.</p>
|
||||
<p>The most basic expression is just a single number.</p>
|
||||
<h2>Numeric Formats</h2>
|
||||
<p>xAsm has a number of numeric formats.</p>
|
||||
<ul>
|
||||
<li>Hexadecimal: $0123456789ABCDEF. Case-insensitive
|
||||
<li>Decimal: 0123456789
|
||||
<li>Octal: &01234567
|
||||
<li>Binary: %01
|
||||
<li>Fixedpoint (16.16): 01234.56789
|
||||
<li>Character constant: "ABYZ"
|
||||
<li>Gameboy graphics: `0123
|
||||
</ul>
|
||||
<p>The last one, Gameboy graphics, is quite interesting and useful. The values are actually pixel values and it converts the “chunky” data to “planar” data as used in the Gameboy.</p>
|
||||
<pre>DW `01012323</pre>
|
||||
<p>Admittedly an expression with just a single number is quite boring. To spice things up a bit there’s a few operators you can use to perform calculations between numbers.</p>
|
||||
<h2>Operators</h2>
|
||||
<p>A great number of operators you can use in expressions are available (listed in order of precedence):</p>
|
||||
<table>
|
||||
<caption>Operators</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Operator</th>
|
||||
<th scope="col">Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>( )</td>
|
||||
<td>Precedence override</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FUNC()</td>
|
||||
<td>Functioncall</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>~ + -</td>
|
||||
<td>Unary not/plus/minus</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>* / %</td>
|
||||
<td>Multiply/divide/modulo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><< >></td>
|
||||
<td>Shift left/right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>& | ^</td>
|
||||
<td>Binary and/or/xor</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>+ -</td>
|
||||
<td>Add/subtract</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>!= == <= >= < ></td>
|
||||
<td>Boolean comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>&& ||</td>
|
||||
<td>Boolean and/or</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>!</td>
|
||||
<td>Unary Boolean not</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>The result of the boolean operators is zero if when FALSE and non-zero when TRUE. Thus it is legal to use an integer as the condition for <a href="if.htm">IF</a> blocks. You can use symbols instead of numbers in your expression if you wish.</p>
|
||||
|
||||
<p>An expression is said to be constant when it doesn't change its value during linking. This basically means that you can't use labels in those expressions. The instructions in the macro-language all require expressions that are constant.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="symbols.htm">Symbols</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="miscfunc.htm">Other functions</a>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,114 +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>xAsm String expressions</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>String Expressions</h1>
|
||||
<p>The most basic string expression is any number of characters contained in double quotes ("for instance"). As in C the escape character is <b>\</b> and there is a number of commands you can use within a string:</p>
|
||||
<table>
|
||||
<caption>Escape characters:</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Character sequence</th>
|
||||
<th scope="col">Meaning</th>
|
||||
<th scope="col">Notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>\\</td>
|
||||
<td>Backslash</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\"</td>
|
||||
<td>Double-quote</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\{</td>
|
||||
<td>Curly bracket left</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\}</td>
|
||||
<td>Curly bracket right</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\n</td>
|
||||
<td>Newline ($0A)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\t</td>
|
||||
<td>Tab ($09)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\1-\9</td>
|
||||
<td>Macroargument</td>
|
||||
<td>Only in macros</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>\@</td>
|
||||
<td>Labelname suffix</td>
|
||||
<td>Only in macros and repts</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>A funky feature is <b>{symbol}</b> withing a string. This will examine the type of the symbol and insert its value accordingly. If symbol is a string symbol the symbols value is simply copied. If it's a numeric symbol the value is converted to hexadecimal notation and inserted as a string.</p>
|
||||
<p><strong>HINT:</strong> The <b>{symbol}</b> construct can also be used outside strings. The symbols value is again inserted as a string. This is just a short way of doing "{symbol}".</p>
|
||||
<p>Whenever the macro-language expects a string you can actually use a string expression. This consists of one or more of these function. Yes, you can nest them. Note that some of these functions actually return an integer and can be used as part of an integer expression!</p>
|
||||
<table>
|
||||
<caption>String functions:</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Operation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>STRLEN(<i>stringexpr</i>)</td>
|
||||
<td>Returns the number of characters in <i>string</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>STRCAT(<i>stringexpr1,stringexpr2</i>)</td>
|
||||
<td>Appends <i>stringexpr2</i> to <i>stringexpr1</i>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>STRCMP(<i>stringexpr1,stringexpr2</i>)</td>
|
||||
<td>Returns negative if <i>stringexpr1</i> is alphabetically less than <i>stringexpr2</i><BR>Zero if they match<BR>Positive if greater than</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>STRIN(<i>haystack,needle</i>)</td>
|
||||
<td>Returns <i>needle</i>s position within <i>haystack</i> or zero if it's not present</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>STRSUB(<i>stringexpr,pos,count</i>)</td>
|
||||
<td>Returns a substring of <i>stringexpr</i> starting at <i>pos</i> (first character is position 1) and with <i>count</i> characters</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>STRUPR(<i>stringexpr</i>)</td>
|
||||
<td>Converts all characters in <i>string</i> to capitals and returns the new string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>STRLWR(<i>string</i>)</td>
|
||||
<td>Converts all characters in <i>string</i> to lower case and returns the new string</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="symbols.htm">Symbols</a>
|
||||
<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="miscfunc.htm">Other functions</a>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,20 +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>xAsm FAIL, WARN</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>FAIL, WARN</h1>
|
||||
<p>FAIL and WARN can be used to terminate the assembling process if you wish to do so. This is especially useful for macros that get an invalid argument. FAIL and WARN take a string as the only argument and they will print this string out as a normal error with a linenumber.</p>
|
||||
<p>FAIL stops assembling immediately while WARN continues after printing the errormessage.</p>
|
||||
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_str.htm">String expressions, functions and formatting</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,224 +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>xAsm History</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>xAsm History</h1>
|
||||
<table>
|
||||
<caption>The history of xAsm</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>1 Oct. 96</td>
|
||||
<td>First release</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.01</td>
|
||||
<td>1 Dec. 96</td>
|
||||
<td><ul>
|
||||
<li>Fixed bug in <a href="incbin.htm">INCBIN</a> (sometimes reported the section full)</li>
|
||||
<li>Added <a href="miscfunc.htm">DEF()</a> function
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.02</td>
|
||||
<td>12 Feb. 97</td>
|
||||
<td><ul>
|
||||
<li>Added <a href="expr_str.htm">STRLEN(), STRCAT(), STRIN(), STRCMP(), STRSUB(), STRUPR() and STRLWR()</a> functions</li>
|
||||
<li><a href="export.htm">IMPORT/EXPORT/GLOBAL</a> takes multiple arguments now</li>
|
||||
<li><a href="section.htm">HRAM</a> sectiontype added</li>
|
||||
<li>ORG like features added to <a href="section.htm">SECTION</a></li>
|
||||
<li><a href="trg_gb.htm">LDIO</a> mnemonic added</li>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.03</td>
|
||||
<td>23 Mar. 97</td>
|
||||
<td><ul>
|
||||
<li>The <a href="section.htm">HRAM section</a> was 128 bytes long instead of 127. potentially thrashing the interrupt enable register if you filled the HRAM.</li>
|
||||
<li>The <a href="miscfunc.htm">BANK() function</a>, when used on a symbol defined in the current sourcefile, returned the wrong bank ID. (reported by Harry P. Mulder)</li>
|
||||
<li>The <a href="miscfunc.htm">BANK() function</a> didn't check whether the argument was a properly defined symbol. (reported by Harry P. Mulder)</li>
|
||||
<li>Completely new lexical analyser module. This fixed several linenumber bugs and other macro/if/rept related bugs. Also fixed a bug which made it possible to have equated symbols with the same name as a reserved keyword (if you get a "parse error" with this release on some of your sources, this is probably what is going on)</li>
|
||||
<li><a href="fail.htm">FAIL and WARN</a> commands.</li>
|
||||
<li><a href="presym.htm">__LINE__, __FILE__, __TIME__, __DATE__</a> predefined symbols added.</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.04</td>
|
||||
<td>03 July 1997</td>
|
||||
<td><ul><li>First ASMotor release</li>
|
||||
<li><a href="presym.htm">__TIME__ and __DATE__</a> give todays date instead of when the assembler was compiled.</li>
|
||||
<li>Sometimes the first line of a file wouldn't assemble correctly. Reported by Jeff Frohwein.</li>
|
||||
<li>Unrolling multiline <a href="equs.htm">string symbols</a> left the linecounter in a sorry state. Jeff Frohwein again.</li>
|
||||
<li><a href="db.htm">DB and DW</a> can now (officially ;-) be used in BSS/HRAM/VRAM sections without any arguments to reserve a byte or a word respectively. Reported/suggested/inspired by Mr. Frohwein.</li>
|
||||
<li>The character # can now be used as part of a <a href="symbols.htm">symbol name</A>. Jeff....</li>
|
||||
<li>The <a href="rs.htm">RS</a> counter "_RS" is now defined from the very start of the assembly process instead of after the first RSSET or RSRESET.</li>
|
||||
<li>Bug fixed: You couldn't use \0-\9 and \@ in <a href="expr_str.htm">{} constructs</a></li>
|
||||
<li><a href="purge.htm">PURGE</a> pseudo-op added. Purges a symbol from the symboltable and memory. Use with extreme caution! Inspired by Harry P. Mulder</li>
|
||||
<li><a href="macro.htm">MACRO</a> parameter passing method changed drastically. Read (and re-read) the manual for details. Suggested by Harry P. Mulder.</li>
|
||||
</ul>
|
||||
</td>
|
||||
<tr>
|
||||
<td>1.05</td>
|
||||
<td>20 July 1997</td>
|
||||
<td><B>RGBDS fixes:</B><BR>
|
||||
RGBAsm supports the LDD and LDI syntax plus [HLD] and [HLI]. LDH is
|
||||
synonymous with LDIO.<BR>
|
||||
<B>General fixes:</B><BR>
|
||||
There was a bug in the macro parameter passing. Any whitespace after the
|
||||
last parameter would be appended to the last parameter. Reported by Jeff Frohwein.<BR>
|
||||
A section stack has been implemented. Look up <a href="pops.htm">POPS and PUSHS</A>. Jeff Frohweins doing again.<BR>
|
||||
<a href="opt.htm">OPT</A> command added for defining and changing some options while assembling.<BR>
|
||||
You can now define which characters are used for the <a href="expr_int.htm">Gameboy graphics
|
||||
integer (`)</A> using the <a href="usage.htm">commandline</A> or the new <a href="opt.htm">OPT</A> command. Cool idea by (surprise surprise) Jeff Frohwein.<BR>
|
||||
Also, an option stack has been added. Look up <a href="popo.htm">POPO and PUSHO</A> in the
|
||||
manual.<BR>
|
||||
Fixed yet another line number bug reported by Jeff Frohwein (when will this guy leave me alone? ;)<BR>
|
||||
</td>
|
||||
<tr>
|
||||
<td>1.06</td>
|
||||
<td>22 July 1997</td>
|
||||
<td><B>General fixes:</B><BR>
|
||||
The lamest typo bug of all time has been fixed. RGBAsm would output a word defined with DW as 4 bytes instead of 2. Jeff Frohwein reported this.<BR>
|
||||
The first line of an included file didn't assemble correctly.<BR>
|
||||
<a href="usage.htm">-b option</A> added for setting the characters used for binary constants.<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>21 September 1997</td>
|
||||
<td><B>General fixes:</B><BR>
|
||||
A crash occured if you tried to use a macro symbol in an expression.
|
||||
(Jeff Frohwein)<BR>
|
||||
You couldn't use STRCMP, STRLEN and STRIN in relocatable expressions. (Harry
|
||||
P. Mulder)<BR>
|
||||
Relocatable symbols are no longer allowed as arguments to the DEF function.<BR>
|
||||
Bug fixed in the assembler where it would sometimes write out too many bytes
|
||||
for HRAM section definitions.<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>02 July 1999</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
DQ directive added for defining 32-bit data constants. See operation of DW & DB.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>05 July 1999</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
Allow only a part of a binary file to be included instead of the whole thing.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>10 June 1999</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
Added output of file dependency information for each file included/assembled. Enabled with a command line option.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>?? ???? 1999</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
Added ORG directive to allow anonymous sections.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>?? ???? 1999</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
Added ability to output error information in either RGBDS or Microsoft Developer Studio format.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>?? ???? 1999</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
Added pseudo-instructions to handle NE (not equal), EQ (equal), and LT (less than) on JR/JP/CALL instructions
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>?? ???? 1999</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
Added STRTRIM, STRLTRIM, STRRTRIM directives to allow trimming of white space from strings in macro arguments.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>?? ???? 1999</td>
|
||||
<td>
|
||||
<B>Bug Fix:</B>
|
||||
<BR>
|
||||
When an "unknown symbol" error was reported during the link phase the undefined symbol was not given.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.08</td>
|
||||
<td>?? ???? 1999</td>
|
||||
<td>
|
||||
<B>Bug Fix:</B>
|
||||
<BR>
|
||||
Declaring a symbol as GLOBAL in a header file and then referencing it in code but never defining it would crash the linker.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.09</td>
|
||||
<td>08 February 2000</td>
|
||||
<td>
|
||||
<B>Feature:</B>
|
||||
<BR>
|
||||
Can now use a command line option to set the number format between a slightly tweaked Motorola/RGBDS format and Zilog.
|
||||
<BR>
|
||||
Hex numbers can now be represented as $FF or FFh.
|
||||
<BR>
|
||||
Octal as &77 or 77o.
|
||||
<BR>
|
||||
Binary as %10010110 or 10010110b.
|
||||
<BR>
|
||||
Gameboy graphics numbers as `1001 or 1001g.
|
||||
<BR>
|
||||
Decimal numbers remain unchanged.
|
||||
<BR>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</TABLE>
|
||||
|
||||
<BR><HR>
|
||||
<FONT SIZE="-1"><I><P ALIGN=RIGHT>Last updated 21 September 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</A></P></I></FONT>
|
||||
@@ -1,24 +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>xAsm IF, ELSE, ENDC</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>IF, ELSE, ENDC</h1>
|
||||
<p>These three commands is used to conditionally assemble parts of your file. It is a powerful feature commonly used in macros.</p>
|
||||
<pre>IF 2+2==4
|
||||
PRINTT "2+2==4\n"
|
||||
ELSE
|
||||
PRINTT "2+2!=4\n"
|
||||
ENDC</pre>
|
||||
<p>The ELSE block is optional. IF/ELSE/ENDC-blocks can be nested.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +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>xAsm INCBIN</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>INCBIN</h1>
|
||||
<p>You probably have some graphics you’d like to include. Use <dfn>INCBIN</dfn> to include a raw binary file as it is. If the file isn’t found in the current directory the <a href="usage.htm">include-path</a> list will be searched.</p>
|
||||
<pre>INCBIN "titlepic.bin"
|
||||
INCBIN "sprites\\hero.bin"</pre>
|
||||
<p>You can also include only part of a file with <b>INCBIN</b>. The example below includes 256 bytes from <i>data.bin</i> starting from position 78.</p>
|
||||
<pre>INCBIN "data.bin",78,256</pre>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_str.htm">String expressions, functions and formatting</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +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>xAsm INCLUDE</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>INCLUDE</h1>
|
||||
<p>Use INCLUDE to process another assembler-file and then return to the current file when done. If the file isn't found in the current directory the <a href="usage.htm">include-path</a> list will be searched. You may nest <b>INCLUDE</b> calls infinitely (or until you run out of memory whichever comes first).</p>
|
||||
<pre>INCLUDE "irq.inc"</pre>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_str.htm">String expressions, functions and formatting</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +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>xAsm Labels</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Labels</h1>
|
||||
<p>One of the assembler’s main tasks is to keep track of addresses for you so you dor’t have to remember obscure numbers but can make do with a meaningful name, a label.</p>
|
||||
<p>This can be done in a number of ways:</p>
|
||||
<pre>GlobalLabel
|
||||
AnotherGlobal:
|
||||
.locallabel
|
||||
.yet_a_local:
|
||||
ThisWillBeExported:: ;note the two colons</pre>
|
||||
<p>This is very similar to other assemblers. Local labels are only accessible within the scope they are defined. A scope starts after a global label and ends at the next global label. You may or may not have seen the <b>::</b> feature before. It declares a normal global label but does an <a href="export.htm">EXPORT</a> at the same time.</p>
|
||||
<p>Labels will normally change their value during the <a href="../link.htm">link process</a> and are thus <em>not</em> constant.</p>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,60 +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>xAsm MACRO/ENDM</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>MACRO, ENDM</h1>
|
||||
<p>One of the best features of an assembler is the ability to write macros for it. Macros also provide a method of passing arguments to them and they can then react to the input using IF-constructs.</p>
|
||||
<pre>MyMacro: MACRO
|
||||
ld a,80
|
||||
call MyFunc
|
||||
ENDM</pre>
|
||||
<p>The above example is a very simple macro. You execute the macro by typing its name.</p>
|
||||
<pre> add a,b
|
||||
ld sp,hl
|
||||
MyMacro ;This will be expanded
|
||||
sub a,87</pre>
|
||||
<p>When the assembler meets MyMacro it will insert the macrodefinition (the text enclosed in <b>MACRO/ENDM</b>).</p>
|
||||
<p id="labelsuffix">Suppose your macro contains a loop.</p>
|
||||
<pre>LoopyMacro: MACRO
|
||||
xor a,a
|
||||
.loop ld [hl+],a
|
||||
dec c
|
||||
jr nz,.loop
|
||||
ENDM</pre>
|
||||
<p>This is fine. That is, if you only use the macro once per <a href="labels.htm">scope</a>. To get around this problem there is a special label string equate called <b>\@</b> that you can append to your labels and it will then expand to a unique string.</p>
|
||||
<p><b>\@</b> also works in <a href="rept.htm">REPT-blocks</a> should you have any loops there.</p>
|
||||
<pre>LoopyMacro: MACRO
|
||||
xor a,a
|
||||
.loop\@ ld [hl+],a
|
||||
dec c
|
||||
jr nz,.loop\@
|
||||
ENDM</pre>
|
||||
<h2>Arguments</h2>
|
||||
<p>I’d like <i>LoopyMacro</i> a lot better if I didn’t have to pre-load the registers with values and <em>then</em> call it. What I’d like is the ability to pass it arguments and it then loaded the registers itself.</p>
|
||||
<p>And I can do that. In macros you can get the arguments by using the special macro string equates <b>\1</b> through <b>\9</b>, <b>\1</b> being the first argument specified on the calling of the macro.</p>
|
||||
<pre>LoopyMacro: MACRO
|
||||
ld hl,\1
|
||||
ld c,\2
|
||||
xor a,a
|
||||
.loop\@ ld [hl+],a
|
||||
dec c
|
||||
jr nz,.loop\@
|
||||
ENDM</pre>
|
||||
<p>Now I can call the macro specifying two arguments. The first being the address and the second being a bytecount. The macro will then reset all bytes in this range.</p>
|
||||
<pre> LoopyMacro MyVars,54</pre>
|
||||
<p>You can specify up to nine arguments when calling a macro. Arguments are passed as string equates. There’s no need to enclose them in quotes. Parameter passing has changed a bit since v1.03 in that an expression will not be evaluated first but passed directly. This means that it’s probably a very good idea to use brackets around \1–\9 if you perform further calculations on them. For instance if you pass 1+2 as the first argument and then do <code> PRINTV \1*2</code>
|
||||
you will get the value 5 on screen and not 6 as you might have expected.</p>
|
||||
<p>Note that a colon (:) following the macro-name is required. Macros can't be exported or imported. It's valid to call a macro from a macro (yes, even the same one).</p>
|
||||
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="shift.htm">SHIFT</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 02 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,38 +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>xAsm Other functions</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Other functions</h1>
|
||||
<p>There's a few other functions that do various useful things:</p>
|
||||
<table>
|
||||
<caption>Other functions</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Operation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>BANK(<i>label</i>)</td>
|
||||
<td>Gameboy ONLY: Returns the bank number <i>label</i> is in. The link will have to resolve this so it can't be used when the expression has to be constant</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DEF(<i>label</i>)</td>
|
||||
<td>Returns TRUE if <i>label</i> has been defined</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h1>See alse:</h1>
|
||||
<ul>
|
||||
<li><a href="section.htm">Sections</a>
|
||||
<li><a href="symbols.htm">Symbols</a>
|
||||
<li><a href="presym.htm">Predeclared symbols</a>
|
||||
<li><a href="if.htm">Conditional assembling</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +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>xAsm OPT</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>OPT</h1>
|
||||
<p>OPT can be used to change <I>some</I> of the options during assembling you source instead of defining them on the commandline.</p>
|
||||
<p>OPT takes a comma-seperated list of options as its argument:</p>
|
||||
|
||||
<pre> PUSHO
|
||||
OPT g.oOX ;Set the GB graphics constants to use these characters
|
||||
DW `..ooOOXX
|
||||
POPO
|
||||
DW `00112233</pre>
|
||||
<p>The options that OPT can modify are currently: <b>b, e and g</b></p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="usage.htm">Usage</a>
|
||||
<li><a href="popo.htm">The option stack</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 20 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +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>xAsm POPO, PUSHO</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>POPO, PUSHO</h1>
|
||||
<p>POPO and PUSHO provide the interface to the option stack. PUSHO will push the current set of options on the option stack. POPO can then later be used to restore them. Useful if you want to change some options in an include file and you don't want to destroy the options set by the program that included your file. The stacks number of entries is limited only by the amount of memory in your machine.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="opt.htm">Changing options while assembling</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 20 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +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>xAsm POPS, PUSHS</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>POPS, PUSHS</h1>
|
||||
<p>POPS and PUSHS provide the interface to the section stack. PUSHS will push the current section context on the section stack. POPS can then later be used to restore it. Useful for defining sections in included files when you don't want to destroy the section context for the program that included your file. The stacks number of entries is limited only by the amount of memory in your machine.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="section.htm">Sections</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 18 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,63 +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>xAsm Predeclared symbols</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Predeclared symbols</h1>
|
||||
<table>
|
||||
<caption>Symbols</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Contents</th>
|
||||
<th scope="col">Type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>@</td>
|
||||
<td>PC value</td>
|
||||
<td>EQU</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>_PI</td>
|
||||
<td>Fixed point ¶</td>
|
||||
<td>EQU</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>_RS</td>
|
||||
<td>_RS counter</td>
|
||||
<td>SET</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>_NARG</td>
|
||||
<td>Number of arguments passed to macro</td>
|
||||
<td>EQU</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>__LINE__</td>
|
||||
<td>The current linenumber</td>
|
||||
<td>EQU</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>__FILE__</td>
|
||||
<td>The current filename</td>
|
||||
<td>EQUS</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>__DATE__</td>
|
||||
<td>Todays date</td>
|
||||
<td>EQUS</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>__TIME__</td>
|
||||
<td>The current time</td>
|
||||
<td>EQUS</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,29 +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>xAsm PRINTT, PRINTV, PRINTF</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>PRINTT, PRINTV, PRINTF</h1>
|
||||
<p>These three instructions type text and values to stdout. Useful for debugging macros or wherever you may feel the need to tell yourself some important information.</p>
|
||||
<pre>PRINTT "I'm the greatest programmer in the whole wide world\n"
|
||||
PRINTV (2+3)/5
|
||||
PRINTF MUL(3.14,3987.0)</pre>
|
||||
<ul>
|
||||
<li><dfn>PRINTT</dfn> prints out a string</li>
|
||||
<li><dfn>PRINTV</dfn> prints out an integer value or, as in the example, the result of a calculation. Unsurprisingly you can also print out a <a href="symbols.htm">constant symbols</a> value</li>
|
||||
<li><dfn>PRINTF</dfn> prints out a fixed point value.</li>
|
||||
</ul>
|
||||
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="asm/expr_int.htm">Integer and Boolean expressions</a>
|
||||
<li><a href="asm/expr_fix.htm">Fixed-point expressions and functions</a>
|
||||
<li><a href="asm/expr_str.htm">String expressions, functions and formatting</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,18 +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>xAsm PURGE</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>PURGE</h1>
|
||||
<p>The PURGE command allows you to completely remove a symbol from the symbol table as if it had never existed. USE WITH EXTREME CAUTION!!! I can’t stress this enough but you <em>seriously</em> need to know what you are doing. DON’T purge symbol that you use in expressions the linker needs to calculate. In fact, it’s probably not even safe to purge anything other than string symbols and macros.</p>
|
||||
<pre>Kamikaze EQUS "I don't want to live anymore"
|
||||
AOLer EQUS "Me too"
|
||||
PURGE Kamikaze,AOLer</pre>
|
||||
<p>Note that string symbols that are part of a PURGE command WILL NOT BE EXPANDED as the ONLY exception to this rule.</p>
|
||||
<hr>
|
||||
<p>Last updated 02 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +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>xAsm REPT, ENDR</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>REPT, ENDR</h1>
|
||||
<p>Suppose you’re feeling lazy and you want to unroll a time consuming loop. <dfn>REPT</dfn> is here for that purpose. Everything between REPT and ENDR will be repeated a number of times just as if you done a copy/paste operation yourself</p>
|
||||
<pre>REPT 4
|
||||
add a,c
|
||||
ENDR</pre>
|
||||
<p>This will assemble <code>add a,c</code> four times.</p>
|
||||
<p>You can also use REPT to generate tables on the fly:</p>
|
||||
<pre>; --
|
||||
; -- Generate a 256 byte sine table with values between 0 and 128
|
||||
; --
|
||||
ANGLE SET 0.0
|
||||
REPT 256
|
||||
DB (MUL(64.0,SIN(ANGLE))+64.0)>>16
|
||||
ANGLE SET ANGLE+256.0
|
||||
ENDR</pre>
|
||||
<p>REPT is also very useful in recursive macros and as in macros you can also use the special label operator \@. REPT-blocks can be nested.<p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="macro.htm#labelsuffix">\@</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,76 +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>xAsm RSSET, RSRESET, RB, RW</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>RSSET, RERESET, RB, RW</h1>
|
||||
<p>The <dfn>RS</dfn> group of commands is a handy way of defining structures:</p>
|
||||
<pre> RSRESET
|
||||
str_pStuff RW 1
|
||||
str_tData RB 256
|
||||
str_bCount RB 1
|
||||
str_SIZEOF RB 0</pre>
|
||||
<p>The example defines four <a href="equ.htm">equated</a> symbols:</p>
|
||||
<table>
|
||||
<caption>Defined symbols</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>str_pStuff</td>
|
||||
<td>0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>str_tData</td>
|
||||
<td>2</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>str_bCount</td>
|
||||
<td>258</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>str_SIZEOF</td>
|
||||
<td>259</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>There are four commands in the RS group of commands:</p>
|
||||
<table>
|
||||
<caption>RS related commands</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Command</th>
|
||||
<th scope="col">Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>RSRESET</td>
|
||||
<td>Resets the <a href="presym.htm">_RS</a> counter to zero</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RSSET <i>constexpr</i></td>
|
||||
<td>Sets the <a href="presym.htm">_RS</a> counter to <i>constexpr</i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RB <i>constexpr</i></td>
|
||||
<td>Sets the preceding symbol to <a href="presym.htm">_RS</a> and adds <i>constexpr</i> to _RS</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>RW <i>constexpr</i></td>
|
||||
<td>Sets the preceding symbol to <a href="presym.htm">_RS</a> and adds <i>constexpr*2</i> to _RS</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Note that a colon (:) following the symbol-name is not allowed. RS symbols can be exported and imported. They don't change their value during the link process.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,70 +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>xAsm SECTION</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<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",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>
|
||||
|
||||
<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",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",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>
|
||||
<li><a href="../link.htm">xLink</a> documentation
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
<li><a href="expr_str.htm">String expressions, functions and formatting</a>
|
||||
<li><a href="pops.htm">POPS and PUSHS:</a> The section stack.
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 18 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,22 +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>xAsm SET</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>SET</h1>
|
||||
<p>SETs are like <a href="equ.htm">EQUates</a> also constant symbols in the sense that their values are defined during the assembly process. These symbols are normally used in macros.</p>
|
||||
<pre>KINKYCOUNT SET 2
|
||||
KINKYCOUNT SET DONUT_ISGOOD+KINKYCOUNT</pre>
|
||||
<p>Note that a colon (:) following the label-name is not allowed. SETs can be exported and imported but the result is undefined and might change in a later release. Alternatively you can use = as a synonym for SET.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="expr_int.htm">Integer and Boolean expressions</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,19 +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>xAsm SHIFT</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>SHIFT</h1>
|
||||
<p><dfn>SHIFT</dfn> is a special command only available in <a href="macro.htm">macros</a>. Very useful in <a href="rept.htm">REPT-blocks</a>. It will "shift" the arguments by one "to the left". <b>\1</b> will get <b>\2</b>'s value, <b>\2</b> will get <b>\3</b>'s value and so forth.</p>
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="macro.htm">Macros</a>
|
||||
<li><a href="rept.htm">Automatically repeating blocks of code</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,31 +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>xAsm Symbols</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>xAsm Symbols</h1>
|
||||
<p>xAsm supports several types of symbols:</p>
|
||||
<ul>
|
||||
<li><a href="labels.htm">Label</a>. Used to assign a memory location with a name
|
||||
<li><a href="equ.htm">EQUate</a>. Give a constant a name.
|
||||
<li><a href="set.htm">SET</a>. Same as EQUate but with a subtle difference. You can change the value of a SET during assembling.
|
||||
<li><a href="rs.htm">Structures (the RS group)</a>. Define a structure easily.
|
||||
<li><a href="equs.htm">String equate (EQUS)</a>. Give an often used string a name. Can also be used as a mini-macro. Much like #define in C.
|
||||
<li><a href="macro.htm">MACROs</a>. A block of code or pseudo instructions that you invoke like any other mnemonic. You can give them arguments too! Life is good.
|
||||
</ul>
|
||||
|
||||
<p><strong>A symbol cannot have the same name as a reserved keyword.</strong></p>
|
||||
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="presym.htm">Predeclared symbols</a>
|
||||
<li><a href="export.htm">Importing and exporting symbols</a>
|
||||
<li><a href="purge.htm">Purging symbols</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 02 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +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>xAsm Syntax</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>xAsm Syntax</h1>
|
||||
<p>The syntax line‐based, just as in any other assembler. Meaning that you do one instruction or pseudo‐op per line:</p>
|
||||
<pre>[label] [instruction] [;comment]</pre>
|
||||
<p>Example:</p>
|
||||
<pre>John: ld a,87 ;Weee</pre>
|
||||
<p>A comment can also be an asterisk (*) followed by the comment if the asterisk is the first character on the line:</p>
|
||||
<pre>********************************
|
||||
* These are full line comments *
|
||||
********************************</pre>
|
||||
<p>All pseudo‐ops, mnemonics and registers (reserved keywords) are <em>case‐insensitive</em> and all labels are <em>case‐sensitive</em>.</p>
|
||||
<hr>
|
||||
<p>Last updated 21 June 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,102 +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>xAsm Gameboy</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>Gameboy</h1>
|
||||
<p>The full GB-Z80 instruction-set is implemented with a few modifications to the original Zilog syntax. This is due to a Bison problem but in my opinion the syntax is better than the original one.</p>
|
||||
<h2>Instructions</h2>
|
||||
<ul>
|
||||
<li>ADC
|
||||
<li>ADD
|
||||
<li>AND
|
||||
<li>BIT
|
||||
<li>CALL
|
||||
<li>CCF
|
||||
<li>CP
|
||||
<li>CPL
|
||||
<li>DAA
|
||||
<li>DEC
|
||||
<li>DI
|
||||
<li>EI
|
||||
<li>EX
|
||||
<li>HALT
|
||||
<li>INC
|
||||
<li>JP
|
||||
<li>JR
|
||||
<li>LD
|
||||
<li>LDD
|
||||
<li>LDI
|
||||
<li>LDH/LDIO (see note below)
|
||||
<li>NOP
|
||||
<li>OR
|
||||
<li>POP
|
||||
<li>PUSH
|
||||
<li>RES
|
||||
<li>RET
|
||||
<li>RETI
|
||||
<li>RL
|
||||
<li>RLA
|
||||
<li>RLC
|
||||
<li>RLCA
|
||||
<li>RR
|
||||
<li>RRA
|
||||
<li>RRC
|
||||
<li>RRCA
|
||||
<li>RST
|
||||
<li>SBC
|
||||
<li>SCF
|
||||
<li>SET
|
||||
<li>SLA
|
||||
<li>SRA
|
||||
<li>SRL
|
||||
<li>STOP
|
||||
<li>SUB
|
||||
<li>SWAP
|
||||
<li>XOR
|
||||
</ul>
|
||||
<p>Note that you can use both
|
||||
<pre> OR A,B
|
||||
OR B</pre>
|
||||
<h2>Addressingmodes</h2>
|
||||
<p>Indirect addressing has been changed to [ ] instead of ( ):</p>
|
||||
<ul>
|
||||
<li> A
|
||||
<li> B
|
||||
<li> C
|
||||
<li> D
|
||||
<li> E
|
||||
<li> H
|
||||
<li> L
|
||||
<li> AF
|
||||
<li> BC
|
||||
<li> DE
|
||||
<li> HL
|
||||
<li> SP
|
||||
<li> [BC]
|
||||
<li> [DE]
|
||||
<li> [HL]
|
||||
<li> [HL-]/[HLI]
|
||||
<li> [HL+]/[HLD]
|
||||
<li> [SP]
|
||||
<li> n8 (8 bit expression)
|
||||
<li> n16 (16 bit expression)
|
||||
<li> n3 (3 bit CONSTANT expression)
|
||||
<li> [n16]/[$FF00+n8]
|
||||
<li> [$FF00+C]/[C]
|
||||
</ul>
|
||||
<p>The assembler will intelligently decide between <b>[n16]</b> and <b>[$FF00+n8]</b> in the LD instruction. Note however that if you use any <a href="symbols.htm">constant symbols</a> in the expression they had better be defined before the instruction or your symbol-table may become mangled. Also worth noting is that it will only ever select the short $FF00 mode when you use constant symbols. NOT if you use symbols defined in a <a href="section.htm">HRAM section</a>. As this defies the whole point of implementing the HRAM sectiontype I've added the LDIO mnemonic. It works like the LD instruction but it will ALWAYS generate the $FF00+ form and it will also automatically logically AND the expression with $FF if it is relocatable. Which is what you want. Trust me ;)</p>
|
||||
<h2>Conditioncodes</h2>
|
||||
<ul>
|
||||
<li> C
|
||||
<li> NC
|
||||
<li> Z
|
||||
<li> NZ
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 20 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,30 +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>xAsm Usage</title>
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>xAsm Usage</h1>
|
||||
<pre>C:\>xAsm [options] asmfile</pre>
|
||||
<p>Options are preceded by a hyphen (-) and go as follows:</p>
|
||||
<pre> o<b>objectfile</b> : Write an <a href="../rgb0.htm">object-file</a> for <a href="../link.htm">xLink</a>
|
||||
i<b>path</b> : Add an extra include-path
|
||||
h : Short help text
|
||||
e<b>(l|b)</b> : Change endianness (CAUTION!)
|
||||
g<b>ASCI</b> : Change the four characters used for Gameboy graphics
|
||||
constants (default is <b>0123</b>)
|
||||
b<b>AS</b> : Change the two characters used for binary constants
|
||||
(default is <b>01</b>)
|
||||
z<b>HX</b> : Set the byte value (hex format) used for uninitialised data (default is ? for random)
|
||||
</pre>
|
||||
|
||||
<h1>See also:</h1>
|
||||
<ul>
|
||||
<li><a href="opt.htm">Changing options while assembling</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<p>Last updated 08 October 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
116
doc/geninfo.htm
116
doc/geninfo.htm
@@ -1,116 +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>General Information</title>
|
||||
<link rel="stylesheet" type="text/css" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1><abbr title="Rednex Game Boy Development System">RGBDS</abbr>—ASMotor General Information</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#license">License</a>
|
||||
<li><a href="#Author">The Author</a>
|
||||
<li><a href="#Introduction">Introduction</a>
|
||||
<li><a href="#Installation">Installation</a>
|
||||
<li><a href="#Documentation">The Documentation</a>
|
||||
<li><a href="#History">History</a>
|
||||
</ul>
|
||||
<h2 id="license">License</h2>
|
||||
<p>The <dfn>ASMotor</dfn> package (<a href="asm.htm">xAsm</a>, <a href="link.htm">xLink</a>, <a href="fix.htm">RGBFix</a>, examples and <a href="#Documentation">documentation</a>) is freeware and distributed as is. The author retains his copyright and right to modify the specifications and operation of the software without notice.
|
||||
<p>In other words this means I encourage you to…
|
||||
<ul>
|
||||
<li>use it for whatever purpose even professional work without me charging you a penny
|
||||
<li>copy it to another person (wholly or in part, though I’m sure he’d appreciate the whole package) in
|
||||
whatever form you find suitable
|
||||
<li>mass-distribute the ASMotor package if it is complete (<a href="asm.htm">xAsm</a>, <a href="link.htm">xLink</a>, <a href="fix.htm">RGBFix</a> and documentation).
|
||||
<li>contact me if you have any problems
|
||||
</ul>
|
||||
<p>This also means you can’t…
|
||||
<ul>
|
||||
<li>blame me for loss of profit, data, sleep, food or other nasty things through the use or distribution of ASMotor. If
|
||||
you choose to use ASMotor you do so at your own risk.
|
||||
<li>expect me to be able to help you should you have a problem related or not to ASMotor.
|
||||
</ul>
|
||||
<h2 id="Author">The Author</h2>
|
||||
<p>Any questions? Write me!
|
||||
<h3>Address</h3>
|
||||
<p>
|
||||
Carsten Sorensen<br>
|
||||
1 Spring Court<br>
|
||||
Guildford<br>
|
||||
Surrey GU2 6QW<br>
|
||||
United Kingdom<br>
|
||||
<h3 id="Email">e-mail:</h3>
|
||||
<ul>
|
||||
<li><a href="mailto:surfsmurf@matilde.demon.co.uk">surfsmurf@matilde.demon.co.uk</a> (private)
|
||||
<li><a href="mailto:csorensen@ea.com">csorensen@ea.com</a> (work)
|
||||
</ul>
|
||||
<p>Get the latest version from my web page at <a href="http://www.matilde.demon.co.uk">http://www.matilde.demon.co.uk</a>
|
||||
<h2 id="History">History</h2>
|
||||
<table>
|
||||
<caption>The history of ASMotor</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Version</th>
|
||||
<th>Dated</th>
|
||||
<th>Release notes</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>1.0</td>
|
||||
<td>03 July 1997</td>
|
||||
<td>First release</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.01</td>
|
||||
<td>20 July 1997</td>
|
||||
<td><p>RGBDS fixes:</p>
|
||||
<ul>
|
||||
<li>RGBFix can now also truncate the ROM-images to a valid size.
|
||||
<li>RGBAsm supports the LDD and LDI syntax plus [HLD] and [HLI]. LDH is synonymous with LDIO.
|
||||
<li>Example filenames have been changed to adhere to Jeff Frohweins proposed standard.
|
||||
</ul>
|
||||
<p>General fixes:</p>
|
||||
<ul>
|
||||
<li>RGBLink knows about big and little endian. Plus it can do range checking on intermediate results in an expression. This is necessary to support
|
||||
different types of CPUs.
|
||||
<li>RGBLink <em>didn’t</em> know about the special PC symbol “@” so if you used it more than once per sourcefile in an expression the linker had to resolve, things would go horribly wrong.
|
||||
<li>There was a bug in the macro parameter passing. Any whitespace after the last parameter would be appended to the last parameter. Reported by Jeff Frohwein.
|
||||
<li>A section stack has been implemented. Look up POPS and PUSHS in the
|
||||
manual. Jeff Frohwein’s doing again.
|
||||
<li>OPT command added for defining and changing some options while assembling.
|
||||
<li>You can now define which characters are used for the Gameboy graphics integer (`) using the commandline or the new OPT command. Cool idea by (surprise surprise) Jeff Frohwein.
|
||||
<li>Also, an option stack has been added. Look up POPO and PUSHO in the manual.
|
||||
<li>Fixed yet another line number bug reported by Jeff Frohwein (when will this guy leave me alone? ;)
|
||||
</ul>
|
||||
</td>
|
||||
<tr>
|
||||
<td>1.02</td>
|
||||
<td>22 July 1997</td>
|
||||
<td><p>General fixes:</p>
|
||||
<ul>
|
||||
<li>The lamest typo bug of all time has been fixed. RGBAsm would output a word defined with DW as 4 bytes instead of 2. Jeff Frohwein reported this.
|
||||
<li>The first line of an included file didn’t assemble correctly.
|
||||
<li>-b option added for setting the characters used for binary constants.
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.10</td>
|
||||
<td>21 Sep 1997</td>
|
||||
<td><p>General fixes:</p>
|
||||
<ul>
|
||||
<li>The assembler would crash if you tried to use a macro symbol in an expression. (Jeff Frohwein)
|
||||
<li>You couldn’t use STRCMP, STRLEN and STRIN in relocatable expressions. (Harry P. Mulder)
|
||||
<li>Relocatable symbols are no longer allowed as arguments to the DEF function.
|
||||
<li>Finally! A librarian and smart linking has been added.
|
||||
<li>Bug fixed in the assembler where it would sometimes write out too many bytes for HRAM section definitions.
|
||||
<li>-z options (set fill value used for uninitialised data) added to the
|
||||
assembler and linker.
|
||||
<li>The assembler will now read in any type of ASCII file on any type of OS.
|
||||
</ul>
|
||||
</table>
|
||||
<p>Last updated 08 October 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,20 +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>RGBDS—ASMotor Documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1><abbr title="Rednex Game Boy Development System">RGBDS</abbr>—ASMotor v1.10 Documentation</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<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="fix.htm">RGBFix Documentation</a>
|
||||
<li><a href="rgb0.htm">The RGB0-2 ObjectFileFormat</a>
|
||||
</ul>
|
||||
<p>Last updated 21 September 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
118
doc/link.htm
118
doc/link.htm
@@ -1,118 +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>xLink</title>
|
||||
<link rel="stylesheet" type="text/css" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>xLink Documentation</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#history"> History</a>
|
||||
<li><a href="#usage"> Usage</a>
|
||||
<li><a href="#linkfile"> The Linkfile</a>
|
||||
<li><a href="#operationtg"> Operation for Gameboy</a>
|
||||
<li><a href="#smallmode"> Operation for Gameboy small mode</a>
|
||||
<li><a href="#psion2"> Operation for Psion2 relocatable modules</a>
|
||||
</ul>
|
||||
<hr>
|
||||
<h2 id="history">History</h2>
|
||||
<table>
|
||||
<caption>The history of xLink</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>1 Oct. 96</td>
|
||||
<td>First release (RGBDS)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.01</td>
|
||||
<td>3 Dec. 96</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>BANK() didn't work. Fixed.</li>
|
||||
<li>Sections were quite often output in the wrong order. Fixed.</li>
|
||||
</ul>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.02</td>
|
||||
<td>12 Feb. 97</td>
|
||||
<td><a href="#usage">-s switch and mapfile option</A> added</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.03</td>
|
||||
<td>23 Mar. 97</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li><a href="#usage">Mapfile</A> now shows BSS, VRAM and HRAM areas</li>
|
||||
<li>There was a bug regarding <a href="#operation">fixed HOME sections.</a>
|
||||
</ul></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.04</td>
|
||||
<td>03 July 1997</td>
|
||||
<td>First ASMotor release. Supports big-endian CPUs as well. <a href="#usage">Usage</a> changed to allow for different output fileformats</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>1.05</td>
|
||||
<td>20 July 1997</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li>We can now do range checking on intermediate results in an expression. This is necessary to support different types of CPUs.</li>
|
||||
<li>RGBLink DIDN’T know about the special PC symbol "@" so if you used it more than once per sourcefile in an expression the linker had to resolve, things would go horribly wrong.</li>
|
||||
</ul>
|
||||
</td>
|
||||
<tr>
|
||||
<td>1.06</td>
|
||||
<td>21 September 1997</td>
|
||||
<td><ul><li>Smart linking and library support added
|
||||
<li>Program renamed to xLink
|
||||
</ul>
|
||||
</td>
|
||||
</table>
|
||||
<h2 id="usage">Usage</h2>
|
||||
<pre> xlink [options] linkfile</pre>
|
||||
<p>Options are preceded by a hyphen (-) and go as follows:
|
||||
<pre> h : Short help text
|
||||
m<b>mapfile</b> : Write a mapfile
|
||||
t : Output target:
|
||||
tg : Gameboy <a href="#operationtg">ROM image</a> (default)
|
||||
ts : Gameboy <a href="#smallmode">Small mode (32kB)</a> ROM image
|
||||
tp : <a href="#psion2">Psion2</a> relocatable module
|
||||
z<b>HX</b> : Set the byte value (hex format) used for uninitialised data (default is ? for random)
|
||||
</pre>
|
||||
<h2 id="linkfile">The Linkfile</h2>
|
||||
<p>A linkfile is used to tell <B>xLink</B> which objects to include and what the outputname should be. It is in plain ASCII-format.
|
||||
<pre> # Linkfile for foobar.gb
|
||||
|
||||
[Objects]
|
||||
foo.obj
|
||||
bar.obj
|
||||
|
||||
[Libraries]
|
||||
mylib.lib
|
||||
|
||||
[Output]
|
||||
foobar.gb</pre>
|
||||
<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>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>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.
|
||||
|
||||
<hr>
|
||||
<p>Last updated 08 October 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
210
doc/rgb0.htm
210
doc/rgb0.htm
@@ -1,210 +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>RGB? Fileformat</title>
|
||||
<link rel="stylesheet" type="text/css" href="./style.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>The RGB ObjectFileFormats</h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul>
|
||||
<li><a href="#background">Background</A>
|
||||
<li><a href="#filestructure">FileStructure</A>
|
||||
<li><a href="#rpn">Rpn Data</A>
|
||||
</ul>
|
||||
<h2 id="background">Background</h2>
|
||||
<p>I developed the RGB0 fileformat mainly because I needed a suitable dataformat to hold the output from <a href="asm.htm">xAsm</a> that was powerful to accomodate all the features I needed and also would make it easy for me to add new ones. The reason for documenting it is so people can write converters between it and other formats. Perhaps even develop other compilers for it?</p>
|
||||
<p>The RGB1 fileformat saw the light of day with the V1.02 of the old RGBDS release because of the addition of fixed sections.</p>
|
||||
<p>The RGB2 fileformat emerged because I needed to add support for big endian CPUs.</p>
|
||||
<h2 id="filestructure">FileStructure</h2>
|
||||
<ul>
|
||||
<li><dfn>LONG</dfn> is a 32‐bit integer stored in little‐endian format (Intel)
|
||||
<li><dfn>BYTE</dfn> is an 8‐bit integer
|
||||
<li><dfn>STRING</dfn> is a 0‐terminated string of <b>BYTE</b>
|
||||
</ul>
|
||||
<p>Down to business...</p>
|
||||
<pre>
|
||||
; There's a header...
|
||||
|
||||
BYTE ID[4] ;"RGB0", "RGB1", "RGB2"
|
||||
LONG NumberOfSymbols ;The number of symbols used in this file
|
||||
LONG NumberOfSections ;The number of sections used in this file
|
||||
|
||||
; Now for some symbols
|
||||
|
||||
REPT NumberOfSymbols ;<b>NumberOfSymbols</b> symboldefs follow
|
||||
STRING Name ;The name of this symbol
|
||||
BYTE Type ;0 = LOCAL symbol only used in this file
|
||||
;1 = IMPORT this symbol from elsewhere
|
||||
;2 = EXPORT this symbol to other objects
|
||||
IF Type != 1
|
||||
LONG SectionID ;The section number in which this symbol
|
||||
;is defined. If -1 this symbol is an EQUate
|
||||
LONG Value ;The symbols value. If SectionID!=-1 it's the
|
||||
;offset into that section
|
||||
ENDC
|
||||
ENDR
|
||||
|
||||
; And I'll be... Sections!
|
||||
|
||||
REPT NumberOfSections
|
||||
LONG Size ;Size in bytes of this section
|
||||
BYTE Type ;0 = WRAM0
|
||||
;1 = VRAM
|
||||
;2 = ROMX
|
||||
;3 = ROM0
|
||||
;4 = HRAM
|
||||
LONG Org ;Only present in RGB1. Address to fix this
|
||||
;section at. -1 if the linker should
|
||||
;decide (normal operation)
|
||||
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 ROMX sections.
|
||||
IF Type==ROMX || Type==ROM0
|
||||
BYTE Data[Size]
|
||||
LONG NumberOfPatches
|
||||
|
||||
; These types of sections may have patches
|
||||
|
||||
REPT NumberOfPatches
|
||||
STRING SourceFile ;The name of the sourcefile (for
|
||||
;printing an errormessage)
|
||||
LONG Line ;The line of the sourcefile
|
||||
LONG Offset ;Offset into the section where patch
|
||||
;should be applied
|
||||
BYTE Type ;0 = BYTE patch
|
||||
;1 = little endian WORD patch
|
||||
;2 = little endianLONG patch
|
||||
;3 = big endian WORD patch (RGB2 and later)
|
||||
;4 = big endianLONG patch (RGB2 and later)
|
||||
LONG RPNSize
|
||||
BYTE RPN[RPNSize] ;RPN definition below
|
||||
ENDR
|
||||
ENDC
|
||||
ENDR</pre>
|
||||
<h2 id="rpn">Rpn Data</h2>
|
||||
<p>Expressions in the objectfile are stored as <abbr title="Reverse Polish Notation">RPN</abbr>. This is an expression of the form “2 5 +”. This will first push the value “2” to the stack. Then “5”. The “+” operator pops two arguments from the stack, adds them, and then pushes the result on the stack, effectively replacing the two top arguments with their sum. In the RGB format RPN expressions are stored as <b>BYTE</b>s with some bytes being special prefixes for integers and symbols.</p>
|
||||
<table>
|
||||
<caption>RPN Expressions</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Byte value</th>
|
||||
<th scope="col">Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr>
|
||||
<td>$00</td>
|
||||
<td>+ operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$01</td>
|
||||
<td>- operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$02</td>
|
||||
<td>* operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$03</td>
|
||||
<td>/ operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$04</td>
|
||||
<td>% operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$05</td>
|
||||
<td>unary -</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$06</td>
|
||||
<td>| operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$07</td>
|
||||
<td>& operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$08</td>
|
||||
<td>^ operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$09</td>
|
||||
<td>unary ~</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$0A</td>
|
||||
<td>&& comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$0B</td>
|
||||
<td>|| comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$0C</td>
|
||||
<td>unary !</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$0D</td>
|
||||
<td>== comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$0E</td>
|
||||
<td>!= comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$0F</td>
|
||||
<td>> comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$10</td>
|
||||
<td>< comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$11</td>
|
||||
<td>>= comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$12</td>
|
||||
<td><= comparison</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$13</td>
|
||||
<td><< operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$14</td>
|
||||
<td>>> operator</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$15</td>
|
||||
<td>BANK() function for Gameboy, a symbol ID follows</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$16</td>
|
||||
<td>HRAMCheck for Gameboy, check if value is in HRAM and logically and it with 0xFF</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$17</td>
|
||||
<td>ZeroPageCheck for PC-Engine, check if value is in ZP (0x2000-0x20FF) and logically and it with 0xFF</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$18</td>
|
||||
<td>RangeCheck. LOW and HIGH signed LONGs follow. Checks a value to see if within the range [LOW;HIGH]. If not, generate an error.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$80</td>
|
||||
<td>LONG integer follows</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$81</td>
|
||||
<td>Symbol ID follows</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<p>Last updated 18 July 1997 by <a href="mailto:surfsmurf@matilde.demon.co.uk">Carsten Sorensen</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -6,16 +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 "asm/localasm.h"
|
||||
|
||||
extern SLONG nLineNo;
|
||||
extern ULONG nTotalLines;
|
||||
@@ -26,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 MAXINCPATHS 16
|
||||
#define MAXMACROARGS 256
|
||||
#define MAXINCPATHS 128
|
||||
|
||||
#endif /* // ASM_H */
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#ifndef ASMOTOR_ASM_CHARMAP_H
|
||||
#define ASMOTOR_ASM_CHARMAP_H
|
||||
#ifndef RGBDS_ASM_CHARMAP_H
|
||||
#define RGBDS_ASM_CHARMAP_H
|
||||
|
||||
#define MAXCHARMAPS 512
|
||||
#define CHARMAPLENGTH 8
|
||||
#define CHARMAPLENGTH 16
|
||||
|
||||
struct Charmap {
|
||||
int count;
|
||||
|
||||
@@ -6,13 +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 {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#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 (1 << 11)
|
||||
#define MAXSTRLEN 255
|
||||
@@ -59,9 +59,7 @@ extern void yyunputbytes(ULONG count);
|
||||
|
||||
extern YY_BUFFER_STATE pCurrentBuffer;
|
||||
|
||||
#ifdef __GNUC__
|
||||
extern void strupr(char *s);
|
||||
extern void strlwr(char *s);
|
||||
#endif
|
||||
extern void upperstring(char *s);
|
||||
extern void lowerstring(char *s);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
#ifndef ASMOTOR_MAIN_H
|
||||
#define ASMOTOR_MAIN_H
|
||||
#ifndef RGBDS_MAIN_H
|
||||
#define RGBDS_MAIN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "extern/stdnoreturn.h"
|
||||
|
||||
struct sOptions {
|
||||
char gbgfx[4];
|
||||
char binary[2];
|
||||
SLONG fillchar;
|
||||
bool verbose;
|
||||
bool haltnop;
|
||||
bool exportall;
|
||||
//-1 == random
|
||||
};
|
||||
|
||||
@@ -22,7 +25,7 @@ extern void opt_Push(void);
|
||||
extern void opt_Pop(void);
|
||||
extern void opt_Parse(char *s);
|
||||
|
||||
void fatalerror(const char *fmt, ...);
|
||||
noreturn 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:
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,7 +1,7 @@
|
||||
#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 (1 << 16)
|
||||
#define MAXSYMLEN 256
|
||||
@@ -36,6 +36,7 @@ struct sSymbol {
|
||||
* not be changed during linking */
|
||||
|
||||
ULONG calchash(char *s);
|
||||
void sym_SetExportAll(BBOOL set);
|
||||
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
|
||||
|
||||
#ifndef _MAX_PATH
|
||||
#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
|
||||
33
include/extern/err.h
vendored
33
include/extern/err.h
vendored
@@ -1,26 +1,3 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef EXTERN_ERR_H
|
||||
#define EXTERN_ERR_H
|
||||
|
||||
@@ -29,7 +6,7 @@
|
||||
#else
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "stdnoreturn.h"
|
||||
#include "extern/stdnoreturn.h"
|
||||
|
||||
#define warn rgbds_warn
|
||||
#define vwarn rgbds_vwarn
|
||||
@@ -41,10 +18,6 @@
|
||||
#define errx rgbds_errx
|
||||
#define verrx rgbds_verrx
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void warn(const char *, ...);
|
||||
void vwarn(const char *, va_list);
|
||||
void warnx(const char *, ...);
|
||||
@@ -55,10 +28,6 @@ noreturn void verr(int, const char *, va_list);
|
||||
noreturn void errx(int, const char *, ...);
|
||||
noreturn void verrx(int, const char *, va_list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#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
|
||||
10
include/extern/stdnoreturn.h
vendored
10
include/extern/stdnoreturn.h
vendored
@@ -1,16 +1,16 @@
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
// C11 or newer
|
||||
/* C11 or newer */
|
||||
#define noreturn _Noreturn
|
||||
#elif __cplusplus >= 201103L
|
||||
// C++11 or newer
|
||||
/* C++11 or newer */
|
||||
#define noreturn [[noreturn]]
|
||||
#elif __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ >= 5))
|
||||
// GCC 2.5 or newer
|
||||
/* GCC 2.5 or newer */
|
||||
#define noreturn __attribute__ ((noreturn))
|
||||
#elif _MSC_VER >= 1310
|
||||
// MS Visual Studio 2003/.NET Framework 1.1 or newer
|
||||
/* MS Visual Studio 2003/.NET Framework 1.1 or newer */
|
||||
#define noreturn _declspec( noreturn)
|
||||
#else
|
||||
// unsupported, but no need to throw a fit
|
||||
/* unsupported, but no need to throw a fit */
|
||||
#define noreturn
|
||||
#endif
|
||||
|
||||
30
include/gfx/gb.h
Normal file
30
include/gfx/gb.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_GFX_GB_H
|
||||
#define RGBDS_GFX_GB_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gfx/main.h"
|
||||
|
||||
void png_to_gb(struct PNGImage png, struct GBImage *gb);
|
||||
void output_file(struct Options opts, struct GBImage gb);
|
||||
int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles, int tile_size);
|
||||
void create_tilemap(struct Options opts, struct GBImage *gb, struct Tilemap *tilemap);
|
||||
void output_tilemap_file(struct Options opts, struct Tilemap tilemap);
|
||||
void output_palette_file(struct Options opts, struct PNGImage png);
|
||||
|
||||
#endif
|
||||
75
include/gfx/main.h
Normal file
75
include/gfx/main.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_GFX_MAIN_H
|
||||
#define RGBDS_GFX_MAIN_H
|
||||
|
||||
#include <png.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
struct Options {
|
||||
bool debug;
|
||||
bool verbose;
|
||||
bool hardfix;
|
||||
bool fix;
|
||||
bool horizontal;
|
||||
bool unique;
|
||||
int trim;
|
||||
char *mapfile;
|
||||
bool mapout;
|
||||
char *palfile;
|
||||
bool palout;
|
||||
char *outfile;
|
||||
char *infile;
|
||||
};
|
||||
|
||||
struct PNGImage {
|
||||
png_struct *png;
|
||||
png_info *info;
|
||||
png_byte **data;
|
||||
int width;
|
||||
int height;
|
||||
png_byte depth;
|
||||
png_byte type;
|
||||
bool horizontal;
|
||||
int trim;
|
||||
char *mapfile;
|
||||
bool mapout;
|
||||
char *palfile;
|
||||
bool palout;
|
||||
};
|
||||
|
||||
struct GBImage {
|
||||
uint8_t *data;
|
||||
int size;
|
||||
bool horizontal;
|
||||
int trim;
|
||||
};
|
||||
|
||||
struct Tilemap {
|
||||
uint8_t *data;
|
||||
int size;
|
||||
};
|
||||
|
||||
int depth, colors;
|
||||
|
||||
#include "gfx/makepng.h"
|
||||
#include "gfx/gb.h"
|
||||
|
||||
#endif
|
||||
28
include/gfx/makepng.h
Normal file
28
include/gfx/makepng.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_GFX_PNG_H
|
||||
#define RGBDS_GFX_PNG_H
|
||||
|
||||
#include "gfx/main.h"
|
||||
|
||||
void input_png_file(struct Options opts, struct PNGImage *img);
|
||||
void get_text(struct PNGImage *png);
|
||||
void set_text(struct PNGImage *png);
|
||||
void output_png_file(struct Options opts, struct PNGImage *png);
|
||||
void free_png_data(struct PNGImage *png);
|
||||
|
||||
#endif
|
||||
@@ -1,17 +1,30 @@
|
||||
#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_ROM0 = 0,
|
||||
BANK_ROMX,
|
||||
BANK_WRAM0 = 512,
|
||||
BANK_WRAMX,
|
||||
BANK_VRAM = 520,
|
||||
BANK_HRAM = 522,
|
||||
BANK_SRAM = 523
|
||||
};
|
||||
#define MAXBANKS 527
|
||||
|
||||
enum eBankCount {
|
||||
BANK_COUNT_ROM0 = 1,
|
||||
BANK_COUNT_ROMX = 511,
|
||||
BANK_COUNT_WRAM0 = 1,
|
||||
BANK_COUNT_WRAMX = 7,
|
||||
BANK_COUNT_VRAM = 2,
|
||||
BANK_COUNT_HRAM = 1,
|
||||
BANK_COUNT_SRAM = 16
|
||||
};
|
||||
|
||||
#define MAXBANKS (BANK_COUNT_ROM0 + BANK_COUNT_ROMX + BANK_COUNT_WRAM0 + BANK_COUNT_WRAMX \
|
||||
+ BANK_COUNT_VRAM + BANK_COUNT_HRAM + BANK_COUNT_SRAM)
|
||||
|
||||
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,9 +1,9 @@
|
||||
#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];
|
||||
extern char *smartlinkstartsymbol;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
|
||||
#ifndef _MAX_PATH
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
extern SLONG options;
|
||||
#define OPT_SMALL 0x01
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
#ifndef ASMOTOR_LINK_TYPES_H
|
||||
#define ASMOTOR_LINK_TYPES_H
|
||||
#ifndef RGBDS_TYPES_H
|
||||
#define RGBDS_TYPES_H
|
||||
|
||||
#ifndef _MAX_PATH
|
||||
#define _MAX_PATH 512
|
||||
343
src/asm/asmy.y
343
src/asm/asmy.y
@@ -1,7 +1,6 @@
|
||||
%{
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -18,11 +17,52 @@
|
||||
#include "asm/main.h"
|
||||
#include "asm/lexer.h"
|
||||
|
||||
extern bool haltnop;
|
||||
|
||||
char *tzNewMacro;
|
||||
ULONG ulNewMacroSize;
|
||||
|
||||
void
|
||||
bankrangecheck(char *name, ULONG secttype, SLONG org, SLONG bank)
|
||||
{
|
||||
SLONG minbank, maxbank;
|
||||
char *stype = NULL;
|
||||
switch (secttype) {
|
||||
case SECT_ROMX:
|
||||
stype = "ROMX";
|
||||
minbank = 1;
|
||||
maxbank = 0x1ff;
|
||||
break;
|
||||
case SECT_SRAM:
|
||||
stype = "SRAM";
|
||||
minbank = 0;
|
||||
maxbank = 0x1ff;
|
||||
break;
|
||||
case SECT_WRAMX:
|
||||
stype = "WRAMX";
|
||||
minbank = 1;
|
||||
maxbank = 7;
|
||||
break;
|
||||
case SECT_VRAM:
|
||||
stype = "VRAM";
|
||||
minbank = 0;
|
||||
maxbank = 1;
|
||||
break;
|
||||
default:
|
||||
yyerror("BANK only allowed for "
|
||||
"ROMX, WRAMX, SRAM, or VRAM sections");
|
||||
}
|
||||
|
||||
if (stype && (bank < minbank || bank > maxbank)) {
|
||||
yyerror("%s bank value $%x out of range ($%x to $%x)",
|
||||
stype, bank, minbank, maxbank);
|
||||
}
|
||||
|
||||
if (secttype == SECT_WRAMX) {
|
||||
bank -= minbank;
|
||||
}
|
||||
|
||||
out_NewAbsSection(name, secttype, org, bank);
|
||||
}
|
||||
|
||||
size_t symvaluetostring(char *dest, size_t maxLength, char *sym)
|
||||
{
|
||||
size_t length;
|
||||
@@ -102,8 +142,9 @@ void copyrept( void )
|
||||
{
|
||||
SLONG level=1, len, instring=0;
|
||||
char *src=pCurrentBuffer->pBuffer;
|
||||
char *bufferEnd = pCurrentBuffer->pBufferStart + pCurrentBuffer->nBufferSize;
|
||||
|
||||
while( *src && level )
|
||||
while( src < bufferEnd && level )
|
||||
{
|
||||
if( instring==0 )
|
||||
{
|
||||
@@ -142,6 +183,10 @@ void copyrept( void )
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0) {
|
||||
fatalerror("Unterminated REPT block");
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer-4;
|
||||
|
||||
src=pCurrentBuffer->pBuffer;
|
||||
@@ -177,8 +222,9 @@ void copymacro( void )
|
||||
{
|
||||
SLONG level=1, len, instring=0;
|
||||
char *src=pCurrentBuffer->pBuffer;
|
||||
char *bufferEnd = pCurrentBuffer->pBufferStart + pCurrentBuffer->nBufferSize;
|
||||
|
||||
while( *src && level )
|
||||
while( src < bufferEnd && level )
|
||||
{
|
||||
if( instring==0 )
|
||||
{
|
||||
@@ -217,6 +263,10 @@ void copymacro( void )
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0) {
|
||||
fatalerror("Unterminated MACRO definition");
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer-4;
|
||||
|
||||
src=pCurrentBuffer->pBuffer;
|
||||
@@ -308,6 +358,10 @@ void if_skip_to_else( void )
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0) {
|
||||
fatalerror("Unterminated IF construct");
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer;
|
||||
|
||||
yyskipbytes( len );
|
||||
@@ -363,6 +417,10 @@ void if_skip_to_endc( void )
|
||||
}
|
||||
}
|
||||
|
||||
if (level != 0) {
|
||||
fatalerror("Unterminated IF construct");
|
||||
}
|
||||
|
||||
len=src-pCurrentBuffer->pBuffer;
|
||||
|
||||
yyskipbytes( len );
|
||||
@@ -500,73 +558,62 @@ void if_skip_to_endc( void )
|
||||
|
||||
%%
|
||||
|
||||
asmfile : lines lastline
|
||||
;
|
||||
asmfile : lines;
|
||||
|
||||
lastline : /* empty */
|
||||
| line
|
||||
{ nLineNo+=1; nTotalLines+=1; }
|
||||
;
|
||||
/* Note: The lexer add '\n' at the end of the input */
|
||||
lines : /* empty */
|
||||
| lines line '\n' {
|
||||
nLineNo += 1;
|
||||
nTotalLines += 1;
|
||||
};
|
||||
|
||||
lines : /* empty */
|
||||
| lines line '\n'
|
||||
{ nLineNo+=1; nTotalLines+=1; }
|
||||
;
|
||||
line : label
|
||||
| label cpu_command
|
||||
| label macro
|
||||
| label simple_pseudoop
|
||||
| pseudoop;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
macro : T_ID
|
||||
{
|
||||
yy_set_state( LEX_STATE_MACROARGS );
|
||||
}
|
||||
macroargs
|
||||
{
|
||||
yy_set_state( LEX_STATE_NORMAL );
|
||||
if (!fstk_RunMacro($1)) {
|
||||
fatalerror("Macro '%s' not defined", $1);
|
||||
}
|
||||
};
|
||||
|
||||
if( !fstk_RunMacro($1) )
|
||||
{
|
||||
yyerror("Macro '%s' not defined", $1);
|
||||
}
|
||||
}
|
||||
;
|
||||
macroargs : /* empty */
|
||||
| macroarg
|
||||
| macroarg ',' macroargs;
|
||||
|
||||
macroargs : /* empty */
|
||||
| macroarg
|
||||
| macroarg ',' macroargs
|
||||
;
|
||||
macroarg : T_STRING {
|
||||
sym_AddNewMacroArg($1);
|
||||
};
|
||||
|
||||
macroarg : T_STRING
|
||||
{ sym_AddNewMacroArg( $1 ); }
|
||||
;
|
||||
|
||||
pseudoop : equ
|
||||
| set
|
||||
| rb
|
||||
| rw
|
||||
| rl
|
||||
| equs
|
||||
| macrodef
|
||||
;
|
||||
pseudoop : equ
|
||||
| set
|
||||
| rb
|
||||
| rw
|
||||
| rl
|
||||
| equs
|
||||
| macrodef;
|
||||
|
||||
simple_pseudoop : include
|
||||
| printf
|
||||
@@ -596,52 +643,44 @@ simple_pseudoop : include
|
||||
| pushs
|
||||
| popo
|
||||
| pusho
|
||||
| opt
|
||||
;
|
||||
| opt;
|
||||
|
||||
opt : T_POP_OPT
|
||||
{
|
||||
yy_set_state( LEX_STATE_MACROARGS );
|
||||
}
|
||||
opt_list
|
||||
{
|
||||
yy_set_state( LEX_STATE_NORMAL );
|
||||
}
|
||||
;
|
||||
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 : opt_list_entry
|
||||
| opt_list_entry ',' opt_list;
|
||||
|
||||
opt_list_entry : T_STRING
|
||||
{
|
||||
opt_Parse($1);
|
||||
}
|
||||
;
|
||||
opt_list_entry : T_STRING {
|
||||
opt_Parse($1);
|
||||
};
|
||||
|
||||
popo : T_POP_POPO
|
||||
{ opt_Pop(); }
|
||||
;
|
||||
popo : T_POP_POPO {
|
||||
opt_Pop();
|
||||
};
|
||||
|
||||
pusho : T_POP_PUSHO
|
||||
{ opt_Push(); }
|
||||
;
|
||||
pusho : T_POP_PUSHO {
|
||||
opt_Push();
|
||||
};
|
||||
|
||||
pops : T_POP_POPS
|
||||
{ out_PopSection(); }
|
||||
;
|
||||
pops : T_POP_POPS {
|
||||
out_PopSection();
|
||||
};
|
||||
|
||||
pushs : T_POP_PUSHS
|
||||
{ out_PushSection(); }
|
||||
;
|
||||
pushs : T_POP_PUSHS {
|
||||
out_PushSection();
|
||||
};
|
||||
|
||||
fail : T_POP_FAIL string
|
||||
{ fatalerror("%s", $2); }
|
||||
;
|
||||
fail : T_POP_FAIL string {
|
||||
fatalerror("%s", $2);
|
||||
};
|
||||
|
||||
warn : T_POP_WARN string
|
||||
{ yyerror("%s", $2); }
|
||||
;
|
||||
warn : T_POP_WARN string {
|
||||
yyerror("%s", $2);
|
||||
};
|
||||
|
||||
shift : T_POP_SHIFT
|
||||
{ sym_ShiftCurrentMacroArgs(); }
|
||||
@@ -709,11 +748,11 @@ dl : T_POP_DL constlist_32bit
|
||||
|
||||
purge : T_POP_PURGE
|
||||
{
|
||||
oDontExpandStrings=1;
|
||||
oDontExpandStrings = true;
|
||||
}
|
||||
purge_list
|
||||
{
|
||||
oDontExpandStrings=0;
|
||||
oDontExpandStrings = false;
|
||||
}
|
||||
;
|
||||
|
||||
@@ -955,8 +994,8 @@ relocconst : T_ID
|
||||
{ rpn_UNNOT(&$$,&$2); }
|
||||
| T_OP_BANK '(' T_ID ')'
|
||||
{ rpn_Bank(&$$,$3); $$.nVal = 0; }
|
||||
| T_OP_DEF { oDontExpandStrings=1; } '(' T_ID ')'
|
||||
{ rpn_Number(&$$,sym_isConstDefined($4)); oDontExpandStrings=0; }
|
||||
| T_OP_DEF { oDontExpandStrings = true; } '(' T_ID ')'
|
||||
{ rpn_Number(&$$,sym_isConstDefined($4)); oDontExpandStrings = false; }
|
||||
| T_OP_ROUND '(' const ')' { rpn_Number(&$$,math_Round($3)); }
|
||||
| T_OP_CEIL '(' const ')' { rpn_Number(&$$,math_Ceil($3)); }
|
||||
| T_OP_FLOOR '(' const ')' { rpn_Number(&$$,math_Floor($3)); }
|
||||
@@ -1008,8 +1047,16 @@ const : T_ID { $$ = sym_GetConstantValue($1); }
|
||||
| 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; }
|
||||
| const T_OP_DIV const {
|
||||
if ($3 == 0)
|
||||
fatalerror("division by zero");
|
||||
$$ = $1 / $3;
|
||||
}
|
||||
| const T_OP_MOD const {
|
||||
if ($3 == 0)
|
||||
fatalerror("division by zero");
|
||||
$$ = $1 % $3;
|
||||
}
|
||||
| T_OP_ADD const %prec NEG { $$ = +$2; }
|
||||
| T_OP_SUB const %prec NEG { $$ = -$2; }
|
||||
| T_OP_NOT const %prec NEG { $$ = 0xFFFFFFFF^$2; }
|
||||
@@ -1025,7 +1072,7 @@ const : T_ID { $$ = sym_GetConstantValue($1); }
|
||||
| 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 { oDontExpandStrings=1; } '(' T_ID ')' { $$ = sym_isConstDefined($4); oDontExpandStrings=0; }
|
||||
| T_OP_DEF { oDontExpandStrings = true; } '(' T_ID ')' { $$ = sym_isConstDefined($4); oDontExpandStrings = false; }
|
||||
| T_OP_STRCMP '(' string ',' string ')' { $$ = strcmp( $3, $5 ); }
|
||||
| T_OP_STRIN '(' string ',' string ')'
|
||||
{
|
||||
@@ -1050,9 +1097,9 @@ string : T_STRING
|
||||
| T_OP_STRCAT '(' string ',' string ')'
|
||||
{ strcpy($$,$3); strcat($$,$5); }
|
||||
| T_OP_STRUPR '(' string ')'
|
||||
{ strcpy($$,$3); strupr($$); }
|
||||
{ strcpy($$,$3); upperstring($$); }
|
||||
| T_OP_STRLWR '(' string ')'
|
||||
{ strcpy($$,$3); strlwr($$); }
|
||||
{ strcpy($$,$3); lowerstring($$); }
|
||||
;
|
||||
section:
|
||||
T_POP_SECTION string ',' sectiontype
|
||||
@@ -1068,76 +1115,14 @@ section:
|
||||
}
|
||||
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']'
|
||||
{
|
||||
if( $4==SECT_ROMX ) {
|
||||
if( $8>=1 && $8<=0x1ff )
|
||||
out_NewAbsSection($2,$4,-1,$8);
|
||||
else
|
||||
yyerror("ROM bank value $%x out of range (1 to $1ff)", $8);
|
||||
} else if ($4 == SECT_SRAM) {
|
||||
if ($8 >= 0 && $8 <= 3) {
|
||||
out_NewAbsSection($2, $4, -1, $8);
|
||||
} else {
|
||||
yyerror("SRAM bank value $%x out of range (0 to 3)", $8);
|
||||
}
|
||||
} else if ($4 == SECT_WRAMX) {
|
||||
if ($8 >= 1 && $8 <= 7) {
|
||||
out_NewAbsSection($2, $4, -1, $8);
|
||||
} else {
|
||||
yyerror("WRAMX bank value $%x out of range (1 to 7)", $8);
|
||||
}
|
||||
} else if ($4 == SECT_VRAM) {
|
||||
if ($8 >= 0 && $8 <= 1) {
|
||||
out_NewAbsSection($2, $4, -1, $8);
|
||||
} else {
|
||||
yyerror("VRAM bank value $%x out of range (0 to 1)", $8);
|
||||
}
|
||||
} else {
|
||||
yyerror("BANK only allowed for ROMX, WRAMX, SRAM, or VRAM sections");
|
||||
}
|
||||
bankrangecheck($2, $4, -1, $8);
|
||||
}
|
||||
| T_POP_SECTION string ',' sectiontype '[' const ']' ',' T_OP_BANK '[' const ']'
|
||||
{
|
||||
if( $4==SECT_ROMX ) {
|
||||
if( $6>=0 && $6<0x10000 ) {
|
||||
if( $11>=1 && $11<=0x1ff )
|
||||
out_NewAbsSection($2,$4,$6,$11);
|
||||
else
|
||||
yyerror("ROM bank value $%x out of range (1 to $1ff)", $11);
|
||||
} else
|
||||
yyerror("Address $%x not 16-bit", $6);
|
||||
} else if ($4 == SECT_SRAM) {
|
||||
if ($6 >= 0 && $6 < 0x10000) {
|
||||
if ($11 >= 0 && $11 <= 3) {
|
||||
out_NewAbsSection($2, $4, $6, $11);
|
||||
} else {
|
||||
yyerror("SRAM bank value $%x out of range (0 to 3)", $11);
|
||||
}
|
||||
} else {
|
||||
yyerror("Address $%x not 16-bit", $6);
|
||||
}
|
||||
} else if ($4 == SECT_WRAMX) {
|
||||
if ($6 >= 0 && $6 < 0x10000) {
|
||||
if ($11 >= 1 && $11 <= 7) {
|
||||
out_NewAbsSection($2, $4, $6, $11);
|
||||
} else {
|
||||
yyerror("WRAMX bank value $%x out of range (1 to 7)", $11);
|
||||
}
|
||||
} else {
|
||||
yyerror("Address $%x not 16-bit", $6);
|
||||
}
|
||||
} else if ($4 == SECT_VRAM) {
|
||||
if ($6 >= 0 && $6 < 0x10000) {
|
||||
if ($11 >= 0 && $11 <= 1) {
|
||||
out_NewAbsSection($2,$4,$6,$11);
|
||||
} else {
|
||||
yyerror("VRAM bank value $%x out of range (0 to 1)", $11);
|
||||
}
|
||||
} else {
|
||||
yyerror("Address $%x not 16-bit", $6);
|
||||
}
|
||||
} else {
|
||||
yyerror("BANK only allowed for ROMX, WRAMX, SRAM, or VRAM sections");
|
||||
if ($6 < 0 || $6 > 0x10000) {
|
||||
yyerror("Address $%x not 16-bit", $6);
|
||||
}
|
||||
bankrangecheck($2, $4, $6, $11);
|
||||
}
|
||||
;
|
||||
|
||||
@@ -1264,7 +1249,7 @@ z80_ex : T_Z80_EX T_MODE_HL comma T_MODE_SP_IND
|
||||
z80_halt: T_Z80_HALT
|
||||
{
|
||||
out_AbsByte(0x76);
|
||||
if (haltnop) {
|
||||
if (CurrentOptions.haltnop) {
|
||||
out_AbsByte(0x00);
|
||||
}
|
||||
}
|
||||
@@ -1296,12 +1281,16 @@ 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)); }
|
||||
| T_Z80_LDI T_MODE_A comma T_MODE_HL_IND
|
||||
{ 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)); }
|
||||
| T_Z80_LDD T_MODE_A comma T_MODE_HL_IND
|
||||
{ out_AbsByte(0x0A|(3<<4)); }
|
||||
;
|
||||
|
||||
z80_ldio : T_Z80_LDIO T_MODE_A comma op_mem_ind
|
||||
|
||||
@@ -1,3 +1,57 @@
|
||||
/*
|
||||
* UTF-8 decoder copyright © 2008–2009 Björn Höhrmann <bjoern@hoehrmann.de>
|
||||
* http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
static const uint8_t utf8d[] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f
|
||||
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf
|
||||
8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df
|
||||
0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef
|
||||
0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff
|
||||
0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2
|
||||
1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4
|
||||
1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6
|
||||
1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8
|
||||
};
|
||||
|
||||
uint32_t
|
||||
decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
|
||||
uint32_t type = utf8d[byte];
|
||||
|
||||
*codep = (*state != 0) ?
|
||||
(byte & 0x3fu) | (*codep << 6) :
|
||||
(0xff >> type) & (byte);
|
||||
|
||||
*state = utf8d[256 + *state*16 + type];
|
||||
return *state;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copyright © 2013 stag019 <stag019@gmail.com>
|
||||
*
|
||||
@@ -28,119 +82,91 @@ struct Charmap globalCharmap = {0};
|
||||
extern struct Section *pCurrentSection;
|
||||
|
||||
int
|
||||
readUTF8Char(char *destination, char *source)
|
||||
readUTF8Char(char *dest, char *src)
|
||||
{
|
||||
int size;
|
||||
UBYTE first;
|
||||
first = source[0];
|
||||
uint32_t state;
|
||||
uint32_t codep;
|
||||
int i;
|
||||
|
||||
if(first >= 0xFC)
|
||||
{
|
||||
size = 6;
|
||||
for (i = 0, state = 0;; i++) {
|
||||
if (decode(&state, &codep, (uint8_t)src[i]) == 1) {
|
||||
fatalerror("invalid UTF-8 character");
|
||||
}
|
||||
|
||||
dest[i] = src[i];
|
||||
|
||||
i++;
|
||||
if (state == 0) {
|
||||
dest[i] = '\0';
|
||||
return i;
|
||||
}
|
||||
dest[i] = src[i];
|
||||
}
|
||||
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;
|
||||
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)
|
||||
{
|
||||
if (pCurrentSection) {
|
||||
if (pCurrentSection->charmap) {
|
||||
charmap = pCurrentSection->charmap;
|
||||
} else {
|
||||
if ((charmap = calloc(1, sizeof(struct Charmap))) ==
|
||||
NULL) {
|
||||
fatalerror("Not enough memory for charmap");
|
||||
}
|
||||
pCurrentSection -> charmap = charmap;
|
||||
pCurrentSection->charmap = charmap;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
charmap = &globalCharmap;
|
||||
}
|
||||
|
||||
if(nPass == 2)
|
||||
{
|
||||
return charmap -> count;
|
||||
if (nPass == 2) {
|
||||
return charmap->count;
|
||||
}
|
||||
|
||||
if(charmap -> count > MAXCHARMAPS || strlen(input) > CHARMAPLENGTH)
|
||||
{
|
||||
if (charmap->count > MAXCHARMAPS || strlen(input) > CHARMAPLENGTH) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
input_length = strlen(input);
|
||||
if(input_length > 1)
|
||||
{
|
||||
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;
|
||||
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);
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(charmap -> input[charmap -> count], input, input_length);
|
||||
charmap -> output[charmap -> count] = output;
|
||||
}
|
||||
return ++charmap -> count;
|
||||
return ++charmap->count;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -152,47 +178,35 @@ charmap_Convert(char **input)
|
||||
char *buffer;
|
||||
int i, j, length;
|
||||
|
||||
if(pCurrentSection && pCurrentSection -> charmap)
|
||||
{
|
||||
charmap = pCurrentSection -> charmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pCurrentSection && pCurrentSection->charmap) {
|
||||
charmap = pCurrentSection->charmap;
|
||||
} else {
|
||||
charmap = &globalCharmap;
|
||||
}
|
||||
|
||||
if((buffer = (char *) malloc(strlen(*input))) == NULL)
|
||||
{
|
||||
if ((buffer = malloc(strlen(*input))) == NULL) {
|
||||
fatalerror("Not enough memory for buffer");
|
||||
}
|
||||
|
||||
length = 0;
|
||||
while(**input)
|
||||
{
|
||||
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];
|
||||
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)
|
||||
{
|
||||
if (!j) {
|
||||
j = readUTF8Char(outchar, *input);
|
||||
}
|
||||
if(!outchar[0])
|
||||
{
|
||||
if (!outchar[0]) {
|
||||
buffer[length++] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i = 0; outchar[i]; i++)
|
||||
{
|
||||
} else {
|
||||
for (i = 0; outchar[i]; i++) {
|
||||
buffer[length++] = outchar[i];
|
||||
}
|
||||
}
|
||||
@@ -201,4 +215,3 @@ charmap_Convert(char **input)
|
||||
*input = buffer;
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
102
src/asm/fstack.c
102
src/asm/fstack.c
@@ -1,8 +1,5 @@
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* FileStack routines
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@@ -13,7 +10,7 @@
|
||||
|
||||
#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"
|
||||
@@ -23,13 +20,6 @@
|
||||
#define PATH_MAX 256
|
||||
#endif
|
||||
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
*/
|
||||
|
||||
struct sContext *pFileStack;
|
||||
struct sSymbol *pCurrentMacro;
|
||||
YY_BUFFER_STATE CurrentFlexHandle;
|
||||
@@ -55,12 +45,8 @@ ULONG ulMacroReturnValue;
|
||||
#define STAT_isREPTBlock 3
|
||||
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Context push and pop
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
pushcontext(void)
|
||||
{
|
||||
@@ -167,13 +153,10 @@ yywrap(void)
|
||||
{
|
||||
return (popcontext());
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Dump the context stack to stderr
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dump the context stack to stderr
|
||||
*/
|
||||
void
|
||||
fstk_Dump(void)
|
||||
{
|
||||
@@ -189,17 +172,22 @@ fstk_Dump(void)
|
||||
|
||||
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);
|
||||
if (NextIncPath == MAXINCPATHS) {
|
||||
fatalerror("Too many include directories passed from command line");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlcpy(IncludePaths[NextIncPath++], s, _MAX_PATH) >= _MAX_PATH) {
|
||||
fatalerror("Include path too long '%s'",s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *
|
||||
@@ -230,13 +218,10 @@ fstk_FindFile(char *fname)
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Set up an include file for parsing
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set up an include file for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunInclude(char *tzFileName)
|
||||
{
|
||||
@@ -262,13 +247,10 @@ fstk_RunInclude(char *tzFileName)
|
||||
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)
|
||||
{
|
||||
@@ -281,6 +263,8 @@ 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,
|
||||
@@ -290,13 +274,10 @@ fstk_RunMacro(char *s)
|
||||
} 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)
|
||||
{
|
||||
@@ -316,13 +297,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)
|
||||
{
|
||||
@@ -338,13 +316,10 @@ fstk_RunString(char *s)
|
||||
} else
|
||||
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)
|
||||
{
|
||||
@@ -362,13 +337,10 @@ fstk_RunRept(ULONG count)
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - FSTACK.C (FileStack routines)
|
||||
*
|
||||
* Initialize the filestack routines
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Initialize the filestack routines
|
||||
*/
|
||||
void
|
||||
fstk_Init(char *s)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -96,7 +97,7 @@ ascii2bin(char *s)
|
||||
|
||||
while (*s != '\0') {
|
||||
c = convertfunc(*s++);
|
||||
result = result * 2 + ((c & 1) << 8) + ((c & 2) >> 1);
|
||||
result = result * 2 + ((c & 2) << 7) + (c & 1);
|
||||
}
|
||||
} else {
|
||||
while (*s != '\0')
|
||||
@@ -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);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "asm/asm.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "asm/types.h"
|
||||
#include "types.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/rpn.h"
|
||||
#include "asm/fstack.h"
|
||||
@@ -39,9 +39,8 @@ ULONG tFloatingChars[256];
|
||||
ULONG nFloating;
|
||||
enum eLexerState lexerstate = LEX_STATE_NORMAL;
|
||||
|
||||
#ifdef __GNUC__
|
||||
void
|
||||
strupr(char *s)
|
||||
upperstring(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = toupper(*s);
|
||||
@@ -50,14 +49,14 @@ strupr(char *s)
|
||||
}
|
||||
|
||||
void
|
||||
strlwr(char *s)
|
||||
lowerstring(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = tolower(*s);
|
||||
s += 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
yyskipbytes(ULONG count)
|
||||
{
|
||||
@@ -352,7 +351,7 @@ lex_AddStrings(struct sLexInitString * lex)
|
||||
(*ppHash)->nToken = lex->nToken;
|
||||
(*ppHash)->pNext = NULL;
|
||||
|
||||
strupr((*ppHash)->tzName);
|
||||
upperstring((*ppHash)->tzName);
|
||||
|
||||
if ((*ppHash)->nNameLength > nLexMaxLength)
|
||||
nLexMaxLength = (*ppHash)->nNameLength;
|
||||
|
||||
220
src/asm/main.c
220
src/asm/main.c
@@ -1,13 +1,5 @@
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -19,18 +11,16 @@
|
||||
#include "asm/output.h"
|
||||
#include "asm/main.h"
|
||||
#include "extern/err.h"
|
||||
#include "extern/reallocarray.h"
|
||||
|
||||
int yyparse(void);
|
||||
void setuplex(void);
|
||||
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* VARIABLES
|
||||
*
|
||||
*/
|
||||
int cldefines_index;
|
||||
int cldefines_size;
|
||||
char **cldefines;
|
||||
|
||||
bool haltnop;
|
||||
char *progname;
|
||||
|
||||
clock_t nStartClock, nEndClock;
|
||||
SLONG nLineNo;
|
||||
@@ -39,10 +29,7 @@ ULONG nTotalLines, nPass, nPC, nIFDepth, nErrors;
|
||||
extern int yydebug;
|
||||
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* Option stack
|
||||
*
|
||||
*/
|
||||
|
||||
struct sOptions DefaultOptions;
|
||||
@@ -193,13 +180,49 @@ opt_Pop(void)
|
||||
} else
|
||||
fatalerror("No entries in the option stack");
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* Error handling
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
opt_AddDefine(char *s)
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -229,26 +252,15 @@ fatalerror(const char *fmt, ...)
|
||||
va_end(args);
|
||||
exit(5);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - MAIN.C
|
||||
*
|
||||
* Help text
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
PrintUsage(void)
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("Usage: rgbasm [-v] [-h] [-b chars] [-g chars] [-i path] [-o outfile] [-p pad_value]\n"
|
||||
" file\n");
|
||||
printf(
|
||||
"Usage: rgbasm [-hvE] [-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[])
|
||||
@@ -260,10 +272,18 @@ main(int argc, char *argv[])
|
||||
|
||||
char *tzMainfile;
|
||||
|
||||
haltnop = true;
|
||||
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; */
|
||||
|
||||
@@ -275,12 +295,14 @@ main(int argc, char *argv[])
|
||||
DefaultOptions.binary[1] = '1';
|
||||
DefaultOptions.fillchar = 0;
|
||||
DefaultOptions.verbose = false;
|
||||
DefaultOptions.haltnop = true;
|
||||
DefaultOptions.exportall = false;
|
||||
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
newopt = CurrentOptions;
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:g:hi:o:p:v")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "b:D:g:hi:o:p:vE")) != -1) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
if (strlen(optarg) == 2) {
|
||||
@@ -291,6 +313,9 @@ main(int argc, char *argv[])
|
||||
"option 'b'");
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
opt_AddDefine(optarg);
|
||||
break;
|
||||
case 'g':
|
||||
if (strlen(optarg) == 4) {
|
||||
newopt.gbgfx[0] = optarg[1];
|
||||
@@ -303,7 +328,7 @@ main(int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
haltnop = false;
|
||||
newopt.haltnop = false;
|
||||
break;
|
||||
case 'i':
|
||||
fstk_AddIncludePath(optarg);
|
||||
@@ -324,8 +349,11 @@ main(int argc, char *argv[])
|
||||
case 'v':
|
||||
newopt.verbose = true;
|
||||
break;
|
||||
case 'E':
|
||||
newopt.exportall = true;
|
||||
break;
|
||||
default:
|
||||
PrintUsage();
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
@@ -335,6 +363,9 @@ main(int argc, char *argv[])
|
||||
|
||||
DefaultOptions = CurrentOptions;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
|
||||
tzMainfile = argv[argc - 1];
|
||||
|
||||
setuplex();
|
||||
@@ -352,7 +383,10 @@ main(int argc, char *argv[])
|
||||
nPass = 1;
|
||||
nErrors = 0;
|
||||
sym_PrepPass1();
|
||||
sym_SetExportAll(CurrentOptions.exportall);
|
||||
fstk_Init(tzMainfile);
|
||||
opt_ParseDefines();
|
||||
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Pass 1...\n");
|
||||
}
|
||||
@@ -360,59 +394,49 @@ main(int argc, char *argv[])
|
||||
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);
|
||||
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Pass 2...\n");
|
||||
}
|
||||
|
||||
if (yyparse() == 0 && nErrors == 0) {
|
||||
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();
|
||||
} else {
|
||||
printf
|
||||
("Assembly aborted in pass 2 (%ld errors)!\n",
|
||||
nErrors);
|
||||
//sym_PrintSymbolTable();
|
||||
exit(5);
|
||||
}
|
||||
} else {
|
||||
errx(1, "Unterminated IF construct (%ld levels)!",
|
||||
nIFDepth);
|
||||
}
|
||||
} else {
|
||||
errx(1, "Assembly aborted in pass 1 (%ld errors)!",
|
||||
nErrors);
|
||||
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;
|
||||
}
|
||||
|
||||
131
src/asm/math.c
131
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,143 +37,110 @@ 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)));
|
||||
}/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Round
|
||||
*
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Round
|
||||
*/
|
||||
SLONG
|
||||
math_Round(SLONG i)
|
||||
{
|
||||
return double2fix(round(fix2double(i)));
|
||||
}/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Ceil
|
||||
*
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Ceil
|
||||
*/
|
||||
SLONG
|
||||
math_Ceil(SLONG i)
|
||||
{
|
||||
return double2fix(ceil(fix2double(i)));
|
||||
}/*
|
||||
* RGBAsm - MATH.C (Fixedpoint math routines)
|
||||
*
|
||||
* Floor
|
||||
*
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Floor
|
||||
*/
|
||||
SLONG
|
||||
math_Floor(SLONG i)
|
||||
{
|
||||
|
||||
388
src/asm/output.c
388
src/asm/output.c
@@ -1,8 +1,5 @@
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* Outputs an objectfile
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@@ -22,13 +19,6 @@
|
||||
|
||||
#define SECTIONCHUNK 0x4000
|
||||
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Internal structures
|
||||
*
|
||||
*/
|
||||
|
||||
void out_SetCurrentSection(struct Section * pSect);
|
||||
|
||||
struct Patch {
|
||||
@@ -52,12 +42,6 @@ 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;
|
||||
@@ -67,12 +51,8 @@ char *tzObjectname;
|
||||
struct SectionStackEntry *pSectionStack = NULL;
|
||||
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Section stack routines
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
out_PushSection(void)
|
||||
{
|
||||
@@ -99,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)
|
||||
{
|
||||
@@ -121,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)
|
||||
{
|
||||
@@ -143,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)
|
||||
{
|
||||
@@ -164,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)
|
||||
{
|
||||
@@ -179,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)
|
||||
{
|
||||
@@ -193,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)
|
||||
{
|
||||
@@ -218,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)
|
||||
{
|
||||
@@ -235,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)
|
||||
{
|
||||
@@ -269,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)
|
||||
{
|
||||
@@ -290,25 +243,27 @@ writesymbol(struct sSymbol * pSym, FILE * f)
|
||||
offset = 0;
|
||||
sectid = -1;
|
||||
type = SYM_IMPORT;
|
||||
} else if (pSym->nType & SYMF_EXPORT) {
|
||||
/* Symbol should be exported */
|
||||
strcpy(symname, pSym->tzName);
|
||||
type = SYM_EXPORT;
|
||||
offset = pSym->nValue;
|
||||
if (pSym->nType & SYMF_CONST)
|
||||
sectid = -1;
|
||||
else
|
||||
sectid = getsectid(pSym->pSection);
|
||||
} else {
|
||||
/* Symbol is local to this file */
|
||||
if (pSym->nType & SYMF_LOCAL) {
|
||||
strcpy(symname, pSym->pScope->tzName);
|
||||
strcat(symname, pSym->tzName);
|
||||
} else
|
||||
strcpy(symname, pSym->tzName);
|
||||
type = SYM_LOCAL;
|
||||
offset = pSym->nValue;
|
||||
sectid = getsectid(pSym->pSection);
|
||||
|
||||
if (pSym->nType & SYMF_EXPORT) {
|
||||
/* Symbol should be exported */
|
||||
type = SYM_EXPORT;
|
||||
offset = pSym->nValue;
|
||||
if (pSym->nType & SYMF_CONST)
|
||||
sectid = -1;
|
||||
else
|
||||
sectid = getsectid(pSym->pSection);
|
||||
} else {
|
||||
/* Symbol is local to this file */
|
||||
type = SYM_LOCAL;
|
||||
offset = pSym->nValue;
|
||||
sectid = getsectid(pSym->pSection);
|
||||
}
|
||||
}
|
||||
|
||||
fputstring(symname, f);
|
||||
@@ -319,13 +274,10 @@ 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)
|
||||
{
|
||||
@@ -333,6 +285,7 @@ addsymbol(struct sSymbol * pSym)
|
||||
static ULONG nextID = 0;
|
||||
ULONG hash;
|
||||
|
||||
|
||||
hash = calchash(pSym->tzName);
|
||||
ppPSym = &(tHashedPatchSymbols[hash]);
|
||||
|
||||
@@ -355,13 +308,10 @@ addsymbol(struct sSymbol * pSym)
|
||||
|
||||
return pPSym->ID;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Add all exported symbols to the object
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add all exported symbols to the object
|
||||
*/
|
||||
void
|
||||
addexports(void)
|
||||
{
|
||||
@@ -378,13 +328,10 @@ 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)
|
||||
{
|
||||
@@ -401,13 +348,10 @@ allocpatch(void)
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -445,7 +389,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;
|
||||
@@ -453,15 +400,19 @@ 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;
|
||||
@@ -473,13 +424,10 @@ createpatch(ULONG type, struct Expression * expr)
|
||||
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)
|
||||
{
|
||||
@@ -488,14 +436,11 @@ 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)
|
||||
{
|
||||
@@ -505,32 +450,35 @@ checkcodesection(SLONG size)
|
||||
errx(1, "Section '%s' cannot contain code or data (not a "
|
||||
"ROM0 or ROMX)", pCurrentSection->pzName);
|
||||
}
|
||||
if (pCurrentSection->nPC + size <= MAXSECTIONSIZE) {
|
||||
if (((pCurrentSection->nPC % SECTIONCHUNK) >
|
||||
((pCurrentSection->nPC + size) % SECTIONCHUNK))
|
||||
&& (pCurrentSection->nType == SECT_ROM0
|
||||
|| pCurrentSection->nType == SECT_ROMX)) {
|
||||
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
|
||||
errx(1, "Section '%s' is too big", pCurrentSection->pzName);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Write an objectfile
|
||||
*
|
||||
*/
|
||||
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)
|
||||
{
|
||||
@@ -561,13 +509,10 @@ out_WriteObject(void)
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Prepare for pass #2
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Prepare for pass #2
|
||||
*/
|
||||
void
|
||||
out_PrepPass2(void)
|
||||
{
|
||||
@@ -581,13 +526,10 @@ out_PrepPass2(void)
|
||||
pCurrentSection = NULL;
|
||||
pSectionStack = NULL;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Set the objectfilename
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set the objectfilename
|
||||
*/
|
||||
void
|
||||
out_SetFileName(char *s)
|
||||
{
|
||||
@@ -599,16 +541,12 @@ out_SetFileName(char *s)
|
||||
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;
|
||||
|
||||
@@ -652,13 +590,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)
|
||||
{
|
||||
@@ -668,37 +603,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)
|
||||
{
|
||||
@@ -719,13 +645,10 @@ out_AbsByteGroup(char *s, int length)
|
||||
while (length--)
|
||||
out_AbsByte(*s++);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - OUTPUT.C - Outputs an objectfile
|
||||
*
|
||||
* Skip this many bytes
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Skip this many bytes
|
||||
*/
|
||||
void
|
||||
out_Skip(int skip)
|
||||
{
|
||||
@@ -741,13 +664,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)
|
||||
{
|
||||
@@ -755,12 +675,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
|
||||
@@ -780,13 +698,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)
|
||||
{
|
||||
@@ -800,14 +715,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)
|
||||
{
|
||||
@@ -828,13 +740,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)
|
||||
{
|
||||
@@ -849,14 +758,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)
|
||||
{
|
||||
@@ -879,13 +785,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)
|
||||
{
|
||||
@@ -899,13 +802,10 @@ 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)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dd February 26, 2015
|
||||
.Dt RGBASM 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
@@ -6,9 +6,9 @@
|
||||
.Nd Game Boy assembler
|
||||
.Sh SYNOPSIS
|
||||
.Nm rgbasm
|
||||
.Op Fl v
|
||||
.Op Fl h
|
||||
.Op Fl Ehv
|
||||
.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
|
||||
@@ -23,6 +23,14 @@ 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 E
|
||||
Export all labels, including unreferenced and local labels.
|
||||
.It Fl g Ar chars
|
||||
Change the four characters used for binary constants.
|
||||
The defaults are 0123.
|
||||
@@ -50,7 +58,7 @@ Be verbose.
|
||||
.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
|
||||
@@ -58,10 +66,11 @@ run through
|
||||
and
|
||||
.Xr rgbfix 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbds 7 ,
|
||||
.Xr rgbfix 1 ,
|
||||
.Xr rgblink 1 ,
|
||||
.Xr gbz80 7
|
||||
.Xr rgbds 7
|
||||
.Pp
|
||||
.Lk https://rednex.github.io/rgbds/asm.htm rgbasm assembly commands
|
||||
.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)
|
||||
{
|
||||
@@ -149,14 +114,11 @@ void
|
||||
rpn_Bank(struct Expression * expr, char *tzSym)
|
||||
{
|
||||
if (!sym_isConstant(tzSym)) {
|
||||
struct sSymbol *psym;
|
||||
|
||||
rpn_Reset(expr);
|
||||
|
||||
psym = sym_FindSymbol(tzSym);
|
||||
if (nPass == 2 && psym == NULL) {
|
||||
yyerror("'%s' not defined", tzSym);
|
||||
}
|
||||
/* Check that the symbol exists by evaluating and discarding the value. */
|
||||
sym_GetValue(tzSym);
|
||||
|
||||
expr->isReloc = 1;
|
||||
pushbyte(expr, RPN_BANK);
|
||||
while (*tzSym)
|
||||
@@ -187,6 +149,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)
|
||||
{
|
||||
@@ -350,6 +313,9 @@ rpn_DIV(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
{
|
||||
joinexpr();
|
||||
if (src2->nVal == 0) {
|
||||
fatalerror("division by zero");
|
||||
}
|
||||
expr->nVal = (expr->nVal / src2->nVal);
|
||||
pushbyte(expr, RPN_DIV);
|
||||
}
|
||||
@@ -359,6 +325,9 @@ rpn_MOD(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
{
|
||||
joinexpr();
|
||||
if (src2->nVal == 0) {
|
||||
fatalerror("division by zero");
|
||||
}
|
||||
expr->nVal = (expr->nVal % src2->nVal);
|
||||
pushbyte(expr, RPN_MOD);
|
||||
}
|
||||
|
||||
344
src/asm/symbol.c
344
src/asm/symbol.c
@@ -1,8 +1,5 @@
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable and macroargs stuff
|
||||
*
|
||||
* INCLUDES
|
||||
*
|
||||
* Symboltable and macroargs stuff
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@@ -16,13 +13,6 @@
|
||||
#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;
|
||||
@@ -31,6 +21,7 @@ char *currentmacroargs[MAXMACROARGS + 1];
|
||||
char *newmacroargs[MAXMACROARGS + 1];
|
||||
char SavedTIME[256];
|
||||
char SavedDATE[256];
|
||||
bool exportall;
|
||||
|
||||
SLONG
|
||||
Callback_NARG(struct sSymbol * sym)
|
||||
@@ -44,12 +35,8 @@ Callback_NARG(struct sSymbol * sym)
|
||||
}
|
||||
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Get the nValue field of a symbol
|
||||
*
|
||||
*/
|
||||
|
||||
SLONG
|
||||
getvaluefield(struct sSymbol * sym)
|
||||
{
|
||||
@@ -58,13 +45,10 @@ 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)
|
||||
{
|
||||
@@ -75,13 +59,10 @@ calchash(char *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)
|
||||
{
|
||||
@@ -110,12 +91,8 @@ createsymbol(char *s)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Find a symbol by name and scope
|
||||
*
|
||||
*/
|
||||
|
||||
struct sSymbol *
|
||||
findsymbol(char *s, struct sSymbol * scope)
|
||||
{
|
||||
@@ -134,13 +111,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)
|
||||
{
|
||||
@@ -159,13 +133,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)
|
||||
{
|
||||
@@ -178,13 +149,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)
|
||||
{
|
||||
@@ -212,13 +180,10 @@ sym_Purge(char *tzName)
|
||||
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)
|
||||
{
|
||||
@@ -260,13 +225,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)
|
||||
{
|
||||
@@ -283,13 +245,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)
|
||||
{
|
||||
@@ -303,13 +262,10 @@ sym_GetStringValue(char *tzSym)
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Return a constant symbols value
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return a constant symbols value
|
||||
*/
|
||||
ULONG
|
||||
sym_GetConstantValue(char *s)
|
||||
{
|
||||
@@ -332,13 +288,10 @@ sym_GetConstantValue(char *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)
|
||||
{
|
||||
@@ -374,13 +327,10 @@ sym_GetValue(char *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)
|
||||
{
|
||||
@@ -406,13 +356,10 @@ sym_GetDefinedValue(char *s)
|
||||
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Macro argument stuff
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Macro argument stuff
|
||||
*/
|
||||
void
|
||||
sym_ShiftCurrentMacroArgs(void)
|
||||
{
|
||||
@@ -490,7 +437,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
|
||||
@@ -510,25 +457,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)
|
||||
{
|
||||
@@ -551,13 +492,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)
|
||||
{
|
||||
@@ -580,13 +518,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)
|
||||
{
|
||||
@@ -598,13 +533,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)
|
||||
{
|
||||
@@ -620,13 +552,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)
|
||||
{
|
||||
@@ -647,6 +576,9 @@ sym_AddLocalReloc(char *tzSym)
|
||||
nsym->nValue = nPC;
|
||||
nsym->nType |=
|
||||
SYMF_RELOC | SYMF_LOCAL | SYMF_DEFINED;
|
||||
if (exportall) {
|
||||
nsym->nType |= SYMF_EXPORT;
|
||||
}
|
||||
nsym->pScope = pScope;
|
||||
nsym->pSection = pCurrentSection;
|
||||
}
|
||||
@@ -654,13 +586,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)
|
||||
{
|
||||
@@ -679,20 +608,19 @@ sym_AddReloc(char *tzSym)
|
||||
if (nsym) {
|
||||
nsym->nValue = nPC;
|
||||
nsym->nType |= SYMF_RELOC | SYMF_DEFINED;
|
||||
if (exportall) {
|
||||
nsym->nType |= SYMF_EXPORT;
|
||||
}
|
||||
nsym->pScope = NULL;
|
||||
nsym->pSection = pCurrentSection;
|
||||
}
|
||||
}
|
||||
pScope = findsymbol(tzSym, NULL);
|
||||
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Export a symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Export a symbol
|
||||
*/
|
||||
void
|
||||
sym_Export(char *tzSym)
|
||||
{
|
||||
@@ -716,13 +644,10 @@ sym_Export(char *tzSym)
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Import a symbol
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Import a symbol
|
||||
*/
|
||||
void
|
||||
sym_Import(char *tzSym)
|
||||
{
|
||||
@@ -737,13 +662,10 @@ sym_Import(char *tzSym)
|
||||
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)
|
||||
{
|
||||
@@ -765,13 +687,10 @@ sym_Global(char *tzSym)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Add a macro definition
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Add a macro definition
|
||||
*/
|
||||
void
|
||||
sym_AddMacro(char *tzSym)
|
||||
{
|
||||
@@ -796,25 +715,26 @@ sym_AddMacro(char *tzSym)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Prepare for pass #1
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set whether to export all relocable symbols by default
|
||||
*/
|
||||
void sym_SetExportAll(BBOOL set) {
|
||||
exportall = set;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
@@ -845,14 +765,13 @@ sym_PrepPass2(void)
|
||||
sym_AddEqu("_NARG", 0);
|
||||
p_NARGSymbol = findsymbol("_NARG", NULL);
|
||||
p_NARGSymbol->Callback = Callback_NARG;
|
||||
}
|
||||
/*
|
||||
* RGBAsm - SYMBOL.C - Symboltable stuff
|
||||
*
|
||||
* Initialise the symboltable
|
||||
*
|
||||
*/
|
||||
|
||||
math_DefinePI();
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the symboltable
|
||||
*/
|
||||
void
|
||||
sym_Init(void)
|
||||
{
|
||||
@@ -889,72 +808,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]);
|
||||
}
|
||||
|
||||
8
src/extern/err.c
vendored
8
src/extern/err.c
vendored
@@ -26,13 +26,11 @@
|
||||
#include <stdlib.h>
|
||||
#include "extern/err.h"
|
||||
|
||||
#ifndef __MINGW32__
|
||||
char *__progname;
|
||||
#endif
|
||||
extern char *progname;
|
||||
|
||||
void rgbds_vwarn(const char *fmt, va_list ap)
|
||||
{
|
||||
fprintf (stderr, "%s: ", __progname);
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
if (fmt) {
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputs (": ", stderr);
|
||||
@@ -42,7 +40,7 @@ void rgbds_vwarn(const char *fmt, va_list ap)
|
||||
|
||||
void rgbds_vwarnx(const char *fmt, va_list ap)
|
||||
{
|
||||
fprintf (stderr, "%s: ", __progname);
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
if (fmt) vfprintf(stderr, fmt, ap);
|
||||
putc('\n', stderr);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
48
src/extern/strlcat.c
vendored
48
src/extern/strlcat.c
vendored
@@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
|
||||
/* $OpenBSD: strlcat.c,v 1.14 2015/01/15 03:54:12 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* 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
|
||||
@@ -20,36 +20,36 @@
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
||||
* full size of dst, not space left). At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
||||
* If retval >= siz, truncation occurred.
|
||||
* 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 siz)
|
||||
rgbds_strlcat(char *dst, const char *src, size_t dsize)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
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 && *d != '\0')
|
||||
d++;
|
||||
dlen = d - dst;
|
||||
n = siz - 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(s));
|
||||
while (*s != '\0') {
|
||||
if (n != 1) {
|
||||
*d++ = *s;
|
||||
if (n-- == 0)
|
||||
return(dlen + strlen(src));
|
||||
while (*src != '\0') {
|
||||
if (n != 0) {
|
||||
*dst++ = *src;
|
||||
n--;
|
||||
}
|
||||
s++;
|
||||
src++;
|
||||
}
|
||||
*d = '\0';
|
||||
*dst = '\0';
|
||||
|
||||
return(dlen + (s - src)); /* count does not include NUL */
|
||||
return(dlen + (src - osrc)); /* count does not include NUL */
|
||||
}
|
||||
|
||||
37
src/extern/strlcpy.c
vendored
37
src/extern/strlcpy.c
vendored
@@ -1,7 +1,7 @@
|
||||
/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
|
||||
/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* 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
|
||||
@@ -20,32 +20,31 @@
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* Copy src to string dst of size siz. At most siz-1 characters
|
||||
* will be copied. Always NUL terminates (unless siz == 0).
|
||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
||||
* 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 siz)
|
||||
rgbds_strlcpy(char *dst, const char *src, size_t dsize)
|
||||
{
|
||||
char *d = dst;
|
||||
const char *s = src;
|
||||
size_t n = siz;
|
||||
const char *osrc = src;
|
||||
size_t nleft = dsize;
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0) {
|
||||
while (--n != 0) {
|
||||
if ((*d++ = *s++) == '\0')
|
||||
/* 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 (n == 0) {
|
||||
if (siz != 0)
|
||||
*d = '\0'; /* NUL-terminate dst */
|
||||
while (*s++)
|
||||
/* 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(s - src - 1); /* count does not include NUL */
|
||||
return(src - osrc - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
@@ -23,13 +23,15 @@
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -40,17 +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) {
|
||||
err(1, "Error opening file %s", argv[argc - 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) {
|
||||
@@ -197,6 +190,20 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
@@ -350,7 +357,8 @@ 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);
|
||||
|
||||
@@ -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,11 +93,11 @@ 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.
|
||||
@@ -109,7 +109,7 @@ It is a good idea to pad the image to a valid size as well
|
||||
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,19 +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 rgblink 1 ,
|
||||
.Xr gbz80 7
|
||||
.Xr rgbds 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally released by Carsten S\(/orensen as a standalone program called
|
||||
|
||||
203
src/gfx/gb.c
Normal file
203
src/gfx/gb.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "gfx/main.h"
|
||||
|
||||
void
|
||||
transpose_tiles(struct GBImage *gb, int width)
|
||||
{
|
||||
uint8_t *newdata;
|
||||
int i;
|
||||
int newbyte;
|
||||
|
||||
newdata = calloc(gb->size, 1);
|
||||
for (i = 0; i < gb->size; i++) {
|
||||
newbyte = i / (8 * depth) * width * 8 * depth;
|
||||
newbyte = newbyte % gb->size + 8 * depth * (newbyte / gb->size) + i % (8 * depth);
|
||||
newdata[newbyte] = gb->data[i];
|
||||
}
|
||||
|
||||
free(gb->data);
|
||||
|
||||
gb->data = newdata;
|
||||
}
|
||||
|
||||
void
|
||||
png_to_gb(struct PNGImage png, struct GBImage *gb)
|
||||
{
|
||||
int x, y, byte;
|
||||
png_byte index;
|
||||
|
||||
for (y = 0; y < png.height; y++) {
|
||||
for (x = 0; x < png.width; x++) {
|
||||
index = png.data[y][x];
|
||||
index &= (1 << depth) - 1;
|
||||
|
||||
if (!gb->horizontal) {
|
||||
byte = y * depth + x / 8 * png.height / 8 * 8 * depth;
|
||||
} else {
|
||||
byte = y * depth + x / 8 * png.height / 8 * 8 * depth;
|
||||
}
|
||||
gb->data[byte] |= (index & 1) << (7 - x % 8);
|
||||
if (depth == 2) {
|
||||
gb->data[byte + 1] |= (index >> 1) << (7 - x % 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!gb->horizontal) {
|
||||
transpose_tiles(gb, png.width / 8);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
output_file(struct Options opts, struct GBImage gb)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = fopen(opts.outfile, "wb");
|
||||
if (!f) {
|
||||
err(1, "Opening output file '%s' failed", opts.outfile);
|
||||
}
|
||||
fwrite(gb.data, 1, gb.size - gb.trim * 8 * depth, f);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
int
|
||||
get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles, int tile_size)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < num_tiles; i++) {
|
||||
for (j = 0; j < tile_size; j++) {
|
||||
if (tile[j] != tiles[i][j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j >= tile_size) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
create_tilemap(struct Options opts, struct GBImage *gb, struct Tilemap *tilemap)
|
||||
{
|
||||
int i, j;
|
||||
int gb_i;
|
||||
int tile_size;
|
||||
int max_tiles;
|
||||
int num_tiles;
|
||||
int index;
|
||||
int gb_size;
|
||||
uint8_t *tile;
|
||||
uint8_t **tiles;
|
||||
|
||||
tile_size = sizeof(uint8_t) * depth * 8;
|
||||
gb_size = gb->size - (gb->trim * tile_size);
|
||||
max_tiles = gb_size / tile_size;
|
||||
tiles = malloc(sizeof(uint8_t*) * max_tiles);
|
||||
num_tiles = 0;
|
||||
|
||||
tilemap->data = malloc(sizeof(uint8_t) * max_tiles);
|
||||
tilemap->size = 0;
|
||||
|
||||
gb_i = 0;
|
||||
while (gb_i < gb_size) {
|
||||
tile = malloc(tile_size);
|
||||
for (i = 0; i < tile_size; i++) {
|
||||
tile[i] = gb->data[gb_i];
|
||||
gb_i++;
|
||||
}
|
||||
if (opts.unique) {
|
||||
index = get_tile_index(tile, tiles, num_tiles, tile_size);
|
||||
if (index < 0) {
|
||||
index = num_tiles;
|
||||
tiles[num_tiles] = tile;
|
||||
num_tiles++;
|
||||
}
|
||||
} else {
|
||||
index = num_tiles;
|
||||
tiles[num_tiles] = tile;
|
||||
num_tiles++;
|
||||
}
|
||||
tilemap->data[tilemap->size] = index;
|
||||
tilemap->size++;
|
||||
}
|
||||
|
||||
if (opts.unique) {
|
||||
free(gb->data);
|
||||
gb->data = malloc(tile_size * num_tiles);
|
||||
for (i = 0; i < num_tiles; i++) {
|
||||
tile = tiles[i];
|
||||
for (j = 0; j < tile_size; j++) {
|
||||
gb->data[i * tile_size + j] = tile[j];
|
||||
}
|
||||
}
|
||||
gb->size = i * tile_size;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_tiles; i++) {
|
||||
free(tiles[i]);
|
||||
}
|
||||
free(tiles);
|
||||
}
|
||||
|
||||
void
|
||||
output_tilemap_file(struct Options opts, struct Tilemap tilemap)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = fopen(opts.mapfile, "wb");
|
||||
if (!f) {
|
||||
err(1, "Opening tilemap file '%s' failed", opts.mapfile);
|
||||
}
|
||||
|
||||
fwrite(tilemap.data, 1, tilemap.size, f);
|
||||
fclose(f);
|
||||
|
||||
if (opts.mapout) {
|
||||
free(opts.mapfile);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
output_palette_file(struct Options opts, struct PNGImage png)
|
||||
{
|
||||
FILE *f;
|
||||
int i, colors, color;
|
||||
png_color *palette;
|
||||
|
||||
if (png_get_PLTE(png.png, png.info, &palette, &colors)) {
|
||||
f = fopen(opts.palfile, "wb");
|
||||
if (!f) {
|
||||
err(1, "Opening palette file '%s' failed", opts.palfile);
|
||||
}
|
||||
for (i = 0; i < colors; i++) {
|
||||
color = palette[i].blue >> 3 << 10 | palette[i].green >> 3 << 5 | palette[i].red >> 3;
|
||||
fwrite(&color, 2, 1, f);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (opts.palout) {
|
||||
free(opts.palfile);
|
||||
}
|
||||
}
|
||||
255
src/gfx/main.c
Normal file
255
src/gfx/main.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* 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 <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "gfx/main.h"
|
||||
|
||||
char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf(
|
||||
"usage: rgbgfx [-DFfhPTuv] [-d #] [-o outfile] [-p palfile] [-t mapfile]\n"
|
||||
"[-x #] infile\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int ch, size;
|
||||
struct Options opts = {0};
|
||||
struct PNGImage png = {0};
|
||||
struct GBImage gb = {0};
|
||||
struct Tilemap tilemap = {0};
|
||||
char *ext;
|
||||
const char *errmsg = "Warning: The PNG's %s setting is not the same as the setting defined on the command line.";
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (argc == 1) {
|
||||
usage();
|
||||
}
|
||||
|
||||
opts.mapfile = "";
|
||||
opts.palfile = "";
|
||||
opts.outfile = "";
|
||||
|
||||
depth = 2;
|
||||
|
||||
while((ch = getopt(argc, argv, "DvFfd:hx:Tt:uPp:o:")) != -1) {
|
||||
switch(ch) {
|
||||
case 'D':
|
||||
opts.debug = true;
|
||||
break;
|
||||
case 'v':
|
||||
opts.verbose = true;
|
||||
break;
|
||||
case 'F':
|
||||
opts.hardfix = true;
|
||||
case 'f':
|
||||
opts.fix = true;
|
||||
break;
|
||||
case 'd':
|
||||
depth = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'h':
|
||||
opts.horizontal = true;
|
||||
break;
|
||||
case 'x':
|
||||
opts.trim = strtoul(optarg, NULL, 0);
|
||||
break;
|
||||
case 'T':
|
||||
opts.mapout = true;
|
||||
break;
|
||||
case 't':
|
||||
opts.mapfile = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
opts.unique = true;
|
||||
break;
|
||||
case 'P':
|
||||
opts.palout = true;
|
||||
break;
|
||||
case 'p':
|
||||
opts.palfile = optarg;
|
||||
break;
|
||||
case 'o':
|
||||
opts.outfile = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0) {
|
||||
usage();
|
||||
}
|
||||
|
||||
opts.infile = argv[argc - 1];
|
||||
|
||||
if (depth != 1 && depth != 2) {
|
||||
errx(1, "Depth option must be either 1 or 2.");
|
||||
}
|
||||
colors = 1 << depth;
|
||||
|
||||
input_png_file(opts, &png);
|
||||
|
||||
png.mapfile = "";
|
||||
png.palfile = "";
|
||||
|
||||
get_text(&png);
|
||||
|
||||
if (png.horizontal != opts.horizontal) {
|
||||
if (opts.verbose) {
|
||||
warnx(errmsg, "horizontal");
|
||||
}
|
||||
if (opts.hardfix) {
|
||||
png.horizontal = opts.horizontal;
|
||||
}
|
||||
}
|
||||
if (png.horizontal) {
|
||||
opts.horizontal = png.horizontal;
|
||||
}
|
||||
|
||||
if (png.trim != opts.trim) {
|
||||
if (opts.verbose) {
|
||||
warnx(errmsg, "trim");
|
||||
}
|
||||
if (opts.hardfix) {
|
||||
png.trim = opts.trim;
|
||||
}
|
||||
}
|
||||
if (png.trim) {
|
||||
opts.trim = png.trim;
|
||||
}
|
||||
if (opts.trim > png.width / 8 - 1) {
|
||||
errx(1, "Trim (%i) for input png file '%s' too large (max: %i)", opts.trim, opts.infile, png.width / 8 - 1);
|
||||
}
|
||||
|
||||
if (strcmp(png.mapfile, opts.mapfile) != 0) {
|
||||
if (opts.verbose) {
|
||||
warnx(errmsg, "tilemap file");
|
||||
}
|
||||
if (opts.hardfix) {
|
||||
png.mapfile = opts.mapfile;
|
||||
}
|
||||
}
|
||||
if (!*opts.mapfile) {
|
||||
opts.mapfile = png.mapfile;
|
||||
}
|
||||
|
||||
if (png.mapout != opts.mapout) {
|
||||
if (opts.verbose) {
|
||||
warnx(errmsg, "tilemap file");
|
||||
}
|
||||
if (opts.hardfix) {
|
||||
png.mapout = opts.mapout;
|
||||
}
|
||||
}
|
||||
if (png.mapout) {
|
||||
opts.mapout = png.mapout;
|
||||
}
|
||||
|
||||
if (strcmp(png.palfile, opts.palfile) != 0) {
|
||||
if (opts.verbose) {
|
||||
warnx(errmsg, "palette file");
|
||||
}
|
||||
if (opts.hardfix) {
|
||||
png.palfile = opts.palfile;
|
||||
}
|
||||
}
|
||||
if (!*opts.palfile) {
|
||||
opts.palfile = png.palfile;
|
||||
}
|
||||
|
||||
if (png.palout != opts.palout) {
|
||||
if (opts.verbose) {
|
||||
warnx(errmsg, "palette file");
|
||||
}
|
||||
if (opts.hardfix) {
|
||||
png.palout = opts.palout;
|
||||
}
|
||||
}
|
||||
if (png.palout) {
|
||||
opts.palout = png.palout;
|
||||
}
|
||||
|
||||
if (!*opts.mapfile && opts.mapout) {
|
||||
if ((ext = strrchr(opts.infile, '.')) != NULL) {
|
||||
size = ext - opts.infile + 9;
|
||||
opts.mapfile = malloc(size);
|
||||
strncpy(opts.mapfile, opts.infile, size);
|
||||
*strrchr(opts.mapfile, '.') = '\0';
|
||||
strcat(opts.mapfile, ".tilemap");
|
||||
} else {
|
||||
opts.mapfile = malloc(strlen(opts.infile) + 9);
|
||||
strcpy(opts.mapfile, opts.infile);
|
||||
strcat(opts.mapfile, ".tilemap");
|
||||
}
|
||||
}
|
||||
|
||||
if (!*opts.palfile && opts.palout) {
|
||||
if ((ext = strrchr(opts.infile, '.')) != NULL) {
|
||||
size = ext - opts.infile + 5;
|
||||
opts.palfile = malloc(size);
|
||||
strncpy(opts.palfile, opts.infile, size);
|
||||
*strrchr(opts.palfile, '.') = '\0';
|
||||
strcat(opts.palfile, ".pal");
|
||||
} else {
|
||||
opts.palfile = malloc(strlen(opts.infile) + 5);
|
||||
strcpy(opts.palfile, opts.infile);
|
||||
strcat(opts.palfile, ".pal");
|
||||
}
|
||||
}
|
||||
|
||||
gb.size = png.width * png.height * depth / 8;
|
||||
gb.data = calloc(gb.size, 1);
|
||||
gb.trim = opts.trim;
|
||||
gb.horizontal = opts.horizontal;
|
||||
|
||||
if (*opts.outfile || *opts.mapfile) {
|
||||
png_to_gb(png, &gb);
|
||||
create_tilemap(opts, &gb, &tilemap);
|
||||
}
|
||||
|
||||
if (*opts.outfile) {
|
||||
output_file(opts, gb);
|
||||
}
|
||||
|
||||
if (*opts.mapfile) {
|
||||
output_tilemap_file(opts, tilemap);
|
||||
}
|
||||
|
||||
if (*opts.palfile) {
|
||||
output_palette_file(opts, png);
|
||||
}
|
||||
|
||||
if (opts.fix || opts.debug) {
|
||||
set_text(&png);
|
||||
output_png_file(opts, &png);
|
||||
}
|
||||
|
||||
free_png_data(&png);
|
||||
free(gb.data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
339
src/gfx/makepng.c
Normal file
339
src/gfx/makepng.c
Normal file
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* 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 <string.h>
|
||||
#include "gfx/main.h"
|
||||
|
||||
void
|
||||
input_png_file(struct Options opts, struct PNGImage *img)
|
||||
{
|
||||
FILE *f;
|
||||
int i, y, num_trans;
|
||||
bool has_palette = false;
|
||||
png_byte *trans_alpha;
|
||||
png_color_16 *trans_values;
|
||||
bool *full_alpha;
|
||||
png_color *palette;
|
||||
|
||||
f = fopen(opts.infile, "rb");
|
||||
if (!f) {
|
||||
err(1, "Opening input png file '%s' failed", opts.infile);
|
||||
}
|
||||
|
||||
img->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!img->png) {
|
||||
errx(1, "Creating png structure failed");
|
||||
}
|
||||
|
||||
img->info = png_create_info_struct(img->png);
|
||||
if (!img->info) {
|
||||
errx(1, "Creating png info structure failed");
|
||||
}
|
||||
|
||||
/* Better error handling here? */
|
||||
if (setjmp(png_jmpbuf(img->png))) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
png_init_io(img->png, f);
|
||||
|
||||
png_read_info(img->png, img->info);
|
||||
|
||||
img->width = png_get_image_width(img->png, img->info);
|
||||
img->height = png_get_image_height(img->png, img->info);
|
||||
img->depth = png_get_bit_depth(img->png, img->info);
|
||||
img->type = png_get_color_type(img->png, img->info);
|
||||
|
||||
if (img->type & PNG_COLOR_MASK_ALPHA) {
|
||||
png_set_strip_alpha(img->png);
|
||||
}
|
||||
|
||||
if (img->depth != depth) {
|
||||
if (opts.verbose) {
|
||||
warnx("Image bit depth is not %i (is %i).", depth,
|
||||
img->depth);
|
||||
}
|
||||
}
|
||||
|
||||
if (img->type == PNG_COLOR_TYPE_GRAY) {
|
||||
if (img->depth < 8) {
|
||||
png_set_expand_gray_1_2_4_to_8(img->png);
|
||||
}
|
||||
png_set_gray_to_rgb(img->png);
|
||||
} else {
|
||||
if (img->depth < 8) {
|
||||
png_set_expand_gray_1_2_4_to_8(img->png);
|
||||
}
|
||||
has_palette = png_get_PLTE(img->png, img->info, &palette,
|
||||
&colors);
|
||||
}
|
||||
|
||||
if (png_get_tRNS(img->png, img->info, &trans_alpha, &num_trans,
|
||||
&trans_values)) {
|
||||
if (img->type == PNG_COLOR_TYPE_PALETTE) {
|
||||
full_alpha = malloc(sizeof(bool) * num_trans);
|
||||
|
||||
for (i = 0; i < num_trans; i++) {
|
||||
if (trans_alpha[i] > 0) {
|
||||
full_alpha[i] = false;
|
||||
} else {
|
||||
full_alpha[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < num_trans; i++) {
|
||||
if (full_alpha[i]) {
|
||||
palette[i].red = 0xFF;
|
||||
palette[i].green = 0x00;
|
||||
palette[i].blue = 0xFF;
|
||||
/*
|
||||
* Set to the lightest color in the
|
||||
* palette.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
free(full_alpha);
|
||||
} else {
|
||||
/* Set to the lightest color in the image. */
|
||||
}
|
||||
|
||||
png_free_data(img->png, img->info, PNG_FREE_TRNS, -1);
|
||||
}
|
||||
|
||||
if (has_palette) {
|
||||
/* Make sure palette only has the amount of colors you want. */
|
||||
} else {
|
||||
/*
|
||||
* Eventually when this copies colors from the image itself,
|
||||
* make sure order is lightest to darkest.
|
||||
*/
|
||||
palette = malloc(sizeof(png_color) * colors);
|
||||
|
||||
if (strcmp(opts.infile, "rgb.png") == 0) {
|
||||
palette[0].red = 0xFF;
|
||||
palette[0].green = 0xEF;
|
||||
palette[0].blue = 0xFF;
|
||||
|
||||
palette[1].red = 0xF7;
|
||||
palette[1].green = 0xF7;
|
||||
palette[1].blue = 0x8C;
|
||||
|
||||
palette[2].red = 0x94;
|
||||
palette[2].green = 0x94;
|
||||
palette[2].blue = 0xC6;
|
||||
|
||||
palette[3].red = 0x39;
|
||||
palette[3].green = 0x39;
|
||||
palette[3].blue = 0x84;
|
||||
} else {
|
||||
palette[0].red = 0xFF;
|
||||
palette[0].green = 0xFF;
|
||||
palette[0].blue = 0xFF;
|
||||
|
||||
palette[1].red = 0xA9;
|
||||
palette[1].green = 0xA9;
|
||||
palette[1].blue = 0xA9;
|
||||
|
||||
palette[2].red = 0x55;
|
||||
palette[2].green = 0x55;
|
||||
palette[2].blue = 0x55;
|
||||
|
||||
palette[3].red = 0x00;
|
||||
palette[3].green = 0x00;
|
||||
palette[3].blue = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Also unfortunately, this sets it at 8 bit, and I can't find any
|
||||
* option to reduce to 2 or 1 bit.
|
||||
*/
|
||||
#if PNG_LIBPNG_VER < 10402
|
||||
png_set_dither(img->png, palette, colors, colors, NULL, 1);
|
||||
#else
|
||||
png_set_quantize(img->png, palette, colors, colors, NULL, 1);
|
||||
#endif
|
||||
|
||||
if (!has_palette) {
|
||||
png_set_PLTE(img->png, img->info, palette, colors);
|
||||
free(palette);
|
||||
}
|
||||
|
||||
/*
|
||||
* If other useless chunks exist (sRGB, bKGD, pHYs, gAMA, cHRM, iCCP,
|
||||
* etc.) offer to remove?
|
||||
*/
|
||||
|
||||
png_read_update_info(img->png, img->info);
|
||||
|
||||
img->data = malloc(sizeof(png_byte *) * img->height);
|
||||
for (y = 0; y < img->height; y++) {
|
||||
img->data[y] = malloc(png_get_rowbytes(img->png, img->info));
|
||||
}
|
||||
|
||||
png_read_image(img->png, img->data);
|
||||
png_read_end(img->png, img->info);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void
|
||||
get_text(struct PNGImage *png)
|
||||
{
|
||||
png_text *text;
|
||||
int i, numtxts, numremoved;
|
||||
|
||||
png_get_text(png->png, png->info, &text, &numtxts);
|
||||
for (i = 0; i < numtxts; i++) {
|
||||
if (strcmp(text[i].key, "h") == 0 && !*text[i].text) {
|
||||
png->horizontal = true;
|
||||
png_free_data(png->png, png->info, PNG_FREE_TEXT, i);
|
||||
} else if (strcmp(text[i].key, "x") == 0) {
|
||||
png->trim = strtoul(text[i].text, NULL, 0);
|
||||
png_free_data(png->png, png->info, PNG_FREE_TEXT, i);
|
||||
} else if (strcmp(text[i].key, "t") == 0) {
|
||||
png->mapfile = text[i].text;
|
||||
png_free_data(png->png, png->info, PNG_FREE_TEXT, i);
|
||||
} else if (strcmp(text[i].key, "T") == 0 && !*text[i].text) {
|
||||
png->mapout = true;
|
||||
png_free_data(png->png, png->info, PNG_FREE_TEXT, i);
|
||||
} else if (strcmp(text[i].key, "p") == 0) {
|
||||
png->palfile = text[i].text;
|
||||
png_free_data(png->png, png->info, PNG_FREE_TEXT, i);
|
||||
} else if (strcmp(text[i].key, "P") == 0 && !*text[i].text) {
|
||||
png->palout = true;
|
||||
png_free_data(png->png, png->info, PNG_FREE_TEXT, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Remove this and simply change the warning function not to warn instead. */
|
||||
for (i = 0, numremoved = 0; i < numtxts; i++) {
|
||||
if (text[i].key == NULL) {
|
||||
numremoved++;
|
||||
}
|
||||
text[i].key = text[i + numremoved].key;
|
||||
text[i].text = text[i + numremoved].text;
|
||||
text[i].compression = text[i + numremoved].compression;
|
||||
}
|
||||
png_set_text(png->png, png->info, text, numtxts - numremoved);
|
||||
}
|
||||
|
||||
void
|
||||
set_text(struct PNGImage *png)
|
||||
{
|
||||
png_text *text;
|
||||
char buffer[3];
|
||||
|
||||
text = malloc(sizeof(png_text));
|
||||
|
||||
if (png->horizontal) {
|
||||
text[0].key = "h";
|
||||
text[0].text = "";
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
png_set_text(png->png, png->info, text, 1);
|
||||
}
|
||||
if (png->trim) {
|
||||
text[0].key = "x";
|
||||
snprintf(buffer, 3, "%d", png->trim);
|
||||
text[0].text = buffer;
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
png_set_text(png->png, png->info, text, 1);
|
||||
}
|
||||
if (*png->mapfile) {
|
||||
text[0].key = "t";
|
||||
text[0].text = "";
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
png_set_text(png->png, png->info, text, 1);
|
||||
}
|
||||
if (png->mapout) {
|
||||
text[0].key = "T";
|
||||
text[0].text = "";
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
png_set_text(png->png, png->info, text, 1);
|
||||
}
|
||||
if (*png->palfile) {
|
||||
text[0].key = "p";
|
||||
text[0].text = "";
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
png_set_text(png->png, png->info, text, 1);
|
||||
}
|
||||
if (png->palout) {
|
||||
text[0].key = "P";
|
||||
text[0].text = "";
|
||||
text[0].compression = PNG_TEXT_COMPRESSION_NONE;
|
||||
png_set_text(png->png, png->info, text, 1);
|
||||
}
|
||||
|
||||
free(text);
|
||||
}
|
||||
|
||||
void
|
||||
output_png_file(struct Options opts, struct PNGImage *png)
|
||||
{
|
||||
FILE *f;
|
||||
char *outfile;
|
||||
png_struct *img;
|
||||
|
||||
/* Variable outfile is for debugging purposes. Eventually, opts.infile will be used directly. */
|
||||
if (opts.debug) {
|
||||
outfile = malloc(strlen(opts.infile) + 5);
|
||||
strcpy(outfile, opts.infile);
|
||||
strcat(outfile, ".out");
|
||||
} else {
|
||||
outfile = opts.infile;
|
||||
}
|
||||
|
||||
f = fopen(outfile, "wb");
|
||||
if (!f) {
|
||||
err(1, "Opening output png file '%s' failed", outfile);
|
||||
}
|
||||
|
||||
img = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!img) {
|
||||
errx(1, "Creating png structure failed");
|
||||
}
|
||||
|
||||
/* Better error handling here? */
|
||||
if (setjmp(png_jmpbuf(img))) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
png_init_io(img, f);
|
||||
|
||||
png_write_info(img, png->info);
|
||||
|
||||
png_write_image(img, png->data);
|
||||
png_write_end(img, NULL);
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (opts.debug) {
|
||||
free(outfile);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free_png_data(struct PNGImage *png)
|
||||
{
|
||||
int y;
|
||||
|
||||
for (y = 0; y < png->height; y++) {
|
||||
free(png->data[y]);
|
||||
}
|
||||
free(png->data);
|
||||
}
|
||||
90
src/gfx/rgbgfx.1
Normal file
90
src/gfx/rgbgfx.1
Normal file
@@ -0,0 +1,90 @@
|
||||
.Dd $Mdocdate$
|
||||
.Dt RGBGFX 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
.Nm rgbgfx
|
||||
.Nd Game Boy graphics converter
|
||||
.Sh SYNOPSIS
|
||||
.Nm rgbgfx
|
||||
.Op Fl DfFhPTv
|
||||
.Op Fl o Ar outfile
|
||||
.Op Fl d Ar depth
|
||||
.Op Fl p Ar palfile
|
||||
.Op Fl t Ar mapfile
|
||||
.Op Fl x Ar tiles
|
||||
.Ar file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
program converts PNG images into the Nintendo Game Boy's planar tile format.
|
||||
The arguments are as follows:
|
||||
.Bl -tag -width Ds
|
||||
.It Fl D
|
||||
Debug features are enabled.
|
||||
.It Fl f
|
||||
Fix the input PNG file to be a correctly indexed image.
|
||||
.It Fl F
|
||||
Same as
|
||||
.Fl f ,
|
||||
but additionally, the input PNG file is fixed to have its parameters match the
|
||||
command line's parameters.
|
||||
.It Fl d Ar depth
|
||||
The bitdepth of the output image (either 1 or 2).
|
||||
By default, the bitdepth is 2 (two bits per pixel).
|
||||
.It Fl h
|
||||
Lay out tiles horizontally rather than vertically.
|
||||
.It Fl o Ar outfile
|
||||
The name of the output file.
|
||||
.It Fl p Ar palfile
|
||||
Raw bytes (8 bytes for two bits per pixel, 4 bytes for one bit per pixel)
|
||||
containing the RGB15 values in the little-endian byte order and then ordered
|
||||
from lightest to darkest.
|
||||
.It Fl P
|
||||
Same as
|
||||
.Fl p ,
|
||||
but the pallete file output name is made by taking the input filename,
|
||||
removing the file extension, and appending
|
||||
.Pa .pal .
|
||||
.It Fl t Ar mapfile
|
||||
If any tiles are the same, don't place the repeat tiles in the output file, and
|
||||
make a tilemap file.
|
||||
.It Fl T
|
||||
Same as
|
||||
.Fl t ,
|
||||
but the tilemap file output name is made by taking the input filename,
|
||||
removing the file extension, and appending
|
||||
.Pa .tilemap .
|
||||
.It Fl u
|
||||
Truncate repeated tiles. Useful with tilemaps.
|
||||
.It Fl v
|
||||
Verbose.
|
||||
Print errors when the command line parameters and the parameters in
|
||||
the PNG file don't match.
|
||||
.It Fl x Ar tiles
|
||||
Trim the end of the output file by this many tiles.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The following will take a PNG file with a bitdepth of 1, 2, or 8, and output
|
||||
planar 2bpp data:
|
||||
.Pp
|
||||
.D1 $ rgbgfx -o out.2bpp in.png
|
||||
.Pp
|
||||
The following creates a planar 2bpp file with only unique tiles, and its tilemap
|
||||
.Pa out.tilemap :
|
||||
.Pp
|
||||
.D1 $ rgbgfx -T -u -o out.2bpp in.png
|
||||
.Pp
|
||||
The following will do nothing:
|
||||
.Pp
|
||||
.D1 $ rgbgfx in.png
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbds 7 ,
|
||||
.Xr rgbasm 1 ,
|
||||
.Xr rgblink 1 ,
|
||||
.Xr rgbfix 1 ,
|
||||
.Xr gbz80 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was created by
|
||||
.An stag019
|
||||
to be included in RGBDS.
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/mylink.h"
|
||||
@@ -13,6 +14,14 @@ struct sFreeArea {
|
||||
struct sFreeArea *pPrev, *pNext;
|
||||
};
|
||||
|
||||
struct sSectionAttributes {
|
||||
const char *name;
|
||||
SLONG bank;
|
||||
SLONG offset; // bank + offset = bank originally stored in a section struct
|
||||
SLONG minBank;
|
||||
SLONG bankCount;
|
||||
};
|
||||
|
||||
struct sFreeArea *BankFree[MAXBANKS];
|
||||
SLONG MaxAvail[MAXBANKS];
|
||||
SLONG MaxBankUsed;
|
||||
@@ -20,11 +29,37 @@ SLONG MaxWBankUsed;
|
||||
SLONG MaxSBankUsed;
|
||||
SLONG MaxVBankUsed;
|
||||
|
||||
#define DOMAXBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
|
||||
const enum eSectionType SECT_MIN = SECT_WRAM0;
|
||||
const enum eSectionType SECT_MAX = SECT_SRAM;
|
||||
const struct sSectionAttributes SECT_ATTRIBUTES[] = {
|
||||
{"WRAM0", BANK_WRAM0, 0, 0, BANK_COUNT_WRAM0},
|
||||
{"VRAM", BANK_VRAM, 0, 0, BANK_COUNT_VRAM},
|
||||
{"ROMX", BANK_ROMX, -1, 1, BANK_COUNT_ROMX},
|
||||
{"ROM0", BANK_ROM0, 0, 0, BANK_COUNT_ROM0},
|
||||
{"HRAM", BANK_HRAM, 0, 0, BANK_COUNT_HRAM},
|
||||
{"WRAMX", BANK_WRAMX, 0, 0, BANK_COUNT_WRAMX},
|
||||
{"SRAM", BANK_SRAM, 0, 0, BANK_COUNT_SRAM}
|
||||
};
|
||||
|
||||
#define DOMAXBANK(x, y) {switch (x) { \
|
||||
case SECT_ROMX: DOMAXRBANK(y); break; \
|
||||
case SECT_WRAMX: DOMAXWBANK(y); break; \
|
||||
case SECT_SRAM: DOMAXSBANK(y); break; \
|
||||
case SECT_VRAM: DOMAXVBANK(y); break; \
|
||||
default: errx(1, "DOMAXBANK used with invalid parameters"); break; }}
|
||||
#define DOMAXRBANK(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);}
|
||||
|
||||
void
|
||||
ensureSectionTypeIsValid(enum eSectionType type)
|
||||
{
|
||||
if (type < SECT_MIN || type > SECT_MAX) {
|
||||
errx(1, "(INTERNAL) Invalid section type found.");
|
||||
}
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_Avail(SLONG bank)
|
||||
{
|
||||
@@ -54,12 +89,12 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
||||
if (org == pArea->nOrg) {
|
||||
pArea->nOrg += size;
|
||||
pArea->nSize -= size;
|
||||
return (org);
|
||||
return 0;
|
||||
} else {
|
||||
if ((org + size - 1) ==
|
||||
(pArea->nOrg + pArea->nSize - 1)) {
|
||||
pArea->nSize -= size;
|
||||
return (org);
|
||||
return 0;
|
||||
} else {
|
||||
struct sFreeArea *pNewArea;
|
||||
|
||||
@@ -75,7 +110,7 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
||||
pNewArea->nSize -=
|
||||
size + pArea->nSize;
|
||||
|
||||
return (org);
|
||||
return 0;
|
||||
} else {
|
||||
err(1, NULL);
|
||||
}
|
||||
@@ -86,62 +121,26 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
|
||||
pArea = *ppArea;
|
||||
}
|
||||
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocAbsSRAMAnyBank(SLONG org, SLONG size)
|
||||
area_AllocAbsAnyBank(SLONG org, SLONG size, enum eSectionType type)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
if (area_AllocAbs(&BankFree[BANK_SRAM + i], org, size) == org) {
|
||||
return BANK_SRAM + i;
|
||||
ensureSectionTypeIsValid(type);
|
||||
|
||||
SLONG startBank = SECT_ATTRIBUTES[type].bank;
|
||||
SLONG bankCount = SECT_ATTRIBUTES[type].bankCount;
|
||||
|
||||
for (int i = 0; i < bankCount; i++) {
|
||||
if (area_AllocAbs(&BankFree[startBank + i], org, size) != -1) {
|
||||
return startBank + i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocAbsWRAMAnyBank(SLONG org, SLONG size)
|
||||
{
|
||||
SLONG i;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_Alloc(struct sFreeArea ** ppArea, SLONG size)
|
||||
{
|
||||
@@ -166,67 +165,31 @@ area_Alloc(struct sFreeArea ** ppArea, SLONG size)
|
||||
}
|
||||
|
||||
SLONG
|
||||
area_AllocVRAMAnyBank(SLONG size)
|
||||
{
|
||||
SLONG i, org;
|
||||
area_AllocAnyBank(SLONG size, enum eSectionType type) {
|
||||
ensureSectionTypeIsValid(type);
|
||||
|
||||
for (i = BANK_VRAM; i <= BANK_VRAM + 1; i += 1) {
|
||||
if ((org = area_Alloc(&BankFree[i], size)) != -1)
|
||||
return ((i << 16) | org);
|
||||
}
|
||||
SLONG startBank = SECT_ATTRIBUTES[type].bank;
|
||||
SLONG bankCount = SECT_ATTRIBUTES[type].bankCount;
|
||||
|
||||
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;
|
||||
for (int i = 0; i < bankCount; i++) {
|
||||
SLONG org = area_Alloc(&BankFree[startBank + i], size);
|
||||
if (org != -1) {
|
||||
return ((startBank + 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)
|
||||
FindLargestSection(enum eSectionType type)
|
||||
{
|
||||
struct sSection *pSection, *r = NULL;
|
||||
SLONG nLargest = 0;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == SECT_WRAMX) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == type) {
|
||||
if (pSection->nByteSize > nLargest) {
|
||||
nLargest = pSection->nByteSize;
|
||||
r = pSection;
|
||||
@@ -237,136 +200,40 @@ FindLargestWRAM(void)
|
||||
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)
|
||||
{
|
||||
struct sSection *pSection, *r = NULL;
|
||||
SLONG nLargest = 0;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == SECT_ROMX) {
|
||||
if (pSection->nByteSize > nLargest) {
|
||||
nLargest = pSection->nByteSize;
|
||||
r = pSection;
|
||||
}
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
return (r);
|
||||
}
|
||||
|
||||
void
|
||||
AssignVRAMSections(void)
|
||||
AssignBankedSections(enum eSectionType type)
|
||||
{
|
||||
ensureSectionTypeIsValid(type);
|
||||
|
||||
struct sSection *pSection;
|
||||
|
||||
while ((pSection = FindLargestVRAM())) {
|
||||
while ((pSection = FindLargestSection(type))) {
|
||||
SLONG org;
|
||||
|
||||
if ((org = area_AllocVRAMAnyBank(pSection->nByteSize)) != -1) {
|
||||
if ((org = area_AllocAnyBank(pSection->nByteSize, type)) != -1) {
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXVBANK(pSection->nBank);
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place VRAM section anywhere");
|
||||
errx(1, "Unable to place %s section anywhere",
|
||||
SECT_ATTRIBUTES[type].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AssignSRAMSections(void)
|
||||
bool
|
||||
VerifyAndSetBank(struct sSection *pSection)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
ensureSectionTypeIsValid(pSection->Type);
|
||||
|
||||
while ((pSection = FindLargestSRAM())) {
|
||||
SLONG org;
|
||||
if (pSection->nBank >= SECT_ATTRIBUTES[pSection->Type].minBank
|
||||
&& pSection->nBank < SECT_ATTRIBUTES[pSection->Type].minBank + SECT_ATTRIBUTES[pSection->Type].bankCount) {
|
||||
pSection->nBank += SECT_ATTRIBUTES[pSection->Type].bank + SECT_ATTRIBUTES[pSection->Type].offset;
|
||||
return true;
|
||||
|
||||
if ((org = area_AllocSRAMAnyBank(pSection->nByteSize)) != -1) {
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
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->oAssigned = 1;
|
||||
DOMAXWBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place WRAMX section anywhere");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AssignCodeSections(void)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
|
||||
while ((pSection = FindLargestCode())) {
|
||||
SLONG org;
|
||||
|
||||
if ((org = area_AllocROMXAnyBank(pSection->nByteSize)) != -1) {
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place ROMX section anywhere");
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,17 +257,15 @@ AssignSections(void)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
if (i == BANK_ROM0) {
|
||||
/* ROM0 bank */
|
||||
BankFree[i]->nOrg = 0x0000;
|
||||
if (options & OPT_SMALL) {
|
||||
BankFree[i]->nSize = 0x8000;
|
||||
MaxAvail[i] = 0x8000;
|
||||
} else {
|
||||
BankFree[i]->nSize = 0x4000;
|
||||
MaxAvail[i] = 0x4000;
|
||||
}
|
||||
} else if (i >= 1 && i <= 511) {
|
||||
} else if (i >= BANK_ROMX && i < BANK_ROMX + BANK_COUNT_ROMX) {
|
||||
/* Swappable ROM bank */
|
||||
BankFree[i]->nOrg = 0x4000;
|
||||
/*
|
||||
@@ -409,37 +274,34 @@ AssignSections(void)
|
||||
*/
|
||||
if (options & OPT_SMALL) {
|
||||
BankFree[i]->nSize = 0;
|
||||
MaxAvail[i] = 0;
|
||||
} else {
|
||||
BankFree[i]->nSize = 0x4000;
|
||||
MaxAvail[i] = 0x4000;
|
||||
}
|
||||
} 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) {
|
||||
} else if (i >= BANK_SRAM && i < BANK_SRAM + BANK_COUNT_SRAM) {
|
||||
/* Swappable SRAM bank */
|
||||
BankFree[i]->nOrg = 0xA000;
|
||||
BankFree[i]->nSize = 0x2000;
|
||||
MaxAvail[i] = 0x2000;
|
||||
} else if (i >= BANK_WRAMX && i <= BANK_WRAMX + 6) {
|
||||
} else if (i >= BANK_WRAMX && i < BANK_WRAMX + BANK_COUNT_WRAMX) {
|
||||
/* Swappable WRAM bank */
|
||||
BankFree[i]->nOrg = 0xD000;
|
||||
BankFree[i]->nSize = 0x1000;
|
||||
MaxAvail[i] = 0x1000;
|
||||
} else if (i == BANK_VRAM || i == BANK_VRAM + 1) {
|
||||
} else if (i >= BANK_VRAM && i < BANK_VRAM + BANK_COUNT_VRAM) {
|
||||
/* 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;
|
||||
} else {
|
||||
errx(1, "(INTERNAL) Unknown bank type!");
|
||||
}
|
||||
|
||||
MaxAvail[i] = BankFree[i]->nSize;
|
||||
BankFree[i]->pPrev = NULL;
|
||||
BankFree[i]->pNext = NULL;
|
||||
}
|
||||
@@ -458,241 +320,31 @@ AssignSections(void)
|
||||
|
||||
switch (pSection->Type) {
|
||||
case SECT_WRAM0:
|
||||
if (area_AllocAbs
|
||||
(&BankFree[BANK_WRAM0], pSection->nOrg,
|
||||
pSection->nByteSize) != pSection->nOrg) {
|
||||
errx(1,
|
||||
"Unable to load fixed WRAM0 "
|
||||
"section at $%lX", pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
pSection->nBank = BANK_WRAM0;
|
||||
break;
|
||||
case SECT_HRAM:
|
||||
if (area_AllocAbs
|
||||
(&BankFree[BANK_HRAM], pSection->nOrg,
|
||||
pSection->nByteSize) != pSection->nOrg) {
|
||||
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 >= 1
|
||||
&& pSection->nBank <= 7) {
|
||||
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_ROM0], pSection->nOrg,
|
||||
pSection->nByteSize) != pSection->nOrg) {
|
||||
errx(1, "Unable to load fixed ROM0 "
|
||||
"section at $%lX", pSection->nOrg);
|
||||
pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank;
|
||||
if (area_AllocAbs(&BankFree[pSection->nBank], pSection->nOrg,
|
||||
pSection->nByteSize) == -1) {
|
||||
errx(1, "Unable to load fixed %s section at $%lX",
|
||||
SECT_ATTRIBUTES[pSection->Type].name,
|
||||
pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
pSection->nBank = BANK_ROM0;
|
||||
break;
|
||||
|
||||
case SECT_SRAM:
|
||||
case SECT_WRAMX:
|
||||
case SECT_VRAM:
|
||||
case SECT_ROMX:
|
||||
if (pSection->nBank == -1) {
|
||||
/*
|
||||
* User doesn't care which bank, so he must want to
|
||||
* decide which position within that bank.
|
||||
* We'll do that at a later stage when the really
|
||||
* hardcoded things are allocated
|
||||
*
|
||||
*/
|
||||
} else {
|
||||
/*
|
||||
* User wants to decide which bank we use
|
||||
* Does he care about the position as well?
|
||||
*
|
||||
*/
|
||||
|
||||
if (pSection->nOrg == -1) {
|
||||
/*
|
||||
* Nope, any position will do
|
||||
* Again, we'll do that later
|
||||
*
|
||||
*/
|
||||
if (pSection->nBank != -1 && pSection->nOrg != -1) {
|
||||
if (VerifyAndSetBank(pSection) &&
|
||||
area_AllocAbs(&BankFree[pSection->nBank], pSection->nOrg, pSection->nByteSize) != -1) {
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
/*
|
||||
* How hardcore can you possibly get? Why does
|
||||
* he even USE this package? Yeah let's just
|
||||
* direct address everything, shall we?
|
||||
* Oh well, the customer is always right
|
||||
*
|
||||
*/
|
||||
|
||||
if (pSection->nBank >= 1
|
||||
&& pSection->nBank <= 511) {
|
||||
if (area_AllocAbs
|
||||
(&BankFree
|
||||
[pSection->nBank],
|
||||
pSection->nOrg,
|
||||
pSection->
|
||||
nByteSize) !=
|
||||
pSection->nOrg) {
|
||||
errx(1,
|
||||
"Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
DOMAXBANK(pSection->
|
||||
nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
errx(1,
|
||||
"Unable to load fixed ROMX section at $%lX in bank $%02lX", pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
errx(1,
|
||||
"Unable to load fixed %s section at $%lX in bank $%02lX", SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -708,70 +360,27 @@ AssignSections(void)
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0
|
||||
&& 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 <= 511) {
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[pSection->nBank],
|
||||
pSection->nByteSize)) == -1) {
|
||||
errx(1,
|
||||
"Unable to load fixed ROMX section into bank $%02lX", pSection->nBank);
|
||||
&& pSection->nOrg == -1 && pSection->nBank != -1) {
|
||||
switch (pSection->Type) {
|
||||
case SECT_ROMX:
|
||||
case SECT_SRAM:
|
||||
case SECT_VRAM:
|
||||
case SECT_WRAMX:
|
||||
if (VerifyAndSetBank(pSection) &&
|
||||
(pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) != -1) {
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to load fixed %s section into bank $%02lX",
|
||||
SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->nBank);
|
||||
} else {
|
||||
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);
|
||||
break;
|
||||
|
||||
default: // Handle other sections later
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
|
||||
@@ -783,58 +392,27 @@ AssignSections(void)
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0
|
||||
&& 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_AllocAbsROMXAnyBank(pSection->nOrg,
|
||||
pSection->nByteSize)) ==
|
||||
-1) {
|
||||
errx(1, "Unable to load fixed ROMX section at $%lX into any bank", pSection->nOrg);
|
||||
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
||||
switch (pSection->Type) {
|
||||
case SECT_ROMX:
|
||||
case SECT_VRAM:
|
||||
case SECT_SRAM:
|
||||
case SECT_WRAMX:
|
||||
if ((pSection->nBank =
|
||||
area_AllocAbsAnyBank(pSection->nOrg, pSection->nByteSize,
|
||||
pSection->Type)) == -1) {
|
||||
errx(1, "Unable to load fixed %s section at $%lX into any bank",
|
||||
SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
break;
|
||||
|
||||
default: // Handle other sections later
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -849,40 +427,23 @@ AssignSections(void)
|
||||
if (pSection->oAssigned == 0) {
|
||||
switch (pSection->Type) {
|
||||
case SECT_WRAM0:
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[BANK_WRAM0],
|
||||
pSection->nByteSize)) == -1) {
|
||||
errx(1, "WRAM0 section too large");
|
||||
}
|
||||
pSection->nBank = BANK_WRAM0;
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
case SECT_HRAM:
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[BANK_HRAM],
|
||||
pSection->nByteSize)) == -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:
|
||||
pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank;
|
||||
if ((pSection->nOrg =
|
||||
area_Alloc(&BankFree[BANK_ROM0],
|
||||
area_Alloc(&BankFree[pSection->nBank],
|
||||
pSection->nByteSize)) == -1) {
|
||||
errx(1, "ROM0 section too large");
|
||||
errx(1, "%s section too large", SECT_ATTRIBUTES[pSection->Type].name);
|
||||
}
|
||||
pSection->nBank = BANK_ROM0;
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
|
||||
case SECT_SRAM:
|
||||
case SECT_VRAM:
|
||||
case SECT_WRAMX:
|
||||
case SECT_ROMX:
|
||||
break;
|
||||
|
||||
default:
|
||||
errx(1, "(INTERNAL) Unknown section type!");
|
||||
break;
|
||||
@@ -891,10 +452,10 @@ AssignSections(void)
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
|
||||
AssignCodeSections();
|
||||
AssignVRAMSections();
|
||||
AssignWRAMSections();
|
||||
AssignSRAMSections();
|
||||
AssignBankedSections(SECT_ROMX);
|
||||
AssignBankedSections(SECT_VRAM);
|
||||
AssignBankedSections(SECT_WRAMX);
|
||||
AssignBankedSections(SECT_SRAM);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/main.h"
|
||||
|
||||
|
||||
@@ -22,7 +22,9 @@ enum eBlockType {
|
||||
|
||||
SLONG options = 0;
|
||||
SLONG fillchar = 0;
|
||||
char smartlinkstartsymbol[256];
|
||||
char *smartlinkstartsymbol;
|
||||
|
||||
char *progname;
|
||||
|
||||
/*
|
||||
* Print the usagescreen
|
||||
@@ -32,9 +34,9 @@ char smartlinkstartsymbol[256];
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
printf("usage: rgblink [-t] [-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);
|
||||
}
|
||||
|
||||
@@ -52,7 +54,9 @@ 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 'm':
|
||||
SetMapfileName(optarg);
|
||||
@@ -75,7 +79,7 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case 's':
|
||||
options |= OPT_SMART_C_LINK;
|
||||
strcpy(smartlinkstartsymbol, optarg);
|
||||
smartlinkstartsymbol = optarg;
|
||||
break;
|
||||
case 't':
|
||||
options |= OPT_SMALL;
|
||||
|
||||
@@ -53,33 +53,49 @@ MapfileInitBank(SLONG bank)
|
||||
{
|
||||
if (mf) {
|
||||
currentbank = bank;
|
||||
if (bank == 0)
|
||||
fprintf(mf, "Bank #0 (HOME):\n");
|
||||
if (bank == BANK_ROM0)
|
||||
fprintf(mf, "ROM Bank #0 (HOME):\n");
|
||||
else if (bank < BANK_WRAM0)
|
||||
fprintf(mf, "Bank #%ld:\n", bank);
|
||||
fprintf(mf, "ROM Bank #%ld:\n", bank);
|
||||
else if (bank == BANK_WRAM0)
|
||||
fprintf(mf, "WRAM0:\n");
|
||||
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 || 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 <= 511) ? 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;
|
||||
|
||||
@@ -86,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;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "link/assign.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/symbol.h"
|
||||
#include "link/main.h"
|
||||
@@ -53,18 +54,29 @@ getsymvalue(SLONG symid)
|
||||
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");
|
||||
}
|
||||
errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
|
||||
|
||||
if (nBank == BANK_WRAM0) return 0;
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -51,7 +50,7 @@ section size from 16KiB to 32KiB.
|
||||
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 .
|
||||
@@ -59,12 +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 gbz80 7
|
||||
.Xr rgbds 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally written by Carsten S\(/orensen as part of the ASMotor package,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "extern/err.h"
|
||||
#include "link/main.h"
|
||||
#include "link/patch.h"
|
||||
#include "link/types.h"
|
||||
#include "types.h"
|
||||
|
||||
#define HASHSIZE 73
|
||||
|
||||
@@ -76,7 +76,7 @@ sym_GetBank(char *tzName)
|
||||
}
|
||||
|
||||
void
|
||||
sym_CreateSymbol(char *tzName, SLONG nValue, SBYTE nBank)
|
||||
sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank)
|
||||
{
|
||||
if (strcmp(tzName, "@") == 0)
|
||||
return;
|
||||
|
||||
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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user