mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Compare commits
262 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b55fead749 | ||
|
|
844e027a18 | ||
|
|
0fb80cd7a9 | ||
|
|
311b412f5d | ||
|
|
975200834e | ||
|
|
c8fa799883 | ||
|
|
7f37eef218 | ||
|
|
8521e45edc | ||
|
|
7bd082563d | ||
|
|
de32e245c9 | ||
|
|
f5164325d2 | ||
|
|
959bfe2a9d | ||
|
|
d24cf11ad4 | ||
|
|
8d89ba39d4 | ||
|
|
b04596a32b | ||
|
|
8e8865940a | ||
|
|
3c14f9760f | ||
|
|
3c15b141e0 | ||
|
|
72f801283d | ||
|
|
2ffaf72e39 | ||
|
|
f41c532400 | ||
|
|
ec76431c51 | ||
|
|
71961a88a0 | ||
|
|
ba944527ec | ||
|
|
87c9d819a1 | ||
|
|
13c0684497 | ||
|
|
c24cab6d1d | ||
|
|
0cbe6abbd5 | ||
|
|
fe6e5e445b | ||
|
|
781c90b940 | ||
|
|
e7a8bb1140 | ||
|
|
f1c13af703 | ||
|
|
90bc8d9110 | ||
|
|
193cc06561 | ||
|
|
f3b475453f | ||
|
|
0c71f5a4e9 | ||
|
|
4b0dfd4f4a | ||
|
|
2d117f68c9 | ||
|
|
8954858bf7 | ||
|
|
4877e6dbba | ||
|
|
ec171c5f00 | ||
|
|
840ddcecd2 | ||
|
|
c00f7409ee | ||
|
|
92449a4fe4 | ||
|
|
4e2a035838 | ||
|
|
df25fa73af | ||
|
|
03bb2d04c3 | ||
|
|
4dc376b0ee | ||
|
|
3dec5698db | ||
|
|
f8bbe9be48 | ||
|
|
4d01b2d5ac | ||
|
|
086f02c1d9 | ||
|
|
8ed6c32ae7 | ||
|
|
d0e0525302 | ||
|
|
318c981c00 | ||
|
|
5c7db42fc4 | ||
|
|
4be92e14e6 | ||
|
|
1b155d9d4c | ||
|
|
f9a1aba0d8 | ||
|
|
fe65e07cb6 | ||
|
|
bb12806da1 | ||
|
|
fa36042131 | ||
|
|
efaad99f25 | ||
|
|
62d820c261 | ||
|
|
a53d795361 | ||
|
|
2e60c4dd2e | ||
|
|
ce8a13a562 | ||
|
|
ff2321a8ce | ||
|
|
4228e3e890 | ||
|
|
023b574fc5 | ||
|
|
a77df57f1c | ||
|
|
8f553e89ce | ||
|
|
b7810ffdb3 | ||
|
|
0d3401058d | ||
|
|
6e123ccc36 | ||
|
|
f2724df566 | ||
|
|
646d71d927 | ||
|
|
9b9b41e605 | ||
|
|
907ccfb280 | ||
|
|
fcd7c117e7 | ||
|
|
323922d854 | ||
|
|
f97e3bad33 | ||
|
|
64415555f1 | ||
|
|
ab2aef3f2b | ||
|
|
947db1e21b | ||
|
|
cde607c09c | ||
|
|
739b113f57 | ||
|
|
64585eebf6 | ||
|
|
1050acc290 | ||
|
|
466bb9ed0b | ||
|
|
83348100f3 | ||
|
|
57bf32f35a | ||
|
|
0030e0371a | ||
|
|
42400ec6a0 | ||
|
|
2e793fb7dc | ||
|
|
ac69e9863e | ||
|
|
59c065cf31 | ||
|
|
729683fb1f | ||
|
|
ed6e4c4769 | ||
|
|
d92c284b85 | ||
|
|
26af7fcffe | ||
|
|
f7f697c267 | ||
|
|
554b5292de | ||
|
|
a7393d7e45 | ||
|
|
fe9e4f0583 | ||
|
|
362aea22bd | ||
|
|
9bc6083e49 | ||
|
|
2b5ad9dc38 | ||
|
|
5679c7066b | ||
|
|
4395ed893a | ||
|
|
0d80f60fcc | ||
|
|
7097b9885e | ||
|
|
f2c207cb44 | ||
|
|
be50f2d302 | ||
|
|
fa767f3228 | ||
|
|
5cfa15f963 | ||
|
|
23584a584f | ||
|
|
53fa608161 | ||
|
|
1154a173cc | ||
|
|
ca3e55cc45 | ||
|
|
206275df57 | ||
|
|
3d8396b86f | ||
|
|
77546e9c58 | ||
|
|
540f8597d4 | ||
|
|
e3109af2f8 | ||
|
|
cf99f33dd6 | ||
|
|
0b6438ae0a | ||
|
|
928b347dfc | ||
|
|
ce21cfad4e | ||
|
|
dda3a066be | ||
|
|
a6a47ff66d | ||
|
|
bfcef01211 | ||
|
|
07861b3b4a | ||
|
|
24439003f3 | ||
|
|
3c43cc14d9 | ||
|
|
52081f32f0 | ||
|
|
6e5a28226b | ||
|
|
2783a36b17 | ||
|
|
2c3afc833f | ||
|
|
0f3b708dce | ||
|
|
7eb9101d43 | ||
|
|
032e698f46 | ||
|
|
63103c050d | ||
|
|
7e107ab41a | ||
|
|
a009a372c5 | ||
|
|
5f299bfe6c | ||
|
|
07cc4fb8fd | ||
|
|
720ae59af8 | ||
|
|
e63e801e9c | ||
|
|
2abdc9c59d | ||
|
|
be200593d6 | ||
|
|
43228f16f0 | ||
|
|
f14b061ea7 | ||
|
|
f431b384a2 | ||
|
|
7e3720b627 | ||
|
|
e9ed81074b | ||
|
|
e16af28676 | ||
|
|
25be5c6561 | ||
|
|
e4b4e427f1 | ||
|
|
2138bb46fd | ||
|
|
ec5eb4f9ff | ||
|
|
b31632b51d | ||
|
|
e50e3e5a23 | ||
|
|
f63339472e | ||
|
|
43fd1ee024 | ||
|
|
d61a0a8a8f | ||
|
|
ec44b554e8 | ||
|
|
01a710a47d | ||
|
|
ff2ba7290c | ||
|
|
53842cd07d | ||
|
|
85ff75d2d3 | ||
|
|
adef2e18cc | ||
|
|
5ba8405dfa | ||
|
|
f0d4750ebc | ||
|
|
eed098ac8e | ||
|
|
64dbcc0912 | ||
|
|
5947ca10dc | ||
|
|
d1ed4fbded | ||
|
|
22d4a10cb6 | ||
|
|
dfb99618f5 | ||
|
|
6b21e02c95 | ||
|
|
011c2c953b | ||
|
|
8eb1a42e31 | ||
|
|
c51aac0c20 | ||
|
|
6feaba2343 | ||
|
|
0867476bde | ||
|
|
fa962b9470 | ||
|
|
b8642bf3af | ||
|
|
317b206fa8 | ||
|
|
469e3e7c86 | ||
|
|
9193710ff9 | ||
|
|
263c9222ab | ||
|
|
947d767c64 | ||
|
|
82cf3eb48f | ||
|
|
a75c15ec46 | ||
|
|
3dcfe2b9f6 | ||
|
|
523b7538f0 | ||
|
|
bc2f885d29 | ||
|
|
bd00b9ab59 | ||
|
|
4f86a12539 | ||
|
|
7e2457c9be | ||
|
|
7993d3455d | ||
|
|
c9daf80f11 | ||
|
|
5a7faa7dff | ||
|
|
7b8d4de35c | ||
|
|
c7fe281c86 | ||
|
|
fa8f25a4de | ||
|
|
7c2cae7a32 | ||
|
|
92b81b1d5a | ||
|
|
42b5be24b4 | ||
|
|
14fea5f659 | ||
|
|
1e16a0ff85 | ||
|
|
7adf1dd502 | ||
|
|
0588e42520 | ||
|
|
2eb748278b | ||
|
|
1ab93a194e | ||
|
|
1b05c43b97 | ||
|
|
e4cbf773f6 | ||
|
|
b07c04cd74 | ||
|
|
9be7c4c849 | ||
|
|
6d1c60b0a6 | ||
|
|
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 | ||
|
|
280ca83acd | ||
|
|
2e9c68f8c3 | ||
|
|
330a39596c | ||
|
|
e241137508 | ||
|
|
581133ecce | ||
|
|
deb44eaeef | ||
|
|
338c176b37 | ||
|
|
1a15ee5363 | ||
|
|
2ea2e47231 | ||
|
|
31294d6d9d | ||
|
|
b2d523acde |
60
.checkpatch.conf
Normal file
60
.checkpatch.conf
Normal file
@@ -0,0 +1,60 @@
|
||||
# Configuration for checkpatch.pl
|
||||
# ===============================
|
||||
|
||||
# Enable more tests
|
||||
--strict
|
||||
|
||||
# Quiet
|
||||
--quiet
|
||||
|
||||
# No per-file summary
|
||||
--no-summary
|
||||
|
||||
# Don't expect the Linux kernel tree
|
||||
--no-tree
|
||||
|
||||
# Show file line, not input line
|
||||
--showfile
|
||||
|
||||
# List of ignored rules
|
||||
# ---------------------
|
||||
|
||||
# There's no BIT macro
|
||||
--ignore BIT_MACRO
|
||||
|
||||
# Allow CamelCase
|
||||
--ignore CAMELCASE
|
||||
|
||||
# Comparing to NULL explicitly isn't a bad thing
|
||||
--ignore COMPARISON_TO_NULL
|
||||
|
||||
# Causes false positives
|
||||
--ignore COMPLEX_MACRO
|
||||
|
||||
# Don't complain about structs not being const
|
||||
--ignore CONST_STRUCT
|
||||
|
||||
# Do not check the format of commit messages
|
||||
--ignore GIT_COMMIT_ID
|
||||
|
||||
# We don't have a MAINTAINERS file, don't complain about it.
|
||||
--ignore FILE_PATH_CHANGES
|
||||
|
||||
# Writing the continuation on the start of the line can make it clearer
|
||||
--ignore LOGICAL_CONTINUATIONS
|
||||
|
||||
# Don't complain if a line that contains a string is too long. It's better to
|
||||
# have a really long line that can be found with grep.
|
||||
--ignore LONG_LINE_STRING
|
||||
|
||||
# Allow new typedefs
|
||||
--ignore NEW_TYPEDEFS
|
||||
|
||||
# Prefer stdint.h types over kernel types
|
||||
--ignore PREFER_KERNEL_TYPES
|
||||
|
||||
# Parentheses can make the code clearer
|
||||
--ignore UNNECESSARY_PARENTHESES
|
||||
|
||||
# Don't complain when files are modified in 'include/asm'
|
||||
--ignore MODIFIED_INCLUDE_ASM
|
||||
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
rgbasm
|
||||
rgblink
|
||||
rgbfix
|
||||
rgbgfx
|
||||
*.o
|
||||
*.exe
|
||||
*.html
|
||||
.checkpatch-camelcase.*
|
||||
13
.travis-deps.sh
Executable file
13
.travis-deps.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $TRAVIS_OS_NAME = "osx" ]; then
|
||||
brew update
|
||||
brew install libpng pkg-config
|
||||
else # linux
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get install -y -q bison flex libpng-dev pkg-config
|
||||
fi
|
||||
|
||||
echo "Dependencies:"
|
||||
yacc --version
|
||||
flex --version
|
||||
16
.travis.yml
Normal file
16
.travis.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
language: c
|
||||
sudo: required
|
||||
install:
|
||||
- ./.travis-deps.sh
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
script:
|
||||
- make
|
||||
- sudo make install
|
||||
after_success:
|
||||
- pushd test/asm/ && ./test.sh && popd
|
||||
- pushd test/link/ && ./test.sh && popd
|
||||
88
CONTRIBUTING.rst
Normal file
88
CONTRIBUTING.rst
Normal file
@@ -0,0 +1,88 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
RGBDS was created in the late 90's and has received contributions from several
|
||||
developers since then. It wouldn't have been possible to get to this point
|
||||
without their work and, for that reason, it is always open to the contributions
|
||||
of other people.
|
||||
|
||||
Reporting Bugs
|
||||
--------------
|
||||
|
||||
Bug reports are essential to improve RGBDS and they are always welcome. If you
|
||||
want to report a bug:
|
||||
|
||||
1. Make sure that there isn't a similar issue already reported
|
||||
`here <https://github.com/rednex/rgbds/issues>`__.
|
||||
|
||||
2. Figure out a way of reproducing it reliably.
|
||||
|
||||
3. If there is a piece of code that triggers the bug, try to reduce it to the
|
||||
smallest file you can.
|
||||
|
||||
4. Create a new `issue <https://github.com/rednex/rgbds/issues>`__.
|
||||
|
||||
Of course, it may not always be possible to give an accurate bug report, but it
|
||||
always helps to fix it.
|
||||
|
||||
Requesting new features
|
||||
-----------------------
|
||||
|
||||
If you come up with a good idea that could be implemented, you can propose it to
|
||||
be done.
|
||||
|
||||
1. Create a new `issue <https://github.com/rednex/rgbds/issues>`__.
|
||||
|
||||
2. Try to be as accurate as possible. Describe what you need and why you need
|
||||
it, maybe with examples.
|
||||
|
||||
Please understand that the contributors are doing it in their free time, so
|
||||
simple requests are more likely to catch the interest of a contributor than
|
||||
complicated ones. If you really need something to be done, and you think you can
|
||||
implement it yourself, you can always contribute to RGBDS with your own code.
|
||||
|
||||
Contributing code
|
||||
-----------------
|
||||
|
||||
If you want to contribute with your own code, whether it is to fix a current
|
||||
issue or to add something that nobody had requested, you should first consider
|
||||
if your change is going to be small (and likely to be accepted as-is) or big
|
||||
(and will have to go through some rework).
|
||||
|
||||
Big changes will most likely require some discussion, so open an
|
||||
`issue <https://github.com/rednex/rgbds/issues>`__ and explain what you want to
|
||||
do and how you intend to do it. If you already have a prototype, it's always a
|
||||
good idea to show it. Tests help, too.
|
||||
|
||||
If you are going to work on a specific issue that involves a lot of work, it is
|
||||
always a good idea to leave a message, just in case someone else is interested
|
||||
but doesn't know that there's someone working on it.
|
||||
|
||||
1. Fork this repository.
|
||||
|
||||
2. Checkout the ``develop`` branch.
|
||||
|
||||
3. Create a new branch to work on. You could still work on ``develop``, but it's
|
||||
easier that way.
|
||||
|
||||
4. Sign off your commits: ``git commit -s``
|
||||
|
||||
5. Follow the Linux kernel coding style, which can be found in the file
|
||||
``Documentation/process/coding-style.rst`` in the Linux kernel repository.
|
||||
Note that the coding style isn't writen on stone, if there is a good reason
|
||||
to deviate from it, it should be fine.
|
||||
|
||||
6. Download the files ``checkpatch.pl``, ``const_structs.checkpatch`` and
|
||||
``spelling.txt`` from the folder ``scripts`` in the Linux kernel repository.
|
||||
|
||||
7. To use ``checkpatch.pl`` you can use ``make checkpatch``, which will check
|
||||
the coding style of all patches between the current one and the upstream
|
||||
code. By default, the Makefile expects the script (and associate files) to be
|
||||
located in ``../linux/scripts/``, but you can place them anywhere you like as
|
||||
long as you specify it when executing the command:
|
||||
``CHECKPATCH=../path/to/folder make checkpatch``.
|
||||
|
||||
8. Create a pull request against the branch ``develop``.
|
||||
|
||||
9. Be prepared to get some comments about your code and to modify it. Tip: Use
|
||||
``git rebase -i origin/develop`` to modify chains of commits.
|
||||
28
LICENSE
28
LICENSE
@@ -1,28 +0,0 @@
|
||||
rgbasm and rgblink are derived from Justin Lloyd's RGBDS, which is
|
||||
released under the following license:
|
||||
|
||||
DO WHATEVER PUBLIC LICENSE*
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You can do whatever you want to with the work.
|
||||
1. You cannot stop anybody from doing whatever they want to with the work.
|
||||
2. You cannot revoke anybody elses DO WHATEVER PUBLIC LICENSE in the work.
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the DO WHATEVER PUBLIC LICENSE
|
||||
|
||||
Software originally created by Justin Lloyd @ http://otakunozoku.com/
|
||||
|
||||
|
||||
rgbfix was rewritten from scratch by Anthony J. Bentley, and is released
|
||||
under the ISC license; see the source file for the text of the license.
|
||||
|
||||
extern/err.c is derived from the Musl C library, http://www.musl-libc.org,
|
||||
and is released under the MIT license.
|
||||
|
||||
extern/reallocarray.c is derived from the OpenBSD Project,
|
||||
http://www.openbsd.org, and is released under the ISC license.
|
||||
|
||||
extern/strl.c is derived from the OpenBSD Project, http://www.openbsd.org,
|
||||
and is released under the BSD license.
|
||||
81
LICENSE.rst
Normal file
81
LICENSE.rst
Normal file
@@ -0,0 +1,81 @@
|
||||
LICENSE
|
||||
=======
|
||||
|
||||
Original code
|
||||
-------------
|
||||
|
||||
Copyright (C) 1997 Carsten Sorensen <surfsmurf@matilde.demon.co.uk>
|
||||
|
||||
The ASMotor package (xAsm, xLink, RGBFix, examples and documentation) is
|
||||
freeware and distributed as is. The author retains his copyright and right to
|
||||
modify the specifications and operation of the software without notice.
|
||||
|
||||
In other words this means I encourage you to...
|
||||
|
||||
- use it for whatever purpose even professional work without me charging you a
|
||||
penny
|
||||
- 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
|
||||
- mass-distribute the ASMotor package if it is complete (xAsm, xLink, RGBFix and
|
||||
documentation).
|
||||
- contact me if you have any problems
|
||||
|
||||
This also means you can't...
|
||||
|
||||
- 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.
|
||||
- expect me to be able to help you should you have a problem related or not to
|
||||
ASMotor.
|
||||
|
||||
Otaku no Zoku's modifications
|
||||
-----------------------------
|
||||
|
||||
Copyright (C) 1999 Justin Lloyd <jlloyd@imf.la> (?)
|
||||
|
||||
::
|
||||
|
||||
DO WHATEVER PUBLIC LICENSE*
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You can do whatever you want to with the work.
|
||||
1. You cannot stop anybody from doing whatever they want to with the work.
|
||||
2. You cannot revoke anybody elses DO WHATEVER PUBLIC LICENSE in the work.
|
||||
|
||||
This program is free software. It comes without any warranty, to
|
||||
the extent permitted by applicable law. You can redistribute it
|
||||
and/or modify it under the terms of the DO WHATEVER PUBLIC LICENSE
|
||||
|
||||
Software originally created by Justin Lloyd @ http://otakunozoku.com/
|
||||
|
||||
rgbds-linux
|
||||
-----------
|
||||
|
||||
Copyright (C) 2009 Vegard Nossum <vegard.nossum@gmail.com>
|
||||
|
||||
Current
|
||||
-------
|
||||
|
||||
rgbasm and rgblink are derived from Justin Lloyd's RGBDS.
|
||||
|
||||
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.
|
||||
|
||||
Some files of rgblink were written by Antonio Niño Díaz, and they are relased
|
||||
under the ISC license. The affected files have the appropriate license in the
|
||||
header of the file.
|
||||
|
||||
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.
|
||||
208
Makefile
208
Makefile
@@ -1,16 +1,43 @@
|
||||
.POSIX:
|
||||
|
||||
WARNFLAGS = -Wall -Werror=implicit
|
||||
REALCFLAGS = ${CFLAGS} ${WARNFLAGS} -Iinclude -g \
|
||||
-std=c99 -D_POSIX_C_SOURCE=200809L
|
||||
|
||||
# User-defined variables
|
||||
PREFIX = /usr/local
|
||||
BINPREFIX = ${PREFIX}/bin
|
||||
MANPREFIX = ${PREFIX}/man
|
||||
Q = @
|
||||
|
||||
rgbasm_obj = \
|
||||
Q := @
|
||||
PREFIX := /usr/local
|
||||
bindir := ${PREFIX}/bin
|
||||
mandir := ${PREFIX}/man
|
||||
STRIP := -s
|
||||
BINMODE := 555
|
||||
MANMODE := 444
|
||||
CHECKPATCH := ../linux/scripts/checkpatch.pl
|
||||
|
||||
# Other variables
|
||||
|
||||
PKG_CONFIG := pkg-config
|
||||
PNGCFLAGS := `${PKG_CONFIG} --static --cflags libpng`
|
||||
PNGLDFLAGS := `${PKG_CONFIG} --static --libs-only-L libpng`
|
||||
PNGLDLIBS := `${PKG_CONFIG} --static --libs-only-l libpng`
|
||||
|
||||
VERSION_STRING := `git describe --tags --dirty --always 2>/dev/null`
|
||||
|
||||
WARNFLAGS := -Wall -Werror
|
||||
|
||||
# Overridable CFLAGS
|
||||
CFLAGS := -g
|
||||
# Non-overridable CFLAGS
|
||||
REALCFLAGS := ${CFLAGS} ${WARNFLAGS} -std=c99 -D_POSIX_C_SOURCE=200809L \
|
||||
-Iinclude -DBUILD_VERSION_STRING=\"${VERSION_STRING}\"
|
||||
|
||||
YFLAGS :=
|
||||
LFLAGS := --nounistd
|
||||
|
||||
YACC := yacc
|
||||
LEX := flex
|
||||
RM := rm -rf
|
||||
|
||||
# Rules to build the RGBDS binaries
|
||||
|
||||
all: rgbasm rgblink rgbfix rgbgfx
|
||||
|
||||
rgbasm_obj := \
|
||||
src/asm/asmy.o \
|
||||
src/asm/charmap.o \
|
||||
src/asm/fstack.o \
|
||||
@@ -21,46 +48,45 @@ rgbasm_obj = \
|
||||
src/asm/output.o \
|
||||
src/asm/rpn.o \
|
||||
src/asm/symbol.o \
|
||||
src/asm/locallex.o \
|
||||
src/extern/err.o \
|
||||
src/extern/reallocarray.o \
|
||||
src/extern/strlcpy.o \
|
||||
src/extern/strlcat.o
|
||||
src/extern/strlcat.o \
|
||||
src/extern/version.o
|
||||
|
||||
rgblink_obj = \
|
||||
|
||||
src/asm/asmy.h: src/asm/asmy.c
|
||||
src/asm/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h
|
||||
|
||||
rgblink_obj := \
|
||||
src/link/assign.o \
|
||||
src/link/lexer.o \
|
||||
src/link/library.o \
|
||||
src/link/main.o \
|
||||
src/link/mapfile.o \
|
||||
src/link/object.o \
|
||||
src/link/output.o \
|
||||
src/link/patch.o \
|
||||
src/link/parser.o \
|
||||
src/link/script.o \
|
||||
src/link/symbol.o \
|
||||
src/extern/err.o
|
||||
src/extern/err.o \
|
||||
src/extern/version.o
|
||||
|
||||
rgbfix_obj = \
|
||||
src/link/parser.h: src/link/parser.c
|
||||
src/link/lexer.o: src/link/parser.h
|
||||
|
||||
rgbfix_obj := \
|
||||
src/fix/main.o \
|
||||
src/extern/err.o
|
||||
src/extern/err.o \
|
||||
src/extern/version.o
|
||||
|
||||
all: rgbasm rgblink rgbfix
|
||||
|
||||
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 src/asm/asmy.c src/asm/asmy.h
|
||||
|
||||
install: all
|
||||
$Qmkdir -p ${BINPREFIX}
|
||||
$Qinstall -s -m 555 rgbasm ${BINPREFIX}/rgbasm
|
||||
$Qinstall -s -m 555 rgbfix ${BINPREFIX}/rgbfix
|
||||
$Qinstall -s -m 555 rgblink ${BINPREFIX}/rgblink
|
||||
$Qmkdir -p ${MANPREFIX}/man1 ${MANPREFIX}/man7
|
||||
$Qinstall -m 444 src/rgbds.7 ${MANPREFIX}/man7/rgbds.7
|
||||
$Qinstall -m 444 src/asm/rgbasm.1 ${MANPREFIX}/man1/rgbasm.1
|
||||
$Qinstall -m 444 src/fix/rgbfix.1 ${MANPREFIX}/man1/rgbfix.1
|
||||
$Qinstall -m 444 src/link/rgblink.1 ${MANPREFIX}/man1/rgblink.1
|
||||
rgbgfx_obj := \
|
||||
src/gfx/gb.o \
|
||||
src/gfx/main.o \
|
||||
src/gfx/makepng.o \
|
||||
src/extern/err.o \
|
||||
src/extern/version.o
|
||||
|
||||
rgbasm: ${rgbasm_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgbasm_obj} -lm
|
||||
@@ -71,37 +97,105 @@ rgblink: ${rgblink_obj}
|
||||
rgbfix: ${rgbfix_obj}
|
||||
$Q${CC} ${REALCFLAGS} -o $@ ${rgbfix_obj}
|
||||
|
||||
rgbgfx: ${rgbgfx_obj}
|
||||
$Q${CC} ${REALCFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${PNGLDLIBS}
|
||||
|
||||
# Rules to process files
|
||||
|
||||
.y.c:
|
||||
$Q${YACC} -d ${YFLAGS} -o $@ $<
|
||||
|
||||
.l.o:
|
||||
$Q${RM} $*.c
|
||||
$Q${LEX} ${LFLAGS} -o $*.c $<
|
||||
$Q${CC} ${REALCFLAGS} -c -o $@ $*.c
|
||||
$Q${RM} $*.c
|
||||
|
||||
.c.o:
|
||||
$Q${CC} ${REALCFLAGS} -c -o $@ $<
|
||||
$Q${CC} ${REALCFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
|
||||
src/asm/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h
|
||||
src/asm/asmy.h: src/asm/asmy.c
|
||||
# Target used to remove all files generated by other Makefile targets.
|
||||
|
||||
# Below is a target for the project maintainer to easily create win32 exes.
|
||||
clean:
|
||||
$Q${RM} rgbds.7.html gbz80.7.html rgbds.5.html
|
||||
$Q${RM} rgbasm rgbasm.exe ${rgbasm_obj} rgbasm.1.html rgbasm.5.html
|
||||
$Q${RM} rgblink rgblink.exe ${rgblink_obj} rgblink.1.html rgblink.5.html
|
||||
$Q${RM} rgbfix rgbfix.exe ${rgbfix_obj} rgbfix.1.html
|
||||
$Q${RM} rgbgfx rgbgfx.exe ${rgbgfx_obj} rgbgfx.1.html
|
||||
$Q${RM} src/asm/asmy.c src/asm/asmy.h
|
||||
$Q${RM} src/link/lexer.c src/link/parser.c src/link/parser.h
|
||||
|
||||
# Target used to install the binaries and man pages.
|
||||
|
||||
install: all
|
||||
$Qmkdir -p ${DESTDIR}${bindir}
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbasm ${DESTDIR}${bindir}/rgbasm
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbfix ${DESTDIR}${bindir}/rgbfix
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgblink ${DESTDIR}${bindir}/rgblink
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbgfx ${DESTDIR}${bindir}/rgbgfx
|
||||
$Qmkdir -p ${DESTDIR}${mandir}/man1 ${DESTDIR}${mandir}/man5 ${DESTDIR}${mandir}/man7
|
||||
$Qinstall -m ${MANMODE} src/rgbds.7 ${DESTDIR}${mandir}/man7/rgbds.7
|
||||
$Qinstall -m ${MANMODE} src/gbz80.7 ${DESTDIR}${mandir}/man7/gbz80.7
|
||||
$Qinstall -m ${MANMODE} src/rgbds.5 ${DESTDIR}${mandir}/man5/rgbds.5
|
||||
$Qinstall -m ${MANMODE} src/asm/rgbasm.1 ${DESTDIR}${mandir}/man1/rgbasm.1
|
||||
$Qinstall -m ${MANMODE} src/asm/rgbasm.5 ${DESTDIR}${mandir}/man5/rgbasm.5
|
||||
$Qinstall -m ${MANMODE} src/fix/rgbfix.1 ${DESTDIR}${mandir}/man1/rgbfix.1
|
||||
$Qinstall -m ${MANMODE} src/link/rgblink.1 ${DESTDIR}${mandir}/man1/rgblink.1
|
||||
$Qinstall -m ${MANMODE} src/link/rgblink.5 ${DESTDIR}${mandir}/man5/rgblink.5
|
||||
$Qinstall -m ${MANMODE} src/gfx/rgbgfx.1 ${DESTDIR}${mandir}/man1/rgbgfx.1
|
||||
|
||||
# Target used to check the coding style of the whole codebase. '.y' and '.l'
|
||||
# files aren't checked, unfortunately...
|
||||
checkcodebase:
|
||||
$Qfor file in `git ls-files | grep -E '\.c|\.h'`; do \
|
||||
${CHECKPATCH} -f "$$file"; \
|
||||
done
|
||||
|
||||
# Target used to check the coding style of the patches from the upstream branch
|
||||
# to the HEAD. Runs checkpatch once for each commit between the current HEAD and
|
||||
# the first common commit between the HEAD and origin/develop. '.y' and '.l'
|
||||
# files aren't checked, unfortunately...
|
||||
checkpatch:
|
||||
$Qeval COMMON_COMMIT=$$(git merge-base HEAD origin/develop); \
|
||||
for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \
|
||||
echo "[*] Analyzing commit '$$commit'"; \
|
||||
git format-patch --stdout "$$commit~..$$commit" \
|
||||
| ${CHECKPATCH} - || true; \
|
||||
done
|
||||
|
||||
# Target for the project maintainer to easily create web manuals.
|
||||
# It relies on mandoc: http://mdocml.bsd.lv
|
||||
|
||||
MANDOC := -Thtml -Ios=General -Oman=%N.%S.html -Ostyle=manual.css
|
||||
|
||||
wwwman:
|
||||
$Qmandoc ${MANDOC} src/rgbds.7 > rgbds.7.html
|
||||
$Qmandoc ${MANDOC} src/gbz80.7 > gbz80.7.html
|
||||
$Qmandoc ${MANDOC} src/rgbds.5 > rgbds.5.html
|
||||
$Qmandoc ${MANDOC} src/asm/rgbasm.1 > rgbasm.1.html
|
||||
$Qmandoc ${MANDOC} src/asm/rgbasm.5 > rgbasm.5.html
|
||||
$Qmandoc ${MANDOC} src/fix/rgbfix.1 > rgbfix.1.html
|
||||
$Qmandoc ${MANDOC} src/link/rgblink.1 > rgblink.1.html
|
||||
$Qmandoc ${MANDOC} src/link/rgblink.5 > rgblink.5.html
|
||||
$Qmandoc ${MANDOC} src/gfx/rgbgfx.1 > rgbgfx.1.html
|
||||
|
||||
# Targets for the project maintainer to easily create Windows exes.
|
||||
# This is not for Windows users!
|
||||
# If you're building on Windows with Cygwin or Mingw, just follow the Unix
|
||||
# install instructions instead.
|
||||
mingw:
|
||||
$Qenv PATH=/usr/local/mingw32/bin:/bin:/usr/bin:/usr/local/bin \
|
||||
make WARNFLAGS= CC=gcc CFLAGS="-I/usr/local/mingw32/include \
|
||||
${CFLAGS}"
|
||||
|
||||
mingw32:
|
||||
$Qenv PKG_CONFIG_PATH=/usr/i686-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
|
||||
make CC=i686-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
|
||||
$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
|
||||
MANDOC = -Thtml -Ios=General -Oman=/rgbds/manual/%N/ \
|
||||
-Ostyle=/rgbds/manual/manual.css
|
||||
|
||||
wwwman:
|
||||
$Qmandoc ${MANDOC} src/rgbds.7 | sed s/OpenBSD/General/ > rgbds.html
|
||||
$Qmandoc ${MANDOC} src/asm/rgbasm.1 | sed s/OpenBSD/General/ > \
|
||||
rgbasm.html
|
||||
$Qmandoc ${MANDOC} src/fix/rgbfix.1 | sed s/OpenBSD/General/ > \
|
||||
rgbfix.html
|
||||
$Qmandoc ${MANDOC} src/link/rgblink.1 | sed s/OpenBSD/General/ > \
|
||||
rgblink.html
|
||||
mingw64:
|
||||
$Qenv PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
|
||||
make CC=x86_64-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
|
||||
$Qmv rgbasm rgbasm.exe
|
||||
$Qmv rgblink rgblink.exe
|
||||
$Qmv rgbfix rgbfix.exe
|
||||
$Qmv rgbgfx rgbgfx.exe
|
||||
|
||||
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: https://github.com/bentley/rgbds/releases
|
||||
|
||||
Copy the .exe files to C:\Windows\ or similar.
|
||||
173
README.rst
Normal file
173
README.rst
Normal file
@@ -0,0 +1,173 @@
|
||||
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)
|
||||
|
||||
This is a fork of the original RGBDS which aims to make the programs more like
|
||||
other UNIX tools.
|
||||
|
||||
This toolchain is maintained on `GitHub <https://github.com/rednex/rgbds>`__, as
|
||||
well as its `documentation <https://github.com/rednex/rednex.github.io>`__.
|
||||
|
||||
The documentation of this toolchain can be viewed online
|
||||
`here <https://rednex.github.io/>`__, it is generated from the man pages found
|
||||
in this repository.
|
||||
|
||||
1. Installing RGBDS
|
||||
-------------------
|
||||
|
||||
1.1 Windows
|
||||
~~~~~~~~~~~
|
||||
|
||||
Windows builds are available in the releases page on GitHub:
|
||||
|
||||
::
|
||||
|
||||
https://github.com/rednex/rgbds/releases
|
||||
|
||||
Copy the ``.exe`` files to ``C:\Windows\`` or similar.
|
||||
|
||||
If you require the latest version in development, it should be possible to
|
||||
compile RGBDS with MinGW or Cygwin by following the instructions to build it on
|
||||
UNIX systems.
|
||||
|
||||
1.2 macOS
|
||||
~~~~~~~~~
|
||||
|
||||
You can build RGBDS by following the instructions below. However, if you would
|
||||
prefer not to build RGBDS yourself, you may also install it using
|
||||
`Homebrew <http://brew.sh/>`__.
|
||||
|
||||
To install the latest release, use:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
brew install rgbds
|
||||
|
||||
To install RGBDS with all of the current changes in development (as seen on the
|
||||
``master`` branch on GitHub), use:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
brew install rgbds --HEAD
|
||||
|
||||
1.3 Other UNIX-like systems
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
No official binaries of RGBDS are distributed for these systems, you must follow
|
||||
the simple instructions below to compile and install it.
|
||||
|
||||
2. Building RGBDS from source
|
||||
-----------------------------
|
||||
|
||||
RGBDS can be built in UNIX-like systems by following the instructions below.
|
||||
|
||||
2.1 Dependencies
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
RGBDS requires yacc, flex, libpng and pkg-config to be installed.
|
||||
|
||||
On macOS, install the latter two with `Homebrew <http://brew.sh/>`__:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
brew install libpng pkg-config
|
||||
|
||||
On other Unixes, use the built-in package manager. For example, on Debian or
|
||||
Ubuntu:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
sudo apt-get install byacc flex pkg-config libpng-dev
|
||||
|
||||
You can test if libpng and pkg-config are 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.
|
||||
|
||||
2.2 Build process
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
To build the programs, run in your terminal:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
make
|
||||
|
||||
Then, to install the compiled programs and manual pages, run (with appropriate
|
||||
privileges, e.g, with ``sudo``):
|
||||
|
||||
.. code:: sh
|
||||
|
||||
make install
|
||||
|
||||
After installation, you can read the manuals with the ``man`` command. E.g.,
|
||||
|
||||
.. code:: sh
|
||||
|
||||
man 7 rgbds
|
||||
|
||||
There are some variables in the Makefile that can be redefined by the user. 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:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
make install PREFIX=$HOME
|
||||
|
||||
To do a verbose build, run:
|
||||
|
||||
.. code:: sh
|
||||
|
||||
make Q=
|
||||
|
||||
This is the complete list of user-defined variables:
|
||||
|
||||
- ``PREFIX``: Location where RGBDS will be installed. Defaults to
|
||||
``/usr/local``.
|
||||
|
||||
- ``bindir``: Location where the binaries will be installed. Defaults to
|
||||
``${PREFIX}/bin``.
|
||||
|
||||
- ``mandir``: Location where the manpages will be installed. Defaults to
|
||||
``${PREFIX}/man``.
|
||||
|
||||
- ``DESTDIR``: This is prepended to all paths during the installation. It is
|
||||
mainly used for packaging.
|
||||
|
||||
- ``Q``: Whether to quiet the build or not. To make the build more verbose,
|
||||
clear this variable. Defaults to ``@``.
|
||||
|
||||
- ``STRIP``: Whether to strip the installed binaries of debug symbols or not.
|
||||
Defaults to ``-s``.
|
||||
|
||||
- ``BINMODE``: Permissions of the installed binaries. Defaults to ``555``.
|
||||
|
||||
- ``MANMODE``: Permissions of the installed manpages. Defaults to ``444``.
|
||||
|
||||
- ``CHECKPATCH``: Path of the script ``checkpatch.pl`` of the Linux kernel.
|
||||
Defaults to ``../linux/scripts/checkpatch.pl``.
|
||||
|
||||
3 History
|
||||
---------
|
||||
|
||||
- Around 1997, Carsten Sorensen (AKA SurfSmurf) writes ASMotor as a
|
||||
general-purpose assembler/linker system for DOS/Win32
|
||||
|
||||
- Around 1999, Justin Lloyd (AKA Otaku no Zoku) adapts ASMotor to read and
|
||||
produce GBZ80 assembly/machine code, and releases this version as RGBDS.
|
||||
|
||||
- 2009, Vegard Nossum adapts the code to be more UNIX-like and releases
|
||||
this version as rgbds-linux on
|
||||
`GitHub <https://github.com/vegard/rgbds-linux>`__.
|
||||
|
||||
- 2010, Anthony J. Bentley forks that repository. The fork becomes the reference
|
||||
implementation of rgbds.
|
||||
|
||||
- 2017, Bentley's repository is moved to a neutral name.
|
||||
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>
|
||||
@@ -1,35 +1,41 @@
|
||||
/* asm.h
|
||||
/*
|
||||
* asm.h
|
||||
*
|
||||
* Contains some assembler-wide defines and externs
|
||||
*
|
||||
* Copyright 1997 Carsten Sorensen
|
||||
* Contains some assembler-wide defines and externs
|
||||
*
|
||||
* Copyright 1997 Carsten Sorensen
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_ASM_H
|
||||
#define RGBDS_ASM_ASM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "asm/localasm.h"
|
||||
#include "asm/symbol.h"
|
||||
|
||||
#include "asm/localasm.h"
|
||||
#define MAXUNIONS 128
|
||||
#define MAXMACROARGS 256
|
||||
#define MAXINCPATHS 128
|
||||
|
||||
extern SLONG nLineNo;
|
||||
extern ULONG nTotalLines;
|
||||
extern ULONG nPC;
|
||||
extern ULONG nPass;
|
||||
extern ULONG nIFDepth;
|
||||
extern int32_t nLineNo;
|
||||
extern uint32_t nTotalLines;
|
||||
extern uint32_t nPC;
|
||||
extern uint32_t nPass;
|
||||
extern uint32_t nIFDepth;
|
||||
extern bool skipElif;
|
||||
extern uint32_t nUnionDepth;
|
||||
extern uint32_t unionStart[MAXUNIONS];
|
||||
extern uint32_t unionSize[MAXUNIONS];
|
||||
extern char tzCurrentFileName[_MAX_PATH + 1];
|
||||
extern struct Section *pCurrentSection;
|
||||
extern struct sSymbol *tHashedSymbols[HASHSIZE];
|
||||
extern struct sSymbol *pPCSymbol;
|
||||
extern bool oDontExpandStrings;
|
||||
|
||||
#define MAXMACROARGS 256
|
||||
#define MAXINCPATHS 16
|
||||
size_t symvaluetostring(char *dest, size_t maxLength, char *sym);
|
||||
|
||||
#endif /* // ASM_H */
|
||||
#endif /* RGBDS_ASM_ASM_H */
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
#ifndef RGBDS_ASM_CHARMAP_H
|
||||
#define RGBDS_ASM_CHARMAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define MAXCHARMAPS 512
|
||||
#define CHARMAPLENGTH 8
|
||||
#define CHARMAPLENGTH 16
|
||||
|
||||
struct Charmap {
|
||||
int count;
|
||||
int32_t count;
|
||||
char input[MAXCHARMAPS][CHARMAPLENGTH + 1];
|
||||
char output[MAXCHARMAPS];
|
||||
};
|
||||
|
||||
int readUTF8Char(char *destination, char *source);
|
||||
void charmap_Sort();
|
||||
int charmap_Add(char *input, UBYTE output);
|
||||
int charmap_Convert(char **input);
|
||||
int32_t readUTF8Char(char *destination, char *source);
|
||||
int32_t charmap_Add(char *input, uint8_t output);
|
||||
int32_t charmap_Convert(char **input);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_ASM_CHARMAP_H */
|
||||
|
||||
@@ -1,46 +1,44 @@
|
||||
/* fstack.h
|
||||
/* fstack.h
|
||||
*
|
||||
* Contains some assembler-wide defines and externs
|
||||
* Contains some assembler-wide defines and externs
|
||||
*
|
||||
* Copyright 1997 Carsten Sorensen
|
||||
* Copyright 1997 Carsten Sorensen
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_FSTACK_H
|
||||
#define RGBDS_ASM_FSTACK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "asm/asm.h"
|
||||
#include "types.h"
|
||||
#include "asm/lexer.h"
|
||||
|
||||
#include "types.h"
|
||||
|
||||
struct sContext {
|
||||
YY_BUFFER_STATE FlexHandle;
|
||||
struct sSymbol *pMacro;
|
||||
struct sContext *pNext;
|
||||
char tzFileName[_MAX_PATH + 1];
|
||||
char *tzMacroArgs[MAXMACROARGS + 1];
|
||||
SLONG nLine;
|
||||
ULONG nStatus;
|
||||
int32_t nLine;
|
||||
uint32_t nStatus;
|
||||
FILE *pFile;
|
||||
char *pREPTBlock;
|
||||
ULONG nREPTBlockCount;
|
||||
ULONG nREPTBlockSize;
|
||||
uint32_t nREPTBlockCount;
|
||||
uint32_t nREPTBlockSize;
|
||||
};
|
||||
|
||||
void
|
||||
fstk_RunInclude(char *);
|
||||
extern void fstk_RunMacroArg(SLONG s);
|
||||
void
|
||||
fstk_Init(char *);
|
||||
extern void fstk_Dump(void);
|
||||
extern void fstk_AddIncludePath(char *s);
|
||||
extern ULONG fstk_RunMacro(char *s);
|
||||
extern void fstk_RunRept(ULONG count);
|
||||
FILE *
|
||||
fstk_FindFile(char *);
|
||||
void fstk_RunInclude(char *tzFileName);
|
||||
void fstk_RunMacroArg(int32_t s);
|
||||
void fstk_Init(char *s);
|
||||
void fstk_Dump(void);
|
||||
void fstk_AddIncludePath(char *s);
|
||||
uint32_t fstk_RunMacro(char *s);
|
||||
void fstk_RunRept(uint32_t count);
|
||||
FILE *fstk_FindFile(char *fname);
|
||||
int32_t fstk_GetLine(void);
|
||||
|
||||
extern int yywrap(void);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_ASM_FSTACK_H */
|
||||
|
||||
@@ -1,67 +1,69 @@
|
||||
#ifndef RGBDS_ASM_LEXER_H
|
||||
#define RGBDS_ASM_LEXER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define LEXHASHSIZE (1 << 11)
|
||||
#define MAXSTRLEN 255
|
||||
#define LEXHASHSIZE (1 << 11)
|
||||
#define MAXSTRLEN 255
|
||||
|
||||
struct sLexInitString {
|
||||
char *tzName;
|
||||
ULONG nToken;
|
||||
uint32_t nToken;
|
||||
};
|
||||
|
||||
struct sLexFloat {
|
||||
ULONG(*Callback) (char *s, ULONG size);
|
||||
ULONG nToken;
|
||||
uint32_t (*Callback)(char *s, uint32_t size);
|
||||
uint32_t nToken;
|
||||
};
|
||||
|
||||
struct yy_buffer_state {
|
||||
char *pBufferRealStart; // actual starting address
|
||||
char *pBufferStart; // address where the data is initially written
|
||||
// after the "safety margin"
|
||||
/* Actual starting address */
|
||||
char *pBufferRealStart;
|
||||
/* Address where the data is initially written after a safety margin */
|
||||
char *pBufferStart;
|
||||
char *pBuffer;
|
||||
ULONG nBufferSize;
|
||||
ULONG oAtLineStart;
|
||||
uint32_t nBufferSize;
|
||||
uint32_t oAtLineStart;
|
||||
};
|
||||
|
||||
enum eLexerState {
|
||||
LEX_STATE_NORMAL,
|
||||
LEX_STATE_MACROARGS
|
||||
};
|
||||
#define INITIAL 0
|
||||
#define macroarg 3
|
||||
|
||||
#define INITIAL 0
|
||||
#define macroarg 3
|
||||
|
||||
typedef struct yy_buffer_state *YY_BUFFER_STATE;
|
||||
|
||||
extern void yy_set_state(enum eLexerState i);
|
||||
extern YY_BUFFER_STATE yy_create_buffer(FILE * f);
|
||||
extern YY_BUFFER_STATE yy_scan_bytes(char *mem, ULONG size);
|
||||
extern void yy_delete_buffer(YY_BUFFER_STATE);
|
||||
extern void yy_switch_to_buffer(YY_BUFFER_STATE);
|
||||
extern ULONG lex_FloatAlloc(struct sLexFloat * tok);
|
||||
extern void lex_FloatAddRange(ULONG id, UWORD start, UWORD end);
|
||||
extern void lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end);
|
||||
extern void lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end);
|
||||
extern void lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end);
|
||||
extern void lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end);
|
||||
extern void lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end);
|
||||
extern void lex_Init(void);
|
||||
extern void lex_AddStrings(struct sLexInitString * lex);
|
||||
extern void lex_SetBuffer(char *buffer, ULONG len);
|
||||
extern ULONG yylex(void);
|
||||
extern void yyunput(char c);
|
||||
extern void yyunputstr(char *s);
|
||||
extern void yyskipbytes(ULONG count);
|
||||
extern void yyunputbytes(ULONG count);
|
||||
void setup_lexer(void);
|
||||
|
||||
void yy_set_state(enum eLexerState i);
|
||||
YY_BUFFER_STATE yy_create_buffer(FILE *f);
|
||||
YY_BUFFER_STATE yy_scan_bytes(char *mem, uint32_t size);
|
||||
void yy_delete_buffer(YY_BUFFER_STATE buf);
|
||||
void yy_switch_to_buffer(YY_BUFFER_STATE buf);
|
||||
uint32_t lex_FloatAlloc(const struct sLexFloat *tok);
|
||||
void lex_FloatAddRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatDeleteRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatAddFirstRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatDeleteFirstRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatAddSecondRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_FloatDeleteSecondRange(uint32_t id, uint16_t start, uint16_t end);
|
||||
void lex_Init(void);
|
||||
void lex_AddStrings(const struct sLexInitString *lex);
|
||||
void lex_SetBuffer(char *buffer, uint32_t len);
|
||||
int yywrap(void);
|
||||
uint32_t yylex(void);
|
||||
void yyunput(char c);
|
||||
void yyunputstr(char *s);
|
||||
void yyskipbytes(uint32_t count);
|
||||
void yyunputbytes(uint32_t count);
|
||||
|
||||
extern YY_BUFFER_STATE pCurrentBuffer;
|
||||
|
||||
#ifdef __GNUC__
|
||||
extern void strupr(char *s);
|
||||
extern void strlwr(char *s);
|
||||
#endif
|
||||
void upperstring(char *s);
|
||||
void lowerstring(char *s);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_ASM_LEXER_H */
|
||||
|
||||
@@ -1,95 +1,89 @@
|
||||
/* GB Z80 instruction groups
|
||||
|
||||
n3 = 3-bit
|
||||
n = 8-bit
|
||||
nn = 16-bit
|
||||
|
||||
*ADC A,n : 0xCE
|
||||
*ADC A,r : 0x88|r
|
||||
*ADD A,n : 0xC6
|
||||
*ADD A,r : 0x80|r
|
||||
*ADD HL,ss : 0x09|(ss<<4)
|
||||
*ADD SP,n : 0xE8
|
||||
*AND A,n : 0xE6
|
||||
*AND A,r : 0xA0|r
|
||||
*BIT n3,r : 0xCB 0x40|(n3<<3)|r
|
||||
*CALL cc,nn : 0xC4|(cc<<3)
|
||||
*CALL nn : 0xCD
|
||||
*CCF : 0x3F
|
||||
*CP A,n : 0xFE
|
||||
*CP A,r : 0xB8|r
|
||||
*CPL : 0x2F
|
||||
*DAA : 0x27
|
||||
*DEC r : 0x05|(r<<3)
|
||||
*DEC ss : 0x0B|(ss<<4)
|
||||
*DI : 0xF3
|
||||
*EI : 0xFB
|
||||
*EX HL,(SP) : 0xE3
|
||||
*HALT : 0x76
|
||||
*INC r : 0x04|(r<<3)
|
||||
*INC ss : 0x03|(ss<<4)
|
||||
*JP (HL) : 0xE9
|
||||
*JP cc,nn : 0xC2|(cc<<3)
|
||||
*JP nn : 0xC3|(cc<<3)
|
||||
*JR n : 0x18
|
||||
*JR cc,n : 0x20|(cc<<3)
|
||||
*LD (nn),SP : 0x08
|
||||
*LD ($FF00+C),A : 0xE2
|
||||
*LD ($FF00+n),A : 0xE0
|
||||
*LD (nn),A : 0xEA
|
||||
*LD (rr),A : 0x02|(rr<<4)
|
||||
*LD A,($FF00+C) : 0xF2
|
||||
*LD A,($FF00+n) : 0xF0
|
||||
*LD A,(nn) : 0xFA
|
||||
*LD A,(rr) : 0x0A|(rr<<4)
|
||||
*LD HL,(SP+n) : 0xF8
|
||||
*LD SP,HL : 0xF9
|
||||
*LD r,n : 0x06|(r<<3)
|
||||
*LD r,r' : 0x40|(r<<3)|r' // NOTE: LD (HL),(HL) not allowed
|
||||
*LD ss,nn : 0x01|(ss<<4)
|
||||
*NOP : 0x00
|
||||
*OR A,n : 0xF6
|
||||
*OR A,r : 0xB0|r
|
||||
*POP tt : 0xC1|(tt<<4)
|
||||
*PUSH tt : 0xC5|(tt<<4)
|
||||
*RES n3,r : 0xCB 0x80|(n3<<3)|r
|
||||
*RET : 0xC9
|
||||
*RET cc : 0xC0|(cc<<3)
|
||||
*RETI : 0xD9
|
||||
*RL r : 0xCB 0x10|r
|
||||
*RLA : 0x17
|
||||
*RLC r : 0xCB 0x00|r
|
||||
*RLCA : 0x07
|
||||
*RR r : 0xCB 0x18|r
|
||||
*RRA : 0x1F
|
||||
*RRC r : 0xCB 0x08|r
|
||||
*RRCA : 0x0F
|
||||
*RST n : 0xC7|n
|
||||
*SBC A,n : 0xDE
|
||||
*SBC A,r : 0x98|r
|
||||
*SCF : 0x37
|
||||
*SET n3,r : 0xCB 0xC0|(n8<<3)|r
|
||||
*SLA r : 0xCB 0x20|r
|
||||
*SRA r : 0xCB 0x28|r
|
||||
*SRL r : 0xCB 0x38|r
|
||||
*STOP : 0x10
|
||||
*SUB A,n : 0xD6
|
||||
*SUB A,r : 0x90|r
|
||||
*SWAP r : 0xCB 0x30|r
|
||||
*XOR A,n : 0xEE
|
||||
*XOR A,r : 0xA8|r
|
||||
#ifndef RGBDS_ASM_LOCALASM_H
|
||||
#define RGBDS_ASM_LOCALASM_H
|
||||
|
||||
/*
|
||||
* GB Z80 instruction groups
|
||||
*
|
||||
* n3 = 3-bit
|
||||
* n = 8-bit
|
||||
* nn = 16-bit
|
||||
*
|
||||
* ADC A,n : 0xCE
|
||||
* ADC A,r : 0x88|r
|
||||
* ADD A,n : 0xC6
|
||||
* ADD A,r : 0x80|r
|
||||
* ADD HL,ss : 0x09|(ss<<4)
|
||||
* ADD SP,n : 0xE8
|
||||
* AND A,n : 0xE6
|
||||
* AND A,r : 0xA0|r
|
||||
* BIT n3,r : 0xCB 0x40|(n3<<3)|r
|
||||
* CALL cc,nn : 0xC4|(cc<<3)
|
||||
* CALL nn : 0xCD
|
||||
* CCF : 0x3F
|
||||
* CP A,n : 0xFE
|
||||
* CP A,r : 0xB8|r
|
||||
* CPL : 0x2F
|
||||
* DAA : 0x27
|
||||
* DEC r : 0x05|(r<<3)
|
||||
* DEC ss : 0x0B|(ss<<4)
|
||||
* DI : 0xF3
|
||||
* EI : 0xFB
|
||||
* HALT : 0x76
|
||||
* INC r : 0x04|(r<<3)
|
||||
* INC ss : 0x03|(ss<<4)
|
||||
* JP HL : 0xE9
|
||||
* JP cc,nn : 0xC2|(cc<<3)
|
||||
* JP nn : 0xC3|(cc<<3)
|
||||
* JR n : 0x18
|
||||
* JR cc,n : 0x20|(cc<<3)
|
||||
* LD (nn),SP : 0x08
|
||||
* LD ($FF00+C),A : 0xE2
|
||||
* LD ($FF00+n),A : 0xE0
|
||||
* LD (nn),A : 0xEA
|
||||
* LD (rr),A : 0x02|(rr<<4) // HL+ and HL- included
|
||||
* LD A,($FF00+C) : 0xF2
|
||||
* LD A,($FF00+n) : 0xF0
|
||||
* LD A,(nn) : 0xFA
|
||||
* LD A,(rr) : 0x0A|(rr<<4) // HL+ and HL- included
|
||||
* LD HL,SP+n : 0xF8
|
||||
* LD SP,HL : 0xF9
|
||||
* LD r,n : 0x06|(r<<3)
|
||||
* LD r,r' : 0x40|(r<<3)|r' // NOTE: LD (HL),(HL) not allowed
|
||||
* LD ss,nn : 0x01|(ss<<4)
|
||||
* NOP : 0x00
|
||||
* OR A,n : 0xF6
|
||||
* OR A,r : 0xB0|r
|
||||
* POP tt : 0xC1|(tt<<4)
|
||||
* PUSH tt : 0xC5|(tt<<4)
|
||||
* RES n3,r : 0xCB 0x80|(n3<<3)|r
|
||||
* RET : 0xC9
|
||||
* RET cc : 0xC0|(cc<<3)
|
||||
* RETI : 0xD9
|
||||
* RL r : 0xCB 0x10|r
|
||||
* RLA : 0x17
|
||||
* RLC r : 0xCB 0x00|r
|
||||
* RLCA : 0x07
|
||||
* RR r : 0xCB 0x18|r
|
||||
* RRA : 0x1F
|
||||
* RRC r : 0xCB 0x08|r
|
||||
* RRCA : 0x0F
|
||||
* RST n : 0xC7|n
|
||||
* SBC A,n : 0xDE
|
||||
* SBC A,r : 0x98|r
|
||||
* SCF : 0x37
|
||||
* SET n3,r : 0xCB 0xC0|(n8<<3)|r
|
||||
* SLA r : 0xCB 0x20|r
|
||||
* SRA r : 0xCB 0x28|r
|
||||
* SRL r : 0xCB 0x38|r
|
||||
* STOP : 0x10 0x00
|
||||
* SUB A,n : 0xD6
|
||||
* SUB A,r : 0x90|r
|
||||
* SWAP r : 0xCB 0x30|r
|
||||
* XOR A,n : 0xEE
|
||||
* XOR A,r : 0xA8|r
|
||||
*/
|
||||
|
||||
#define MAXSECTIONSIZE 0x4000
|
||||
|
||||
#define NAME_DB "db"
|
||||
#define NAME_DW "dw"
|
||||
#define NAME_RB "rb"
|
||||
#define NAME_RW "rw"
|
||||
|
||||
/* "r" defs */
|
||||
|
||||
enum {
|
||||
REG_B = 0,
|
||||
REG_C,
|
||||
@@ -100,36 +94,30 @@ enum {
|
||||
REG_HL_IND,
|
||||
REG_A
|
||||
};
|
||||
/* "rr" defs */
|
||||
|
||||
/* "rr" defs */
|
||||
enum {
|
||||
REG_BC_IND = 0,
|
||||
REG_DE_IND,
|
||||
REG_HL_INDINC,
|
||||
REG_HL_INDDEC,
|
||||
};
|
||||
/* "ss" defs */
|
||||
|
||||
/* "ss" defs (SP) and "tt" defs (AF) */
|
||||
enum {
|
||||
REG_BC = 0,
|
||||
REG_DE,
|
||||
REG_HL,
|
||||
REG_SP
|
||||
REG_DE = 1,
|
||||
REG_HL = 2,
|
||||
REG_SP = 3,
|
||||
REG_AF = 3
|
||||
};
|
||||
/* "tt" defs */
|
||||
|
||||
/*
|
||||
#define REG_BC 0
|
||||
#define REG_DE 1
|
||||
#define REG_HL 2
|
||||
*/
|
||||
#define REG_AF 3
|
||||
|
||||
/* "cc" defs */
|
||||
|
||||
enum {
|
||||
CC_NZ = 0,
|
||||
CC_Z,
|
||||
CC_NC,
|
||||
CC_C
|
||||
};
|
||||
|
||||
#endif /* RGBDS_ASM_LOCALASM_H */
|
||||
|
||||
@@ -1,36 +1,63 @@
|
||||
#ifndef RGBDS_MAIN_H
|
||||
#define RGBDS_MAIN_H
|
||||
#ifndef RGBDS_MAIN_H
|
||||
#define RGBDS_MAIN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "extern/stdnoreturn.h"
|
||||
|
||||
struct sOptions {
|
||||
char gbgfx[4];
|
||||
char binary[2];
|
||||
SLONG fillchar;
|
||||
int32_t fillchar;
|
||||
bool verbose;
|
||||
bool haltnop;
|
||||
//-1 == random
|
||||
bool exportall;
|
||||
bool warnings; /* True to enable warnings, false to disable them. */
|
||||
};
|
||||
|
||||
extern char *tzNewMacro;
|
||||
extern ULONG ulNewMacroSize;
|
||||
extern SLONG nGBGfxID;
|
||||
extern SLONG nBinaryID;
|
||||
extern uint32_t ulNewMacroSize;
|
||||
extern int32_t nGBGfxID;
|
||||
extern int32_t nBinaryID;
|
||||
|
||||
extern struct sOptions DefaultOptions;
|
||||
extern struct sOptions CurrentOptions;
|
||||
extern void opt_Push(void);
|
||||
extern void opt_Pop(void);
|
||||
extern void opt_Parse(char *s);
|
||||
|
||||
void fatalerror(const char *fmt, ...);
|
||||
extern FILE *dependfile;
|
||||
|
||||
void opt_Push(void);
|
||||
void opt_Pop(void);
|
||||
void opt_Parse(char *s);
|
||||
|
||||
/*
|
||||
* Used for errors that compromise the whole assembly process by affecting the
|
||||
* folliwing code, potencially making the assembler generate errors caused by
|
||||
* the first one and unrelated to the code that the assembler complains about.
|
||||
* It is also used when the assembler goes into an invalid state (for example,
|
||||
* when it fails to allocate memory).
|
||||
*/
|
||||
noreturn void fatalerror(const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* Used for errors that make it impossible to assemble correctly, but don't
|
||||
* affect the following code. The code will fail to assemble but the user will
|
||||
* get a list of all errors at the end, making it easier to fix all of them at
|
||||
* once.
|
||||
*/
|
||||
void yyerror(const char *fmt, ...);
|
||||
|
||||
#define YY_FATAL_ERROR fatalerror
|
||||
/*
|
||||
* Used to warn the user about problems that don't prevent the generation of
|
||||
* valid code.
|
||||
*/
|
||||
void warning(const char *fmt, ...);
|
||||
|
||||
#ifdef YYLMAX
|
||||
#undef YYLMAX
|
||||
#define YY_FATAL_ERROR fatalerror
|
||||
|
||||
#ifdef YYLMAX
|
||||
#undef YYLMAX
|
||||
#endif
|
||||
#define YYLMAX 65536
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_MAIN_H */
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
#ifndef RGBDS_ASM_LINK_H
|
||||
#define RGBDS_ASM_LINK_H
|
||||
|
||||
/* RGB0 .obj format:
|
||||
*
|
||||
* Header
|
||||
* Symbols
|
||||
* Sections
|
||||
*
|
||||
* Header:
|
||||
* "RGB0"
|
||||
* LONG NumberOfSymbols
|
||||
* LONG NumberOfSections
|
||||
*
|
||||
* Symbols:
|
||||
* Symbol[NumberOfSymbols]
|
||||
*
|
||||
* Symbol:
|
||||
* char Name (NULL terminated)
|
||||
* char nType
|
||||
* if( nType!=SYM_IMPORT )
|
||||
* {
|
||||
* LONG SectionID
|
||||
* LONG Offset
|
||||
* }
|
||||
*
|
||||
* Sections:
|
||||
* Section[NumberOfSections]
|
||||
*
|
||||
* Section:
|
||||
* LONG SizeInBytes
|
||||
* char Type
|
||||
* if( Type!=WRAM0 )
|
||||
* {
|
||||
* char Data[SizeInBytes]
|
||||
* Patches
|
||||
* }
|
||||
*
|
||||
* Patches:
|
||||
* LONG NumberOfPatches
|
||||
* Patch[NumberOfPatches]
|
||||
*
|
||||
* Patch:
|
||||
* char Filename NULL-terminated
|
||||
* LONG LineNo
|
||||
* LONG Offset
|
||||
* char Type
|
||||
* LONG RpnByteSize
|
||||
* Rpn[RpnByteSize]
|
||||
*
|
||||
* Rpn:
|
||||
* Operators: 0x00-0x7F
|
||||
* Constants: 0x80 0x00000000
|
||||
* Symbols : 0x81 0x00000000
|
||||
*
|
||||
*/
|
||||
|
||||
enum {
|
||||
RPN_ADD = 0,
|
||||
RPN_SUB,
|
||||
RPN_MUL,
|
||||
RPN_DIV,
|
||||
RPN_MOD,
|
||||
RPN_UNSUB,
|
||||
|
||||
RPN_OR,
|
||||
RPN_AND,
|
||||
RPN_XOR,
|
||||
RPN_UNNOT,
|
||||
|
||||
RPN_LOGAND,
|
||||
RPN_LOGOR,
|
||||
RPN_LOGUNNOT,
|
||||
|
||||
RPN_LOGEQ,
|
||||
RPN_LOGNE,
|
||||
RPN_LOGGT,
|
||||
RPN_LOGLT,
|
||||
RPN_LOGGE,
|
||||
RPN_LOGLE,
|
||||
|
||||
RPN_SHL,
|
||||
RPN_SHR,
|
||||
|
||||
RPN_BANK,
|
||||
|
||||
RPN_HRAM,
|
||||
|
||||
RPN_PCEZP,
|
||||
|
||||
RPN_RANGECHECK,
|
||||
|
||||
RPN_CONST = 0x80,
|
||||
RPN_SYM = 0x81
|
||||
};
|
||||
|
||||
enum {
|
||||
SECT_WRAM0 = 0,
|
||||
SECT_VRAM,
|
||||
SECT_ROMX,
|
||||
SECT_ROM0,
|
||||
SECT_HRAM,
|
||||
SECT_WRAMX,
|
||||
SECT_SRAM
|
||||
};
|
||||
|
||||
enum {
|
||||
SYM_LOCAL = 0,
|
||||
SYM_IMPORT,
|
||||
SYM_EXPORT
|
||||
};
|
||||
|
||||
enum {
|
||||
PATCH_BYTE = 0,
|
||||
PATCH_WORD_L,
|
||||
PATCH_LONG_L,
|
||||
PATCH_WORD_B,
|
||||
PATCH_LONG_B
|
||||
};
|
||||
#endif
|
||||
@@ -1,21 +1,21 @@
|
||||
#ifndef RGBDS_ASM_MATH_H
|
||||
#define RGBDS_ASM_MATH_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void math_DefinePI(void);
|
||||
void math_Print(SLONG i);
|
||||
SLONG math_Sin(SLONG i);
|
||||
SLONG math_Cos(SLONG i);
|
||||
SLONG math_Tan(SLONG i);
|
||||
SLONG math_ASin(SLONG i);
|
||||
SLONG math_ACos(SLONG i);
|
||||
SLONG math_ATan(SLONG i);
|
||||
SLONG math_ATan2(SLONG i, SLONG j);
|
||||
SLONG math_Mul(SLONG i, SLONG j);
|
||||
SLONG math_Div(SLONG i, SLONG j);
|
||||
SLONG math_Round(SLONG i);
|
||||
SLONG math_Ceil(SLONG i);
|
||||
SLONG math_Floor(SLONG i);
|
||||
void math_Print(int32_t i);
|
||||
int32_t math_Sin(int32_t i);
|
||||
int32_t math_Cos(int32_t i);
|
||||
int32_t math_Tan(int32_t i);
|
||||
int32_t math_ASin(int32_t i);
|
||||
int32_t math_ACos(int32_t i);
|
||||
int32_t math_ATan(int32_t i);
|
||||
int32_t math_ATan2(int32_t i, int32_t j);
|
||||
int32_t math_Mul(int32_t i, int32_t j);
|
||||
int32_t math_Div(int32_t i, int32_t j);
|
||||
int32_t math_Round(int32_t i);
|
||||
int32_t math_Ceil(int32_t i);
|
||||
int32_t math_Floor(int32_t i);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_ASM_MATH_H */
|
||||
|
||||
@@ -1,38 +1,45 @@
|
||||
#ifndef RGBDS_ASM_OUTPUT_H
|
||||
#define RGBDS_ASM_OUTPUT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "asm/rpn.h"
|
||||
#include "types.h"
|
||||
|
||||
struct Section {
|
||||
char *pzName;
|
||||
UBYTE nType;
|
||||
ULONG nPC;
|
||||
ULONG nOrg;
|
||||
ULONG nBank;
|
||||
uint8_t nType;
|
||||
uint32_t nPC;
|
||||
uint32_t nOrg;
|
||||
uint32_t nBank;
|
||||
uint32_t nAlign;
|
||||
struct Section *pNext;
|
||||
struct Patch *pPatches;
|
||||
struct Charmap *charmap;
|
||||
UBYTE *tData;
|
||||
uint8_t *tData;
|
||||
};
|
||||
|
||||
extern char *tzObjectname;
|
||||
|
||||
void out_PrepPass2(void);
|
||||
void out_SetFileName(char *s);
|
||||
void out_NewSection(char *pzName, ULONG secttype);
|
||||
void out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank);
|
||||
void out_AbsByte(int b);
|
||||
void out_AbsByteGroup(char *s, int length);
|
||||
void out_RelByte(struct Expression * expr);
|
||||
void out_RelWord(struct Expression * expr);
|
||||
void out_PCRelByte(struct Expression * expr);
|
||||
void out_NewSection(char *pzName, uint32_t secttype);
|
||||
void out_NewAbsSection(char *pzName, uint32_t secttype, int32_t org,
|
||||
int32_t bank);
|
||||
void out_NewAlignedSection(char *pzName, uint32_t secttype, int32_t alignment,
|
||||
int32_t bank);
|
||||
void out_AbsByte(int32_t b);
|
||||
void out_AbsByteGroup(char *s, int32_t length);
|
||||
void out_RelByte(struct Expression *expr);
|
||||
void out_RelWord(struct Expression *expr);
|
||||
void out_PCRelByte(struct Expression *expr);
|
||||
void out_WriteObject(void);
|
||||
void out_Skip(int skip);
|
||||
void out_Skip(int32_t skip);
|
||||
void out_BinaryFile(char *s);
|
||||
void out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length);
|
||||
void out_BinaryFileSlice(char *s, int32_t start_pos, int32_t length);
|
||||
void out_String(char *s);
|
||||
void out_AbsLong(SLONG b);
|
||||
void out_RelLong(struct Expression * expr);
|
||||
void out_AbsLong(int32_t b);
|
||||
void out_RelLong(struct Expression *expr);
|
||||
void out_PushSection(void);
|
||||
void out_PopSection(void);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_ASM_OUTPUT_H */
|
||||
|
||||
@@ -1,82 +1,67 @@
|
||||
#ifndef RGBDS_ASM_RPN_H
|
||||
#define RGBDS_ASM_RPN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct Expression {
|
||||
SLONG nVal;
|
||||
UBYTE tRPN[256];
|
||||
ULONG nRPNLength;
|
||||
ULONG nRPNOut;
|
||||
ULONG isReloc;
|
||||
ULONG isPCRel;
|
||||
int32_t nVal;
|
||||
uint8_t tRPN[256];
|
||||
uint32_t nRPNLength;
|
||||
uint32_t nRPNOut;
|
||||
uint32_t isReloc;
|
||||
uint32_t isPCRel;
|
||||
};
|
||||
|
||||
ULONG rpn_isReloc(struct Expression * expr);
|
||||
ULONG rpn_isPCRelative(struct Expression * expr);
|
||||
void rpn_Symbol(struct Expression * expr, char *tzSym);
|
||||
void rpn_Number(struct Expression * expr, ULONG i);
|
||||
void rpn_LOGNOT(struct Expression * expr, struct Expression * src1);
|
||||
void
|
||||
rpn_LOGOR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_LOGAND(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_LOGGT(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_LOGLT(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_LOGGE(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_LOGLE(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_LOGNE(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_ADD(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_SUB(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_XOR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_OR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_AND(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_SHL(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_SHR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_MUL(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_DIV(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void
|
||||
rpn_MOD(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2);
|
||||
void rpn_UNNEG(struct Expression * expr, struct Expression * src);
|
||||
void rpn_UNNOT(struct Expression * expr, struct Expression * src);
|
||||
UWORD rpn_PopByte(struct Expression * expr);
|
||||
void rpn_Bank(struct Expression * expr, char *tzSym);
|
||||
void rpn_Reset(struct Expression * expr);
|
||||
int
|
||||
rpn_RangeCheck(struct Expression * expr, struct Expression * src, SLONG low,
|
||||
SLONG high);
|
||||
void rpn_CheckHRAM(struct Expression * expr, struct Expression * src1);
|
||||
uint32_t rpn_isReloc(const struct Expression *expr);
|
||||
uint32_t rpn_isPCRelative(const struct Expression *expr);
|
||||
void rpn_Symbol(struct Expression *expr, char *tzSym);
|
||||
void rpn_Number(struct Expression *expr, uint32_t i);
|
||||
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_LOGOR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_LOGAND(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_LOGEQU(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_LOGGT(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_LOGLT(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_LOGGE(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_LOGLE(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_LOGNE(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_ADD(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_SUB(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_XOR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_OR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_AND(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_SHL(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_SHR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_MUL(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_DIV(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_MOD(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_HIGH(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_LOW(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_UNNEG(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_UNNOT(struct Expression *expr, const struct Expression *src);
|
||||
uint16_t rpn_PopByte(struct Expression *expr);
|
||||
void rpn_BankSymbol(struct Expression *expr, char *tzSym);
|
||||
void rpn_BankSection(struct Expression *expr, char *tzSectionName);
|
||||
void rpn_BankSelf(struct Expression *expr);
|
||||
void rpn_Reset(struct Expression *expr);
|
||||
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_ASM_RPN_H */
|
||||
|
||||
@@ -1,41 +1,50 @@
|
||||
#ifndef RGBDS_SYMBOL_H
|
||||
#define RGBDS_SYMBOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define HASHSIZE (1 << 16)
|
||||
#define MAXSYMLEN 256
|
||||
#define HASHSIZE (1 << 16)
|
||||
#define MAXSYMLEN 256
|
||||
|
||||
struct sSymbol {
|
||||
char tzName[MAXSYMLEN + 1];
|
||||
SLONG nValue;
|
||||
ULONG nType;
|
||||
int32_t nValue;
|
||||
uint32_t nType;
|
||||
struct sSymbol *pScope;
|
||||
struct sSymbol *pNext;
|
||||
struct Section *pSection;
|
||||
ULONG ulMacroSize;
|
||||
uint32_t ulMacroSize;
|
||||
char *pMacro;
|
||||
SLONG(*Callback) (struct sSymbol *);
|
||||
int32_t (*Callback)(struct sSymbol *);
|
||||
char tzFileName[_MAX_PATH + 1]; /* File where the symbol was defined. */
|
||||
uint32_t nFileLine; /* Line where the symbol was defined. */
|
||||
};
|
||||
#define SYMF_RELOC 0x001 /* symbol will be reloc'ed during
|
||||
* linking, it's absolute value is
|
||||
* unknown */
|
||||
#define SYMF_EQU 0x002 /* symbol is defined using EQU, will
|
||||
* not be changed during linking */
|
||||
#define SYMF_SET 0x004 /* symbol is (re)defined using SET,
|
||||
* will not be changed during linking */
|
||||
#define SYMF_EXPORT 0x008 /* symbol should be exported */
|
||||
#define SYMF_IMPORT 0x010 /* symbol is imported, it's value is
|
||||
* unknown */
|
||||
#define SYMF_LOCAL 0x020 /* symbol is a local symbol */
|
||||
#define SYMF_DEFINED 0x040 /* symbol has been defined, not only
|
||||
* referenced */
|
||||
#define SYMF_MACRO 0x080 /* symbol is a macro */
|
||||
#define SYMF_STRING 0x100 /* symbol is a stringsymbol */
|
||||
#define SYMF_CONST 0x200 /* symbol has a constant value, will
|
||||
* not be changed during linking */
|
||||
|
||||
ULONG calchash(char *s);
|
||||
/* Symbol will be relocated during linking, it's absolute value is unknown */
|
||||
#define SYMF_RELOC 0x001
|
||||
/* Symbol is defined using EQU, will not be changed during linking */
|
||||
#define SYMF_EQU 0x002
|
||||
/* Symbol is (re)defined using SET, will not be changed during linking */
|
||||
#define SYMF_SET 0x004
|
||||
/* Symbol should be exported */
|
||||
#define SYMF_EXPORT 0x008
|
||||
/* Symbol is imported, it's value is unknown */
|
||||
#define SYMF_IMPORT 0x010
|
||||
/* Symbol is a local symbol */
|
||||
#define SYMF_LOCAL 0x020
|
||||
/* Symbol has been defined, not only referenced */
|
||||
#define SYMF_DEFINED 0x040
|
||||
/* Symbol is a macro */
|
||||
#define SYMF_MACRO 0x080
|
||||
/* Symbol is a stringsymbol */
|
||||
#define SYMF_STRING 0x100
|
||||
/* Symbol has a constant value, will not be changed during linking */
|
||||
#define SYMF_CONST 0x200
|
||||
|
||||
uint32_t calchash(char *s);
|
||||
void sym_SetExportAll(uint8_t set);
|
||||
void sym_PrepPass1(void);
|
||||
void sym_PrepPass2(void);
|
||||
void sym_AddLocalReloc(char *tzSym);
|
||||
@@ -49,26 +58,30 @@ void sym_SaveCurrentMacroArgs(char *save[]);
|
||||
void sym_RestoreCurrentMacroArgs(char *save[]);
|
||||
void sym_UseNewMacroArgs(void);
|
||||
void sym_FreeCurrentMacroArgs(void);
|
||||
void sym_AddEqu(char *tzSym, SLONG value);
|
||||
void sym_AddSet(char *tzSym, SLONG value);
|
||||
void sym_AddEqu(char *tzSym, int32_t value);
|
||||
void sym_AddSet(char *tzSym, int32_t value);
|
||||
void sym_Init(void);
|
||||
ULONG sym_GetConstantValue(char *s);
|
||||
void sym_Import(char *tzSym);
|
||||
ULONG sym_isConstant(char *s);
|
||||
uint32_t sym_GetConstantValue(char *s);
|
||||
uint32_t sym_isConstant(char *s);
|
||||
struct sSymbol *sym_FindSymbol(char *tzName);
|
||||
void sym_Global(char *tzSym);
|
||||
char *sym_FindMacroArg(SLONG i);
|
||||
char *sym_FindMacroArg(int32_t i);
|
||||
char *sym_GetStringValue(char *tzSym);
|
||||
void sym_UseCurrentMacroArgs(void);
|
||||
void sym_SetMacroArgID(ULONG nMacroCount);
|
||||
ULONG sym_isString(char *tzSym);
|
||||
void sym_SetMacroArgID(uint32_t nMacroCount);
|
||||
uint32_t sym_isString(char *tzSym);
|
||||
void sym_AddMacro(char *tzSym);
|
||||
void sym_ShiftCurrentMacroArgs(void);
|
||||
void sym_AddString(char *tzSym, char *tzValue);
|
||||
ULONG sym_GetValue(char *s);
|
||||
ULONG sym_GetDefinedValue(char *s);
|
||||
ULONG sym_isDefined(char *tzName);
|
||||
uint32_t sym_GetValue(char *s);
|
||||
uint32_t sym_GetDefinedValue(char *s);
|
||||
uint32_t sym_isDefined(char *tzName);
|
||||
void sym_Purge(char *tzName);
|
||||
ULONG sym_isConstDefined(char *tzName);
|
||||
uint32_t sym_isConstDefined(char *tzName);
|
||||
int32_t sym_IsRelocDiffDefined(char *tzSym1, char *tzSym2);
|
||||
|
||||
#endif
|
||||
/* Functions to save and restore the current symbol scope. */
|
||||
struct sSymbol *sym_GetCurrentSymbolScope(void);
|
||||
void sym_SetCurrentSymbolScope(struct sSymbol *pNewScope);
|
||||
|
||||
#endif /* RGBDS_SYMBOL_H */
|
||||
|
||||
36
include/common.h
Normal file
36
include/common.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef RGBDS_COMMON_H
|
||||
#define RGBDS_COMMON_H
|
||||
|
||||
#define RGBDS_OBJECT_VERSION_STRING "RGB6"
|
||||
|
||||
enum eBankCount {
|
||||
BANK_COUNT_ROM0 = 1,
|
||||
BANK_COUNT_ROMX = 511,
|
||||
BANK_COUNT_WRAM0 = 1,
|
||||
BANK_COUNT_WRAMX = 7,
|
||||
BANK_COUNT_VRAM = 2,
|
||||
BANK_COUNT_OAM = 1,
|
||||
BANK_COUNT_HRAM = 1,
|
||||
BANK_COUNT_SRAM = 16
|
||||
};
|
||||
|
||||
enum eBankGBCount {
|
||||
BANK_MIN_ROM0 = 0,
|
||||
BANK_MAX_ROM0 = BANK_COUNT_ROM0 + BANK_MIN_ROM0 - 1,
|
||||
BANK_MIN_ROMX = 1,
|
||||
BANK_MAX_ROMX = BANK_COUNT_ROMX + BANK_MIN_ROMX - 1,
|
||||
BANK_MIN_WRAM0 = 0,
|
||||
BANK_MAX_WRAM0 = BANK_COUNT_WRAM0 + BANK_MIN_WRAM0 - 1,
|
||||
BANK_MIN_WRAMX = 1,
|
||||
BANK_MAX_WRAMX = BANK_COUNT_WRAMX + BANK_MIN_WRAMX - 1,
|
||||
BANK_MIN_VRAM = 0,
|
||||
BANK_MAX_VRAM = BANK_COUNT_VRAM + BANK_MIN_VRAM - 1,
|
||||
BANK_MIN_OAM = 0,
|
||||
BANK_MAX_OAM = BANK_COUNT_OAM + BANK_MIN_OAM - 1,
|
||||
BANK_MIN_HRAM = 0,
|
||||
BANK_MAX_HRAM = BANK_COUNT_HRAM + BANK_MIN_HRAM - 1,
|
||||
BANK_MIN_SRAM = 0,
|
||||
BANK_MAX_SRAM = BANK_COUNT_SRAM + BANK_MIN_SRAM - 1
|
||||
};
|
||||
|
||||
#endif /* RGBDS_COMMON_H */
|
||||
25
include/extern/err.h
vendored
25
include/extern/err.h
vendored
@@ -2,10 +2,13 @@
|
||||
#define EXTERN_ERR_H
|
||||
|
||||
#ifdef ERR_IN_LIBC
|
||||
|
||||
#include <err.h>
|
||||
#else
|
||||
|
||||
#else /* ERR_IN_LIBC */
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "extern/stdnoreturn.h"
|
||||
|
||||
#define warn rgbds_warn
|
||||
@@ -18,16 +21,16 @@
|
||||
#define errx rgbds_errx
|
||||
#define verrx rgbds_verrx
|
||||
|
||||
void warn(const char *, ...);
|
||||
void vwarn(const char *, va_list);
|
||||
void warnx(const char *, ...);
|
||||
void vwarnx(const char *, va_list);
|
||||
void warn(const char *fmt, ...);
|
||||
void vwarn(const char *fmt, va_list ap);
|
||||
void warnx(const char *fmt, ...);
|
||||
void vwarnx(const char *fmt, va_list ap);
|
||||
|
||||
noreturn void err(int, const char *, ...);
|
||||
noreturn void verr(int, const char *, va_list);
|
||||
noreturn void errx(int, const char *, ...);
|
||||
noreturn void verrx(int, const char *, va_list);
|
||||
noreturn void err(int status, const char *fmt, ...);
|
||||
noreturn void verr(int status, const char *fmt, va_list ap);
|
||||
noreturn void errx(int status, const char *fmt, ...);
|
||||
noreturn void verrx(int status, const char *fmt, va_list ap);
|
||||
|
||||
#endif
|
||||
#endif /* ERR_IN_LIBC */
|
||||
|
||||
#endif
|
||||
#endif /* EXTERN_ERR_H */
|
||||
|
||||
9
include/extern/reallocarray.h
vendored
9
include/extern/reallocarray.h
vendored
@@ -2,13 +2,14 @@
|
||||
#define EXTERN_REALLOCARRAY_H
|
||||
|
||||
#ifdef REALLOCARRAY_IN_LIBC
|
||||
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
|
||||
#else /* REALLOCARRAY_IN_LIBC */
|
||||
|
||||
#define reallocarray rgbds_reallocarray
|
||||
|
||||
void *reallocarray(void *, size_t, size_t);
|
||||
|
||||
#endif
|
||||
#endif /* REALLOCARRAY_IN_LIBC */
|
||||
|
||||
#endif
|
||||
#endif /* EXTERN_REALLOCARRAY_H */
|
||||
|
||||
25
include/extern/stdnoreturn.h
vendored
25
include/extern/stdnoreturn.h
vendored
@@ -1,16 +1,21 @@
|
||||
#ifndef EXTERN_STDNORETURN_H
|
||||
#define EXTERN_STDNORETURN_H
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
/* C11 or newer */
|
||||
#define noreturn _Noreturn
|
||||
/* C11 or newer */
|
||||
#define noreturn _Noreturn
|
||||
#elif __cplusplus >= 201103L
|
||||
/* C++11 or newer */
|
||||
#define noreturn [[noreturn]]
|
||||
/* C++11 or newer */
|
||||
#define noreturn [[noreturn]]
|
||||
#elif __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ >= 5))
|
||||
/* GCC 2.5 or newer */
|
||||
#define noreturn __attribute__ ((noreturn))
|
||||
/* GCC 2.5 or newer */
|
||||
#define noreturn __attribute__ ((noreturn))
|
||||
#elif _MSC_VER >= 1310
|
||||
/* MS Visual Studio 2003/.NET Framework 1.1 or newer */
|
||||
#define noreturn _declspec( noreturn)
|
||||
/* MS Visual Studio 2003/.NET Framework 1.1 or newer */
|
||||
#define noreturn _declspec(noreturn)
|
||||
#else
|
||||
/* unsupported, but no need to throw a fit */
|
||||
#define noreturn
|
||||
/* Unsupported, but no need to throw a fit */
|
||||
#define noreturn
|
||||
#endif
|
||||
|
||||
#endif /* EXTERN_STDNORETURN_H */
|
||||
|
||||
18
include/extern/strl.h
vendored
18
include/extern/strl.h
vendored
@@ -1,13 +1,17 @@
|
||||
#ifndef STRL_H
|
||||
#define STRL_H
|
||||
#ifndef EXTERN_STRL_H
|
||||
#define EXTERN_STRL_H
|
||||
|
||||
#ifdef STRL_IN_LIBC
|
||||
|
||||
#include <string.h>
|
||||
#else
|
||||
|
||||
#else /* STRL_IN_LIBC */
|
||||
|
||||
#define strlcpy rgbds_strlcpy
|
||||
#define strlcat rgbds_strlcat
|
||||
size_t strlcpy(char *, const char *, size_t);
|
||||
size_t strlcat(char *, const char *, size_t);
|
||||
#endif
|
||||
size_t strlcpy(char *dst, const char *src, size_t dsize);
|
||||
size_t strlcat(char *dst, const char *src, size_t dsize);
|
||||
|
||||
#endif
|
||||
#endif /* STRL_IN_LIBC */
|
||||
|
||||
#endif /* EXTERN_STRL_H */
|
||||
|
||||
26
include/extern/version.h
vendored
Normal file
26
include/extern/version.h
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.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 EXTERN_VERSION_H
|
||||
#define EXTERN_VERSION_H
|
||||
|
||||
#define PACKAGE_VERSION_MAJOR (0)
|
||||
#define PACKAGE_VERSION_MINOR (3)
|
||||
#define PACKAGE_VERSION_PATCH (4)
|
||||
|
||||
const char *get_package_version_string(void);
|
||||
|
||||
#endif /* EXTERN_VERSION_H */
|
||||
33
include/gfx/gb.h
Normal file
33
include/gfx/gb.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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(const struct PNGImage png, struct GBImage *gb);
|
||||
void output_file(const struct Options opts, const struct GBImage gb);
|
||||
int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
|
||||
int tile_size);
|
||||
void create_tilemap(const struct Options opts, struct GBImage *gb,
|
||||
struct Tilemap *tilemap);
|
||||
void output_tilemap_file(const struct Options opts,
|
||||
const struct Tilemap tilemap);
|
||||
void output_palette_file(const struct Options opts, const 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 /* RGBDS_GFX_MAIN_H */
|
||||
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(const struct Options opts, struct PNGImage *img);
|
||||
void get_text(struct PNGImage *png);
|
||||
void set_text(const struct PNGImage *png);
|
||||
void output_png_file(const struct Options opts, const struct PNGImage *png);
|
||||
void free_png_data(const struct PNGImage *png);
|
||||
|
||||
#endif /* RGBDS_GFX_PNG_H */
|
||||
@@ -1,22 +1,45 @@
|
||||
#ifndef RGBDS_LINK_ASSIGN_H
|
||||
#define RGBDS_LINK_ASSIGN_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "mylink.h"
|
||||
|
||||
/* Bank numbers as seen by the linker */
|
||||
enum eBankDefine {
|
||||
BANK_ROM0 = 0,
|
||||
BANK_WRAM0 = 512,
|
||||
BANK_WRAMX,
|
||||
BANK_VRAM = 520,
|
||||
BANK_HRAM = 522,
|
||||
BANK_SRAM = 523
|
||||
BANK_INDEX_ROM0 = 0,
|
||||
BANK_INDEX_ROMX = BANK_INDEX_ROM0 + BANK_COUNT_ROM0,
|
||||
BANK_INDEX_WRAM0 = BANK_INDEX_ROMX + BANK_COUNT_ROMX,
|
||||
BANK_INDEX_WRAMX = BANK_INDEX_WRAM0 + BANK_COUNT_WRAM0,
|
||||
BANK_INDEX_VRAM = BANK_INDEX_WRAMX + BANK_COUNT_WRAMX,
|
||||
BANK_INDEX_OAM = BANK_INDEX_VRAM + BANK_COUNT_VRAM,
|
||||
BANK_INDEX_HRAM = BANK_INDEX_OAM + BANK_COUNT_OAM,
|
||||
BANK_INDEX_SRAM = BANK_INDEX_HRAM + BANK_COUNT_HRAM,
|
||||
BANK_INDEX_MAX = BANK_INDEX_SRAM + BANK_COUNT_SRAM
|
||||
};
|
||||
#define MAXBANKS 527
|
||||
|
||||
extern SLONG area_Avail(SLONG bank);
|
||||
extern void AssignSections(void);
|
||||
extern void CreateSymbolTable(void);
|
||||
extern SLONG MaxBankUsed;
|
||||
extern SLONG MaxAvail[MAXBANKS];
|
||||
extern int32_t MaxBankUsed;
|
||||
extern int32_t MaxAvail[BANK_INDEX_MAX];
|
||||
|
||||
#endif
|
||||
int32_t area_Avail(int32_t bank);
|
||||
void AssignSections(void);
|
||||
void CreateSymbolTable(void);
|
||||
struct sSection *GetSectionByName(const char *name);
|
||||
int32_t IsSectionNameInUse(const char *name);
|
||||
void SetLinkerscriptName(char *tzLinkerscriptFile);
|
||||
int32_t IsSectionSameTypeBankAndFloating(const char *name,
|
||||
enum eSectionType type, int32_t bank);
|
||||
uint32_t AssignSectionAddressAndBankByName(const char *name, uint32_t address,
|
||||
int32_t bank);
|
||||
|
||||
int BankIndexIsROM0(int32_t bank);
|
||||
int BankIndexIsROMX(int32_t bank);
|
||||
int BankIndexIsWRAM0(int32_t bank);
|
||||
int BankIndexIsWRAMX(int32_t bank);
|
||||
int BankIndexIsVRAM(int32_t bank);
|
||||
int BankIndexIsOAM(int32_t bank);
|
||||
int BankIndexIsHRAM(int32_t bank);
|
||||
int BankIndexIsSRAM(int32_t bank);
|
||||
|
||||
#endif /* RGBDS_LINK_ASSIGN_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef RGBDS_LINK_LIBRARY_H
|
||||
#define RGBDS_LINK_LIBRARY_H
|
||||
#ifndef RGBDS_LINK_LIBRARY_H
|
||||
#define RGBDS_LINK_LIBRARY_H
|
||||
|
||||
extern void AddNeededModules(void);
|
||||
void AddNeededModules(void);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_LIBRARY_H */
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef RGBDS_LINK_MAIN_H
|
||||
#define RGBDS_LINK_MAIN_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
extern SLONG fillchar;
|
||||
extern char smartlinkstartsymbol[256];
|
||||
extern int32_t fillchar;
|
||||
extern char *smartlinkstartsymbol;
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_MAIN_H */
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#ifndef RGBDS_LINK_MAPFILE_H
|
||||
#define RGBDS_LINK_MAPFILE_H
|
||||
#ifndef RGBDS_LINK_MAPFILE_H
|
||||
#define RGBDS_LINK_MAPFILE_H
|
||||
|
||||
extern void SetMapfileName(char *name);
|
||||
extern void SetSymfileName(char *name);
|
||||
extern void CloseMapfile(void);
|
||||
extern void MapfileWriteSection(struct sSection * pSect);
|
||||
extern void MapfileInitBank(SLONG bank);
|
||||
extern void MapfileCloseBank(SLONG slack);
|
||||
#include <stdint.h>
|
||||
|
||||
#endif
|
||||
void SetMapfileName(char *name);
|
||||
void SetSymfileName(char *name);
|
||||
void CloseMapfile(void);
|
||||
void MapfileWriteSection(const struct sSection *pSect);
|
||||
void MapfileInitBank(int32_t bank);
|
||||
void MapfileCloseBank(int32_t slack);
|
||||
|
||||
#endif /* RGBDS_LINK_MAPFILE_H */
|
||||
|
||||
@@ -1,114 +1,60 @@
|
||||
#ifndef RGBDS_LINK_LINK_H
|
||||
#define RGBDS_LINK_LINK_H
|
||||
|
||||
#ifndef _MAX_PATH
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "linkdefs.h"
|
||||
|
||||
extern SLONG options;
|
||||
#define OPT_SMALL 0x01
|
||||
extern int32_t options;
|
||||
|
||||
#define OPT_TINY 0x01
|
||||
#define OPT_SMART_C_LINK 0x02
|
||||
|
||||
enum eRpnData {
|
||||
RPN_ADD = 0,
|
||||
RPN_SUB,
|
||||
RPN_MUL,
|
||||
RPN_DIV,
|
||||
RPN_MOD,
|
||||
RPN_UNSUB,
|
||||
|
||||
RPN_OR,
|
||||
RPN_AND,
|
||||
RPN_XOR,
|
||||
RPN_UNNOT,
|
||||
|
||||
RPN_LOGAND,
|
||||
RPN_LOGOR,
|
||||
RPN_LOGUNNOT,
|
||||
|
||||
RPN_LOGEQ,
|
||||
RPN_LOGNE,
|
||||
RPN_LOGGT,
|
||||
RPN_LOGLT,
|
||||
RPN_LOGGE,
|
||||
RPN_LOGLE,
|
||||
|
||||
RPN_SHL,
|
||||
RPN_SHR,
|
||||
|
||||
RPN_BANK,
|
||||
|
||||
RPN_HRAM,
|
||||
|
||||
RPN_PCEZP,
|
||||
|
||||
RPN_RANGECHECK,
|
||||
|
||||
RPN_CONST = 0x80,
|
||||
RPN_SYM = 0x81
|
||||
};
|
||||
|
||||
enum eSectionType {
|
||||
SECT_WRAM0,
|
||||
SECT_VRAM,
|
||||
SECT_ROMX,
|
||||
SECT_ROM0,
|
||||
SECT_HRAM,
|
||||
SECT_WRAMX,
|
||||
SECT_SRAM
|
||||
};
|
||||
#define OPT_OVERLAY 0x04
|
||||
#define OPT_CONTWRAM 0x08
|
||||
#define OPT_DMG_MODE 0x10
|
||||
|
||||
struct sSection {
|
||||
SLONG nBank;
|
||||
SLONG nOrg;
|
||||
BBOOL oAssigned;
|
||||
int32_t nBank;
|
||||
int32_t nOrg;
|
||||
int32_t nAlign;
|
||||
uint8_t oAssigned;
|
||||
|
||||
SLONG nByteSize;
|
||||
char *pzName;
|
||||
int32_t nByteSize;
|
||||
enum eSectionType Type;
|
||||
UBYTE *pData;
|
||||
SLONG nNumberOfSymbols;
|
||||
uint8_t *pData;
|
||||
int32_t nNumberOfSymbols;
|
||||
struct sSymbol **tSymbols;
|
||||
struct sPatch *pPatches;
|
||||
struct sSection *pNext;
|
||||
};
|
||||
|
||||
enum eSymbolType {
|
||||
SYM_LOCAL,
|
||||
SYM_IMPORT,
|
||||
SYM_EXPORT
|
||||
};
|
||||
|
||||
struct sSymbol {
|
||||
char *pzName;
|
||||
enum eSymbolType Type;
|
||||
/* the following 3 items only valid when Type!=SYM_IMPORT */
|
||||
SLONG nSectionID; /* internal to object.c */
|
||||
struct sSection *pSection;
|
||||
SLONG nOffset;
|
||||
};
|
||||
|
||||
enum ePatchType {
|
||||
PATCH_BYTE = 0,
|
||||
PATCH_WORD_L,
|
||||
PATCH_LONG_L,
|
||||
PATCH_WORD_B,
|
||||
PATCH_LONG_B
|
||||
/* The following 3 items only valid when Type!=SYM_IMPORT */
|
||||
int32_t nSectionID; /* Internal to object.c */
|
||||
struct sSection *pSection;
|
||||
int32_t nOffset;
|
||||
|
||||
char *pzObjFileName; /* Object file where the symbol is located. */
|
||||
char *pzFileName; /* Source file where the symbol was defined. */
|
||||
uint32_t nFileLine; /* Line where the symbol was defined. */
|
||||
};
|
||||
|
||||
struct sPatch {
|
||||
char *pzFilename;
|
||||
SLONG nLineNo;
|
||||
SLONG nOffset;
|
||||
int32_t nLineNo;
|
||||
int32_t nOffset;
|
||||
enum ePatchType Type;
|
||||
SLONG nRPNSize;
|
||||
UBYTE *pRPN;
|
||||
int32_t nRPNSize;
|
||||
uint8_t *pRPN;
|
||||
struct sPatch *pNext;
|
||||
BBOOL oRelocPatch;
|
||||
uint8_t oRelocPatch;
|
||||
};
|
||||
|
||||
extern struct sSection *pSections;
|
||||
extern struct sSection *pLibSections;
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_LINK_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef RGBDS_LINK_OBJECT_H
|
||||
#define RGBDS_LINK_OBJECT_H
|
||||
#ifndef RGBDS_LINK_OBJECT_H
|
||||
#define RGBDS_LINK_OBJECT_H
|
||||
|
||||
extern void obj_Readfile(char *tzObjectfile);
|
||||
void obj_Readfile(char *tzObjectfile);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_OBJECT_H */
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#ifndef RGBDS_LINK_OUTPUT_H
|
||||
#define RGBDS_LINK_OUTPUT_H
|
||||
#ifndef RGBDS_LINK_OUTPUT_H
|
||||
#define RGBDS_LINK_OUTPUT_H
|
||||
|
||||
void out_Setname(char *tzOutputfile);
|
||||
void out_SetOverlayname(char *tzOverlayfile);
|
||||
void Output(void);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_OUTPUT_H */
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef RGBDS_LINK_PATCH_H
|
||||
#define RGBDS_LINK_PATCH_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void Patch(void);
|
||||
extern SLONG nPC;
|
||||
extern int32_t nPC;
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_PATCH_H */
|
||||
|
||||
38
include/link/script.h
Normal file
38
include/link/script.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.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_LINK_SCRIPT_H
|
||||
#define RGBDS_LINK_SCRIPT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "extern/stdnoreturn.h"
|
||||
|
||||
noreturn void script_fatalerror(const char *fmt, ...);
|
||||
|
||||
void script_Parse(const char *path);
|
||||
|
||||
void script_IncludeFile(const char *path);
|
||||
int32_t script_IncludeDepthGet(void);
|
||||
void script_IncludePop(void);
|
||||
|
||||
void script_InitSections(void);
|
||||
void script_SetCurrentSectionType(const char *type, uint32_t bank);
|
||||
void script_SetAddress(uint32_t addr);
|
||||
void script_SetAlignment(uint32_t alignment);
|
||||
void script_OutputSection(const char *section_name);
|
||||
|
||||
#endif /* RGBDS_LINK_SCRIPT_H */
|
||||
@@ -1,11 +1,13 @@
|
||||
#ifndef RGBDS_LINK_SYMBOL_H
|
||||
#define RGBDS_LINK_SYMBOL_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void sym_Init(void);
|
||||
void sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank);
|
||||
SLONG sym_GetValue(char *tzName);
|
||||
SLONG sym_GetBank(char *tzName);
|
||||
void sym_CreateSymbol(char *tzName, int32_t nValue, int32_t nBank,
|
||||
char *tzObjFileName, char *tzFileName,
|
||||
uint32_t nFileLine);
|
||||
int32_t sym_GetValue(char *tzName);
|
||||
int32_t sym_GetBank(char *tzName);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_SYMBOL_H */
|
||||
|
||||
64
include/linkdefs.h
Normal file
64
include/linkdefs.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef RGBDS_LINKDEFS_H
|
||||
#define RGBDS_LINKDEFS_H
|
||||
|
||||
enum eRpnData {
|
||||
RPN_ADD = 0x00,
|
||||
RPN_SUB = 0x01,
|
||||
RPN_MUL = 0x02,
|
||||
RPN_DIV = 0x03,
|
||||
RPN_MOD = 0x04,
|
||||
RPN_UNSUB = 0x05,
|
||||
|
||||
RPN_OR = 0x10,
|
||||
RPN_AND = 0x11,
|
||||
RPN_XOR = 0x12,
|
||||
RPN_UNNOT = 0x13,
|
||||
|
||||
RPN_LOGAND = 0x21,
|
||||
RPN_LOGOR = 0x22,
|
||||
RPN_LOGUNNOT = 0x23,
|
||||
|
||||
RPN_LOGEQ = 0x30,
|
||||
RPN_LOGNE = 0x31,
|
||||
RPN_LOGGT = 0x32,
|
||||
RPN_LOGLT = 0x33,
|
||||
RPN_LOGGE = 0x34,
|
||||
RPN_LOGLE = 0x35,
|
||||
|
||||
RPN_SHL = 0x40,
|
||||
RPN_SHR = 0x41,
|
||||
|
||||
RPN_BANK_SYM = 0x50,
|
||||
RPN_BANK_SECT = 0x51,
|
||||
RPN_BANK_SELF = 0x52,
|
||||
|
||||
RPN_HRAM = 0x60,
|
||||
|
||||
RPN_CONST = 0x80,
|
||||
RPN_SYM = 0x81
|
||||
};
|
||||
|
||||
enum eSectionType {
|
||||
SECT_WRAM0 = 0x00,
|
||||
SECT_VRAM = 0x01,
|
||||
SECT_ROMX = 0x02,
|
||||
SECT_ROM0 = 0x03,
|
||||
SECT_HRAM = 0x04,
|
||||
SECT_WRAMX = 0x05,
|
||||
SECT_SRAM = 0x06,
|
||||
SECT_OAM = 0x07
|
||||
};
|
||||
|
||||
enum eSymbolType {
|
||||
SYM_LOCAL = 0x00,
|
||||
SYM_IMPORT = 0x01,
|
||||
SYM_EXPORT = 0x02
|
||||
};
|
||||
|
||||
enum ePatchType {
|
||||
PATCH_BYTE = 0x00,
|
||||
PATCH_WORD_L = 0x01,
|
||||
PATCH_LONG_L = 0x02
|
||||
};
|
||||
|
||||
#endif /* RGBDS_LINKDEFS_H */
|
||||
@@ -2,15 +2,7 @@
|
||||
#define RGBDS_TYPES_H
|
||||
|
||||
#ifndef _MAX_PATH
|
||||
#define _MAX_PATH 512
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
|
||||
typedef unsigned char UBYTE;
|
||||
typedef signed char SBYTE;
|
||||
typedef unsigned short UWORD;
|
||||
typedef signed short SWORD;
|
||||
typedef unsigned long ULONG;
|
||||
typedef signed long SLONG;
|
||||
typedef signed char BBOOL;
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_TYPES_H */
|
||||
|
||||
2960
src/asm/asmy.y
2960
src/asm/asmy.y
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,71 @@
|
||||
/*
|
||||
* 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, /* 00..0f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10..1f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20..2f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 30..3f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40..4f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 50..5f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60..6f */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70..7f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80..8f */
|
||||
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, /* 90..9f */
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* a0..af */
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, /* b0..bf */
|
||||
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* c0..cf */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* d0..df */
|
||||
0xa, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, /* e0..e7 */
|
||||
0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, /* e8..ef */
|
||||
0xb, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, /* f0..f7 */
|
||||
0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, /* f8..ff */
|
||||
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, /* s0.. */
|
||||
0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, /* ..s0 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* s1 */
|
||||
1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, /* s1 */
|
||||
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, /* s3 */
|
||||
1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, /* s4 */
|
||||
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, /* s5 */
|
||||
1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, /* s6 */
|
||||
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, /* s7 */
|
||||
1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 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>
|
||||
*
|
||||
@@ -25,180 +93,131 @@
|
||||
|
||||
struct Charmap globalCharmap = {0};
|
||||
|
||||
extern struct Section *pCurrentSection;
|
||||
|
||||
int
|
||||
readUTF8Char(char *destination, char *source)
|
||||
int32_t readUTF8Char(char *dest, char *src)
|
||||
{
|
||||
int size;
|
||||
UBYTE first;
|
||||
first = source[0];
|
||||
uint32_t state;
|
||||
uint32_t codep;
|
||||
int32_t 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)
|
||||
int32_t charmap_Add(char *input, uint8_t output)
|
||||
{
|
||||
int i, input_length;
|
||||
char temp1i[CHARMAPLENGTH + 1], temp2i[CHARMAPLENGTH + 1], temp1o = 0, temp2o = 0;
|
||||
int32_t i;
|
||||
size_t input_length;
|
||||
char temp1i[CHARMAPLENGTH + 1], temp2i[CHARMAPLENGTH + 1];
|
||||
char 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 {
|
||||
charmap = calloc(1, sizeof(struct Charmap));
|
||||
if (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
|
||||
charmap_Convert(char **input)
|
||||
int32_t charmap_Convert(char **input)
|
||||
{
|
||||
struct Charmap *charmap;
|
||||
|
||||
char outchar[CHARMAPLENGTH + 1];
|
||||
char *buffer;
|
||||
int i, j, length;
|
||||
int32_t i, j, length;
|
||||
|
||||
if(pCurrentSection && pCurrentSection -> charmap)
|
||||
{
|
||||
charmap = pCurrentSection -> charmap;
|
||||
}
|
||||
if (pCurrentSection && pCurrentSection->charmap)
|
||||
charmap = pCurrentSection->charmap;
|
||||
else
|
||||
{
|
||||
charmap = &globalCharmap;
|
||||
}
|
||||
|
||||
if((buffer = (char *) malloc(strlen(*input))) == NULL)
|
||||
{
|
||||
buffer = malloc(strlen(*input));
|
||||
if (buffer == 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];
|
||||
}
|
||||
}
|
||||
*input += j;
|
||||
}
|
||||
*input = buffer;
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
379
src/asm/fstack.c
379
src/asm/fstack.c
@@ -4,51 +4,50 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/fstack.h"
|
||||
#include "types.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/output.h"
|
||||
#include "asm/symbol.h"
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "extern/strl.h"
|
||||
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX 256
|
||||
#endif
|
||||
#include "types.h"
|
||||
|
||||
struct sContext *pFileStack;
|
||||
struct sSymbol *pCurrentMacro;
|
||||
YY_BUFFER_STATE CurrentFlexHandle;
|
||||
FILE *pCurrentFile;
|
||||
ULONG nCurrentStatus;
|
||||
static struct sContext *pFileStack;
|
||||
static struct sSymbol *pCurrentMacro;
|
||||
static YY_BUFFER_STATE CurrentFlexHandle;
|
||||
static FILE *pCurrentFile;
|
||||
static uint32_t nCurrentStatus;
|
||||
char tzCurrentFileName[_MAX_PATH + 1];
|
||||
char IncludePaths[MAXINCPATHS][_MAX_PATH + 1];
|
||||
SLONG NextIncPath = 0;
|
||||
ULONG nMacroCount;
|
||||
static char IncludePaths[MAXINCPATHS][_MAX_PATH + 1];
|
||||
static int32_t NextIncPath;
|
||||
static uint32_t nMacroCount;
|
||||
|
||||
char *pCurrentREPTBlock;
|
||||
ULONG nCurrentREPTBlockSize;
|
||||
ULONG nCurrentREPTBlockCount;
|
||||
static char *pCurrentREPTBlock;
|
||||
static uint32_t nCurrentREPTBlockSize;
|
||||
static uint32_t nCurrentREPTBlockCount;
|
||||
|
||||
ULONG ulMacroReturnValue;
|
||||
uint32_t ulMacroReturnValue;
|
||||
|
||||
/*
|
||||
* defines for nCurrentStatus
|
||||
*/
|
||||
#define STAT_isInclude 0
|
||||
#define STAT_isMacro 1
|
||||
#define STAT_isInclude 0 /* 'Normal' state as well */
|
||||
#define STAT_isMacro 1
|
||||
#define STAT_isMacroArg 2
|
||||
#define STAT_isREPTBlock 3
|
||||
|
||||
/*
|
||||
* Context push and pop
|
||||
*/
|
||||
void
|
||||
pushcontext(void)
|
||||
static void pushcontext(void)
|
||||
{
|
||||
struct sContext **ppFileStack;
|
||||
|
||||
@@ -56,36 +55,37 @@ pushcontext(void)
|
||||
while (*ppFileStack)
|
||||
ppFileStack = &((*ppFileStack)->pNext);
|
||||
|
||||
if ((*ppFileStack = malloc(sizeof(struct sContext))) != NULL) {
|
||||
(*ppFileStack)->FlexHandle = CurrentFlexHandle;
|
||||
(*ppFileStack)->pNext = NULL;
|
||||
strcpy((char *) (*ppFileStack)->tzFileName,
|
||||
(char *) tzCurrentFileName);
|
||||
(*ppFileStack)->nLine = nLineNo;
|
||||
switch ((*ppFileStack)->nStatus = nCurrentStatus) {
|
||||
case STAT_isMacroArg:
|
||||
case STAT_isMacro:
|
||||
sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
|
||||
(*ppFileStack)->pMacro = pCurrentMacro;
|
||||
break;
|
||||
case STAT_isInclude:
|
||||
(*ppFileStack)->pFile = pCurrentFile;
|
||||
break;
|
||||
case STAT_isREPTBlock:
|
||||
sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
|
||||
(*ppFileStack)->pREPTBlock = pCurrentREPTBlock;
|
||||
(*ppFileStack)->nREPTBlockSize = nCurrentREPTBlockSize;
|
||||
(*ppFileStack)->nREPTBlockCount =
|
||||
nCurrentREPTBlockCount;
|
||||
break;
|
||||
}
|
||||
nLineNo = 0;
|
||||
} else
|
||||
*ppFileStack = malloc(sizeof(struct sContext));
|
||||
|
||||
if (*ppFileStack == NULL)
|
||||
fatalerror("No memory for context");
|
||||
|
||||
(*ppFileStack)->FlexHandle = CurrentFlexHandle;
|
||||
(*ppFileStack)->pNext = NULL;
|
||||
strcpy((char *)(*ppFileStack)->tzFileName, (char *)tzCurrentFileName);
|
||||
(*ppFileStack)->nLine = nLineNo;
|
||||
|
||||
switch ((*ppFileStack)->nStatus = nCurrentStatus) {
|
||||
case STAT_isMacroArg:
|
||||
case STAT_isMacro:
|
||||
sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
|
||||
(*ppFileStack)->pMacro = pCurrentMacro;
|
||||
break;
|
||||
case STAT_isInclude:
|
||||
(*ppFileStack)->pFile = pCurrentFile;
|
||||
break;
|
||||
case STAT_isREPTBlock:
|
||||
sym_SaveCurrentMacroArgs((*ppFileStack)->tzMacroArgs);
|
||||
(*ppFileStack)->pREPTBlock = pCurrentREPTBlock;
|
||||
(*ppFileStack)->nREPTBlockSize = nCurrentREPTBlockSize;
|
||||
(*ppFileStack)->nREPTBlockCount = nCurrentREPTBlockCount;
|
||||
break;
|
||||
}
|
||||
|
||||
nLineNo = 0;
|
||||
}
|
||||
|
||||
int
|
||||
popcontext(void)
|
||||
static int32_t popcontext(void)
|
||||
{
|
||||
struct sContext *pLastFile, **ppLastFile;
|
||||
|
||||
@@ -93,116 +93,165 @@ popcontext(void)
|
||||
if (--nCurrentREPTBlockCount) {
|
||||
yy_delete_buffer(CurrentFlexHandle);
|
||||
CurrentFlexHandle =
|
||||
yy_scan_bytes(pCurrentREPTBlock,
|
||||
nCurrentREPTBlockSize);
|
||||
yy_scan_bytes(pCurrentREPTBlock,
|
||||
nCurrentREPTBlockSize);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
sym_UseCurrentMacroArgs();
|
||||
sym_SetMacroArgID(nMacroCount++);
|
||||
sym_UseNewMacroArgs();
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if ((pLastFile = pFileStack) != NULL) {
|
||||
|
||||
pLastFile = pFileStack;
|
||||
if (pLastFile == NULL)
|
||||
return 1;
|
||||
|
||||
ppLastFile = &pFileStack;
|
||||
while (pLastFile->pNext) {
|
||||
ppLastFile = &(pLastFile->pNext);
|
||||
pLastFile = *ppLastFile;
|
||||
}
|
||||
|
||||
yy_delete_buffer(CurrentFlexHandle);
|
||||
nLineNo = pLastFile->nLine;
|
||||
|
||||
if (nCurrentStatus == STAT_isInclude)
|
||||
fclose(pCurrentFile);
|
||||
|
||||
if (nCurrentStatus == STAT_isMacro) {
|
||||
sym_FreeCurrentMacroArgs();
|
||||
nLineNo += 1;
|
||||
}
|
||||
|
||||
if (nCurrentStatus == STAT_isREPTBlock)
|
||||
nLineNo += 1;
|
||||
|
||||
CurrentFlexHandle = pLastFile->FlexHandle;
|
||||
strcpy((char *)tzCurrentFileName, (char *)pLastFile->tzFileName);
|
||||
|
||||
switch (nCurrentStatus = pLastFile->nStatus) {
|
||||
case STAT_isMacroArg:
|
||||
case STAT_isMacro:
|
||||
sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
|
||||
pCurrentMacro = pLastFile->pMacro;
|
||||
break;
|
||||
case STAT_isInclude:
|
||||
pCurrentFile = pLastFile->pFile;
|
||||
break;
|
||||
case STAT_isREPTBlock:
|
||||
sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
|
||||
pCurrentREPTBlock = pLastFile->pREPTBlock;
|
||||
nCurrentREPTBlockSize = pLastFile->nREPTBlockSize;
|
||||
nCurrentREPTBlockCount = pLastFile->nREPTBlockCount;
|
||||
break;
|
||||
}
|
||||
|
||||
free(*ppLastFile);
|
||||
*ppLastFile = NULL;
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t fstk_GetLine(void)
|
||||
{
|
||||
struct sContext *pLastFile, **ppLastFile;
|
||||
|
||||
switch (nCurrentStatus) {
|
||||
case STAT_isInclude:
|
||||
/* This is the normal mode, also used when including a file. */
|
||||
return nLineNo;
|
||||
case STAT_isMacro:
|
||||
break; /* Peek top file of the stack */
|
||||
case STAT_isMacroArg:
|
||||
return nLineNo; /* ??? */
|
||||
case STAT_isREPTBlock:
|
||||
break; /* Peek top file of the stack */
|
||||
}
|
||||
|
||||
pLastFile = pFileStack;
|
||||
|
||||
if (pLastFile != NULL) {
|
||||
ppLastFile = &pFileStack;
|
||||
while (pLastFile->pNext) {
|
||||
ppLastFile = &(pLastFile->pNext);
|
||||
pLastFile = *ppLastFile;
|
||||
}
|
||||
return pLastFile->nLine;
|
||||
}
|
||||
|
||||
yy_delete_buffer(CurrentFlexHandle);
|
||||
nLineNo = pLastFile->nLine;
|
||||
if (nCurrentStatus == STAT_isInclude)
|
||||
fclose(pCurrentFile);
|
||||
if (nCurrentStatus == STAT_isMacro) {
|
||||
sym_FreeCurrentMacroArgs();
|
||||
nLineNo += 1;
|
||||
}
|
||||
if (nCurrentStatus == STAT_isREPTBlock)
|
||||
nLineNo += 1;
|
||||
|
||||
CurrentFlexHandle = pLastFile->FlexHandle;
|
||||
strcpy((char *) tzCurrentFileName,
|
||||
(char *) pLastFile->tzFileName);
|
||||
switch (nCurrentStatus = pLastFile->nStatus) {
|
||||
case STAT_isMacroArg:
|
||||
case STAT_isMacro:
|
||||
sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
|
||||
pCurrentMacro = pLastFile->pMacro;
|
||||
break;
|
||||
case STAT_isInclude:
|
||||
pCurrentFile = pLastFile->pFile;
|
||||
break;
|
||||
case STAT_isREPTBlock:
|
||||
sym_RestoreCurrentMacroArgs(pLastFile->tzMacroArgs);
|
||||
pCurrentREPTBlock = pLastFile->pREPTBlock;
|
||||
nCurrentREPTBlockSize = pLastFile->nREPTBlockSize;
|
||||
nCurrentREPTBlockCount = pLastFile->nREPTBlockCount;
|
||||
break;
|
||||
}
|
||||
|
||||
free(*ppLastFile);
|
||||
*ppLastFile = NULL;
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
return (0);
|
||||
} else
|
||||
return (1);
|
||||
/*
|
||||
* This is only reached if the lexer is in REPT or MACRO mode but there
|
||||
* are no saved contexts with the origin of said REPT or MACRO.
|
||||
*/
|
||||
fatalerror("%s: Internal error.", __func__);
|
||||
}
|
||||
|
||||
int
|
||||
yywrap(void)
|
||||
int yywrap(void)
|
||||
{
|
||||
return (popcontext());
|
||||
return popcontext();
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump the context stack to stderr
|
||||
*/
|
||||
void
|
||||
fstk_Dump(void)
|
||||
void fstk_Dump(void)
|
||||
{
|
||||
struct sContext *pLastFile;
|
||||
const struct sContext *pLastFile;
|
||||
|
||||
pLastFile = pFileStack;
|
||||
|
||||
while (pLastFile) {
|
||||
fprintf(stderr, "%s(%ld) -> ", pLastFile->tzFileName,
|
||||
pLastFile->nLine);
|
||||
fprintf(stderr, "%s(%d) -> ", pLastFile->tzFileName,
|
||||
pLastFile->nLine);
|
||||
pLastFile = pLastFile->pNext;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s(%ld)", tzCurrentFileName, nLineNo);
|
||||
fprintf(stderr, "%s(%d)", tzCurrentFileName, nLineNo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Extra includepath stuff
|
||||
*/
|
||||
void
|
||||
fstk_AddIncludePath(char *s)
|
||||
void fstk_AddIncludePath(char *s)
|
||||
{
|
||||
strcpy(IncludePaths[NextIncPath++], s);
|
||||
if (NextIncPath == MAXINCPATHS)
|
||||
fatalerror("Too many include directories passed from command line");
|
||||
|
||||
if (strlcpy(IncludePaths[NextIncPath++], s, _MAX_PATH) >= _MAX_PATH)
|
||||
fatalerror("Include path too long '%s'", s);
|
||||
}
|
||||
|
||||
FILE *
|
||||
fstk_FindFile(char *fname)
|
||||
FILE *fstk_FindFile(char *fname)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int i;
|
||||
char path[_MAX_PATH];
|
||||
int32_t i;
|
||||
FILE *f;
|
||||
|
||||
if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) {
|
||||
f = fopen(fname, "rb");
|
||||
|
||||
if (f != NULL || errno != ENOENT) {
|
||||
if (dependfile)
|
||||
fprintf(dependfile, "%s: %s\n", tzObjectname, fname);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
for (i = 0; i < NextIncPath; ++i) {
|
||||
if (strlcpy(path, IncludePaths[i], sizeof path) >=
|
||||
sizeof path) {
|
||||
if (strlcpy(path, IncludePaths[i], sizeof(path))
|
||||
>= sizeof(path))
|
||||
continue;
|
||||
}
|
||||
if (strlcat(path, fname, sizeof path) >= sizeof path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) {
|
||||
if (strlcat(path, fname, sizeof(path)) >= sizeof(path))
|
||||
continue;
|
||||
|
||||
f = fopen(path, "rb");
|
||||
|
||||
if (f != NULL || errno != ENOENT) {
|
||||
if (dependfile) {
|
||||
fprintf(dependfile, "%s: %s\n", tzObjectname,
|
||||
path);
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
@@ -214,17 +263,12 @@ fstk_FindFile(char *fname)
|
||||
/*
|
||||
* Set up an include file for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunInclude(char *tzFileName)
|
||||
void fstk_RunInclude(char *tzFileName)
|
||||
{
|
||||
FILE *f;
|
||||
FILE *f = fstk_FindFile(tzFileName);
|
||||
|
||||
f = fstk_FindFile(tzFileName);
|
||||
|
||||
if (f == NULL) {
|
||||
err(1, "Unable to open included file '%s'",
|
||||
tzFileName);
|
||||
}
|
||||
if (f == NULL)
|
||||
err(1, "Unable to open included file '%s'", tzFileName);
|
||||
|
||||
pushcontext();
|
||||
nLineNo = 1;
|
||||
@@ -234,7 +278,7 @@ fstk_RunInclude(char *tzFileName)
|
||||
CurrentFlexHandle = yy_create_buffer(pCurrentFile);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
|
||||
//Dirty hack to give the INCLUDE directive a linefeed
|
||||
/* Dirty hack to give the INCLUDE directive a linefeed */
|
||||
|
||||
yyunput('\n');
|
||||
nLineNo -= 1;
|
||||
@@ -243,35 +287,35 @@ fstk_RunInclude(char *tzFileName)
|
||||
/*
|
||||
* Set up a macro for parsing
|
||||
*/
|
||||
ULONG
|
||||
fstk_RunMacro(char *s)
|
||||
uint32_t fstk_RunMacro(char *s)
|
||||
{
|
||||
struct sSymbol *sym;
|
||||
struct sSymbol *sym = sym_FindMacro(s);
|
||||
|
||||
if ((sym = sym_FindMacro(s)) != NULL) {
|
||||
pushcontext();
|
||||
sym_SetMacroArgID(nMacroCount++);
|
||||
nLineNo = -1;
|
||||
sym_UseNewMacroArgs();
|
||||
nCurrentStatus = STAT_isMacro;
|
||||
strcpy(tzCurrentFileName, s);
|
||||
if (sym->pMacro == NULL)
|
||||
return 0;
|
||||
pCurrentMacro = sym;
|
||||
CurrentFlexHandle =
|
||||
yy_scan_bytes(pCurrentMacro->pMacro,
|
||||
strlen(pCurrentMacro->pMacro));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
if (sym == NULL)
|
||||
return 0;
|
||||
|
||||
pushcontext();
|
||||
sym_SetMacroArgID(nMacroCount++);
|
||||
nLineNo = -1;
|
||||
sym_UseNewMacroArgs();
|
||||
nCurrentStatus = STAT_isMacro;
|
||||
strcpy(tzCurrentFileName, s);
|
||||
|
||||
if (sym->pMacro == NULL)
|
||||
return 0;
|
||||
|
||||
pCurrentMacro = sym;
|
||||
CurrentFlexHandle = yy_scan_bytes(pCurrentMacro->pMacro,
|
||||
strlen(pCurrentMacro->pMacro));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a macroargument for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunMacroArg(SLONG s)
|
||||
void fstk_RunMacroArg(int32_t s)
|
||||
{
|
||||
char *sym;
|
||||
|
||||
@@ -280,40 +324,41 @@ fstk_RunMacroArg(SLONG s)
|
||||
else
|
||||
s -= '0';
|
||||
|
||||
if ((sym = sym_FindMacroArg(s)) != NULL) {
|
||||
pushcontext();
|
||||
nCurrentStatus = STAT_isMacroArg;
|
||||
sprintf(tzCurrentFileName, "%c", (UBYTE) s);
|
||||
CurrentFlexHandle = yy_scan_bytes(sym, strlen(sym));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
} else
|
||||
sym = sym_FindMacroArg(s);
|
||||
|
||||
if (sym == NULL)
|
||||
fatalerror("No such macroargument");
|
||||
|
||||
pushcontext();
|
||||
nCurrentStatus = STAT_isMacroArg;
|
||||
sprintf(tzCurrentFileName, "%c", (uint8_t)s);
|
||||
CurrentFlexHandle = yy_scan_bytes(sym, strlen(sym));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a stringequate for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunString(char *s)
|
||||
void fstk_RunString(char *s)
|
||||
{
|
||||
struct sSymbol *pSym;
|
||||
const struct sSymbol *pSym = sym_FindSymbol(s);
|
||||
|
||||
if ((pSym = sym_FindSymbol(s)) != NULL) {
|
||||
if (pSym != NULL) {
|
||||
pushcontext();
|
||||
nCurrentStatus = STAT_isMacroArg;
|
||||
strcpy(tzCurrentFileName, s);
|
||||
CurrentFlexHandle =
|
||||
yy_scan_bytes(pSym->pMacro, strlen(pSym->pMacro));
|
||||
yy_scan_bytes(pSym->pMacro, strlen(pSym->pMacro));
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
} else
|
||||
} else {
|
||||
yyerror("No such string symbol '%s'", s);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a repeat block for parsing
|
||||
*/
|
||||
void
|
||||
fstk_RunRept(ULONG count)
|
||||
void fstk_RunRept(uint32_t count)
|
||||
{
|
||||
if (count) {
|
||||
pushcontext();
|
||||
@@ -325,7 +370,7 @@ fstk_RunRept(ULONG count)
|
||||
nCurrentREPTBlockSize = ulNewMacroSize;
|
||||
pCurrentREPTBlock = tzNewMacro;
|
||||
CurrentFlexHandle =
|
||||
yy_scan_bytes(pCurrentREPTBlock, nCurrentREPTBlockSize);
|
||||
yy_scan_bytes(pCurrentREPTBlock, nCurrentREPTBlockSize);
|
||||
yy_switch_to_buffer(CurrentFlexHandle);
|
||||
}
|
||||
}
|
||||
@@ -333,19 +378,19 @@ fstk_RunRept(ULONG count)
|
||||
/*
|
||||
* Initialize the filestack routines
|
||||
*/
|
||||
void
|
||||
fstk_Init(char *s)
|
||||
void fstk_Init(char *s)
|
||||
{
|
||||
char tzFileName[_MAX_PATH + 1];
|
||||
char tzSymFileName[_MAX_PATH + 1 + 2];
|
||||
|
||||
sym_AddString("__FILE__", s);
|
||||
snprintf(tzSymFileName, sizeof(tzSymFileName), "\"%s\"", s);
|
||||
sym_AddString("__FILE__", tzSymFileName);
|
||||
|
||||
strcpy(tzFileName, s);
|
||||
pFileStack = NULL;
|
||||
pCurrentFile = fopen(tzFileName, "rb");
|
||||
if (pCurrentFile == NULL) {
|
||||
if (pCurrentFile == NULL)
|
||||
err(1, "Unable to open file '%s'", tzFileName);
|
||||
}
|
||||
|
||||
nMacroCount = 0;
|
||||
nCurrentStatus = STAT_isInclude;
|
||||
|
||||
@@ -1,52 +1,48 @@
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/asm.h"
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/rpn.h"
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "asm/symbol.h"
|
||||
|
||||
#include "asmy.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
bool oDontExpandStrings;
|
||||
int32_t nGBGfxID = -1;
|
||||
int32_t nBinaryID = -1;
|
||||
|
||||
bool oDontExpandStrings = false;
|
||||
SLONG nGBGfxID = -1;
|
||||
SLONG nBinaryID = -1;
|
||||
|
||||
SLONG
|
||||
gbgfx2bin(char ch)
|
||||
static int32_t gbgfx2bin(char ch)
|
||||
{
|
||||
SLONG i;
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i <= 3; i += 1) {
|
||||
if (CurrentOptions.gbgfx[i] == ch) {
|
||||
return (i);
|
||||
}
|
||||
if (CurrentOptions.gbgfx[i] == ch)
|
||||
return i;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SLONG
|
||||
binary2bin(char ch)
|
||||
static int32_t binary2bin(char ch)
|
||||
{
|
||||
SLONG i;
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i <= 1; i += 1) {
|
||||
if (CurrentOptions.binary[i] == ch) {
|
||||
return (i);
|
||||
}
|
||||
if (CurrentOptions.binary[i] == ch)
|
||||
return i;
|
||||
}
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
SLONG
|
||||
char2bin(char ch)
|
||||
static int32_t char2bin(char ch)
|
||||
{
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
return (ch - 'a' + 10);
|
||||
@@ -57,16 +53,15 @@ char2bin(char ch)
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return (ch - '0');
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef SLONG(*x2bin) (char ch);
|
||||
typedef int32_t(*x2bin) (char ch);
|
||||
|
||||
SLONG
|
||||
ascii2bin(char *s)
|
||||
static int32_t ascii2bin(char *s)
|
||||
{
|
||||
SLONG radix = 10;
|
||||
SLONG result = 0;
|
||||
int32_t radix = 10;
|
||||
int32_t result = 0;
|
||||
x2bin convertfunc = char2bin;
|
||||
|
||||
switch (*s) {
|
||||
@@ -93,48 +88,42 @@ ascii2bin(char *s)
|
||||
}
|
||||
|
||||
if (radix == 4) {
|
||||
SLONG c;
|
||||
int32_t c;
|
||||
|
||||
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')
|
||||
result = result * radix + convertfunc(*s++);
|
||||
}
|
||||
|
||||
return (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ParseFixedPoint(char *s, ULONG size)
|
||||
uint32_t ParseFixedPoint(char *s, uint32_t size)
|
||||
{
|
||||
//char dest[256];
|
||||
ULONG i = 0, dot = 0;
|
||||
uint32_t i = 0, dot = 0;
|
||||
|
||||
while (size && dot != 2) {
|
||||
if (s[i] == '.')
|
||||
dot += 1;
|
||||
|
||||
if (dot < 2) {
|
||||
//dest[i] = s[i];
|
||||
size -= 1;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
//dest[i] = 0;
|
||||
|
||||
yyunputbytes(size);
|
||||
|
||||
yylval.nConstValue = (SLONG) (atof(s) * 65536);
|
||||
yylval.nConstValue = (int32_t)(atof(s) * 65536);
|
||||
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ParseNumber(char *s, ULONG size)
|
||||
uint32_t ParseNumber(char *s, uint32_t size)
|
||||
{
|
||||
char dest[256];
|
||||
|
||||
@@ -142,14 +131,13 @@ ParseNumber(char *s, ULONG size)
|
||||
dest[size] = 0;
|
||||
yylval.nConstValue = ascii2bin(dest);
|
||||
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG
|
||||
ParseSymbol(char *src, ULONG size)
|
||||
uint32_t ParseSymbol(char *src, uint32_t size)
|
||||
{
|
||||
char dest[MAXSYMLEN + 1];
|
||||
int copied = 0, size_backup = size;
|
||||
int32_t copied = 0, size_backup = size;
|
||||
|
||||
while (size && copied < MAXSYMLEN) {
|
||||
if (*src == '\\') {
|
||||
@@ -158,13 +146,13 @@ ParseSymbol(char *src, ULONG size)
|
||||
src += 1;
|
||||
size -= 1;
|
||||
|
||||
if (*src == '@')
|
||||
if (*src == '@') {
|
||||
marg = sym_FindMacroArg(-1);
|
||||
else if (*src >= '0' && *src <= '9')
|
||||
} else if (*src >= '0' && *src <= '9') {
|
||||
marg = sym_FindMacroArg(*src - '0');
|
||||
else {
|
||||
} else {
|
||||
fatalerror("Malformed ID");
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
src += 1;
|
||||
@@ -192,47 +180,48 @@ ParseSymbol(char *src, ULONG size)
|
||||
yyunputstr(s = sym_GetStringValue(dest));
|
||||
|
||||
while (*s) {
|
||||
if (*s++ == '\n') {
|
||||
if (*s++ == '\n')
|
||||
nLineNo -= 1;
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
} else {
|
||||
strcpy(yylval.tzString, dest);
|
||||
return (1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(yylval.tzString, dest);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG
|
||||
PutMacroArg(char *src, ULONG size)
|
||||
uint32_t PutMacroArg(char *src, uint32_t size)
|
||||
{
|
||||
char *s;
|
||||
|
||||
yyskipbytes(size);
|
||||
if ((size == 2 && src[1] >= '1' && src[1] <= '9')) {
|
||||
if ((s = sym_FindMacroArg(src[1] - '0')) != NULL) {
|
||||
s = sym_FindMacroArg(src[1] - '0');
|
||||
|
||||
if (s != NULL)
|
||||
yyunputstr(s);
|
||||
} else {
|
||||
else
|
||||
yyerror("Macro argument not defined");
|
||||
}
|
||||
} else {
|
||||
yyerror("Invalid macro argument");
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ULONG
|
||||
PutUniqueArg(char *src, ULONG size)
|
||||
uint32_t PutUniqueArg(char *src, uint32_t size)
|
||||
{
|
||||
char *s;
|
||||
|
||||
yyskipbytes(size);
|
||||
if ((s = sym_FindMacroArg(-1)) != NULL) {
|
||||
|
||||
s = sym_FindMacroArg(-1);
|
||||
|
||||
if (s != NULL)
|
||||
yyunputstr(s);
|
||||
} else {
|
||||
else
|
||||
yyerror("Macro unique label string not defined");
|
||||
}
|
||||
return (0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum {
|
||||
@@ -240,9 +229,85 @@ enum {
|
||||
T_LEX_MACROUNIQUE
|
||||
};
|
||||
|
||||
extern struct sLexInitString localstrings[];
|
||||
const struct sLexInitString lexer_strings[] = {
|
||||
{"adc", T_Z80_ADC},
|
||||
{"add", T_Z80_ADD},
|
||||
{"and", T_Z80_AND},
|
||||
{"bit", T_Z80_BIT},
|
||||
{"call", T_Z80_CALL},
|
||||
{"ccf", T_Z80_CCF},
|
||||
{"cpl", T_Z80_CPL},
|
||||
{"cp", T_Z80_CP},
|
||||
{"daa", T_Z80_DAA},
|
||||
{"dec", T_Z80_DEC},
|
||||
{"di", T_Z80_DI},
|
||||
{"ei", T_Z80_EI},
|
||||
{"halt", T_Z80_HALT},
|
||||
{"inc", T_Z80_INC},
|
||||
{"jp", T_Z80_JP},
|
||||
{"jr", T_Z80_JR},
|
||||
{"ld", T_Z80_LD},
|
||||
{"ldi", T_Z80_LDI},
|
||||
{"ldd", T_Z80_LDD},
|
||||
{"ldio", T_Z80_LDIO},
|
||||
{"ldh", T_Z80_LDIO},
|
||||
{"nop", T_Z80_NOP},
|
||||
{"or", T_Z80_OR},
|
||||
{"pop", T_Z80_POP},
|
||||
{"push", T_Z80_PUSH},
|
||||
{"res", T_Z80_RES},
|
||||
{"reti", T_Z80_RETI},
|
||||
{"ret", T_Z80_RET},
|
||||
{"rlca", T_Z80_RLCA},
|
||||
{"rlc", T_Z80_RLC},
|
||||
{"rla", T_Z80_RLA},
|
||||
{"rl", T_Z80_RL},
|
||||
{"rrc", T_Z80_RRC},
|
||||
{"rrca", T_Z80_RRCA},
|
||||
{"rra", T_Z80_RRA},
|
||||
{"rr", T_Z80_RR},
|
||||
{"rst", T_Z80_RST},
|
||||
{"sbc", T_Z80_SBC},
|
||||
{"scf", T_Z80_SCF},
|
||||
{"set", T_POP_SET},
|
||||
{"sla", T_Z80_SLA},
|
||||
{"sra", T_Z80_SRA},
|
||||
{"srl", T_Z80_SRL},
|
||||
{"stop", T_Z80_STOP},
|
||||
{"sub", T_Z80_SUB},
|
||||
{"swap", T_Z80_SWAP},
|
||||
{"xor", T_Z80_XOR},
|
||||
|
||||
{"nz", T_CC_NZ},
|
||||
{"z", T_CC_Z},
|
||||
{"nc", T_CC_NC},
|
||||
/* Handled in list of registers */
|
||||
/* { "c", T_TOKEN_C }, */
|
||||
|
||||
{"[bc]", T_MODE_BC_IND},
|
||||
{"[de]", T_MODE_DE_IND},
|
||||
{"[hl]", T_MODE_HL_IND},
|
||||
{"[hl+]", T_MODE_HL_INDINC},
|
||||
{"[hl-]", T_MODE_HL_INDDEC},
|
||||
{"[hli]", T_MODE_HL_INDINC},
|
||||
{"[hld]", T_MODE_HL_INDDEC},
|
||||
{"[sp]", T_MODE_SP_IND},
|
||||
{"af", T_MODE_AF},
|
||||
{"bc", T_MODE_BC},
|
||||
{"de", T_MODE_DE},
|
||||
{"hl", T_MODE_HL},
|
||||
{"sp", T_MODE_SP},
|
||||
{"[c]", T_MODE_C_IND},
|
||||
{"[$ff00+c]", T_MODE_C_IND},
|
||||
|
||||
{"a", T_TOKEN_A},
|
||||
{"b", T_TOKEN_B},
|
||||
{"c", T_TOKEN_C},
|
||||
{"d", T_TOKEN_D},
|
||||
{"e", T_TOKEN_E},
|
||||
{"h", T_TOKEN_H},
|
||||
{"l", T_TOKEN_L},
|
||||
|
||||
struct sLexInitString staticstrings[] = {
|
||||
{"||", T_OP_LOGICOR},
|
||||
{"&&", T_OP_LOGICAND},
|
||||
{"==", T_OP_LOGICEQU},
|
||||
@@ -267,6 +332,7 @@ struct sLexInitString staticstrings[] = {
|
||||
{"def", T_OP_DEF},
|
||||
|
||||
{"bank", T_OP_BANK},
|
||||
{"align", T_OP_ALIGN},
|
||||
|
||||
{"round", T_OP_ROUND},
|
||||
{"ceil", T_OP_CEIL},
|
||||
@@ -281,6 +347,9 @@ struct sLexInitString staticstrings[] = {
|
||||
{"atan", T_OP_ATAN},
|
||||
{"atan2", T_OP_ATAN2},
|
||||
|
||||
{"high", T_OP_HIGH},
|
||||
{"low", T_OP_LOW},
|
||||
|
||||
{"strcmp", T_OP_STRCMP},
|
||||
{"strin", T_OP_STRIN},
|
||||
{"strsub", T_OP_STRSUB},
|
||||
@@ -299,11 +368,9 @@ struct sLexInitString staticstrings[] = {
|
||||
{"xref", T_POP_IMPORT},
|
||||
{"global", T_POP_GLOBAL},
|
||||
{"ds", T_POP_DS},
|
||||
{NAME_DB, T_POP_DB},
|
||||
{NAME_DW, T_POP_DW},
|
||||
#ifdef NAME_DL
|
||||
{NAME_DL, T_POP_DL},
|
||||
#endif
|
||||
{"db", T_POP_DB},
|
||||
{"dw", T_POP_DW},
|
||||
{"dl", T_POP_DL},
|
||||
{"section", T_POP_SECTION},
|
||||
{"purge", T_POP_PURGE},
|
||||
|
||||
@@ -317,7 +384,6 @@ struct sLexInitString staticstrings[] = {
|
||||
{"warn", T_POP_WARN},
|
||||
|
||||
{"macro", T_POP_MACRO},
|
||||
|
||||
/* Not needed but we have it here just to protect the name */
|
||||
{"endm", T_POP_ENDM},
|
||||
{"shift", T_POP_SHIFT},
|
||||
@@ -328,29 +394,35 @@ struct sLexInitString staticstrings[] = {
|
||||
|
||||
{"if", T_POP_IF},
|
||||
{"else", T_POP_ELSE},
|
||||
{"elif", T_POP_ELIF},
|
||||
{"endc", T_POP_ENDC},
|
||||
|
||||
{"union", T_POP_UNION},
|
||||
{"nextu", T_POP_NEXTU},
|
||||
{"endu", T_POP_ENDU},
|
||||
|
||||
{"wram0", T_SECT_WRAM0},
|
||||
{"bss", T_SECT_WRAM0}, /* deprecated */
|
||||
{"vram", T_SECT_VRAM},
|
||||
{"code", T_SECT_ROMX}, /* deprecated */
|
||||
{"data", T_SECT_ROMX}, /* deprecated */
|
||||
{"romx", T_SECT_ROMX},
|
||||
{"home", T_SECT_ROM0}, /* deprecated */
|
||||
{"rom0", T_SECT_ROM0},
|
||||
{"hram", T_SECT_HRAM},
|
||||
{"wramx", T_SECT_WRAMX},
|
||||
{"sram", T_SECT_SRAM},
|
||||
{"oam", T_SECT_OAM},
|
||||
|
||||
{NAME_RB, T_POP_RB},
|
||||
{NAME_RW, T_POP_RW},
|
||||
#ifdef NAME_RL
|
||||
{NAME_RL, T_POP_RL},
|
||||
#endif
|
||||
/* Deprecated section type names */
|
||||
{"home", T_SECT_HOME},
|
||||
{"code", T_SECT_CODE},
|
||||
{"data", T_SECT_DATA},
|
||||
{"bss", T_SECT_BSS},
|
||||
|
||||
{"rb", T_POP_RB},
|
||||
{"rw", T_POP_RW},
|
||||
{"equ", T_POP_EQU},
|
||||
{"equs", T_POP_EQUS},
|
||||
|
||||
{"set", T_POP_SET},
|
||||
/* Handled before in list of CPU instructions */
|
||||
/* {"set", T_POP_SET}, */
|
||||
{"=", T_POP_SET},
|
||||
|
||||
{"pushs", T_POP_PUSHS},
|
||||
@@ -363,43 +435,41 @@ struct sLexInitString staticstrings[] = {
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
struct sLexFloat tNumberToken = {
|
||||
const struct sLexFloat tNumberToken = {
|
||||
ParseNumber,
|
||||
T_NUMBER
|
||||
};
|
||||
|
||||
struct sLexFloat tFixedPointToken = {
|
||||
const struct sLexFloat tFixedPointToken = {
|
||||
ParseFixedPoint,
|
||||
T_NUMBER
|
||||
};
|
||||
|
||||
struct sLexFloat tIDToken = {
|
||||
const struct sLexFloat tIDToken = {
|
||||
ParseSymbol,
|
||||
T_ID
|
||||
};
|
||||
|
||||
struct sLexFloat tMacroArgToken = {
|
||||
const struct sLexFloat tMacroArgToken = {
|
||||
PutMacroArg,
|
||||
T_LEX_MACROARG
|
||||
};
|
||||
|
||||
struct sLexFloat tMacroUniqueToken = {
|
||||
const struct sLexFloat tMacroUniqueToken = {
|
||||
PutUniqueArg,
|
||||
T_LEX_MACROUNIQUE
|
||||
};
|
||||
|
||||
void
|
||||
setuplex(void)
|
||||
void setup_lexer(void)
|
||||
{
|
||||
ULONG id;
|
||||
uint32_t id;
|
||||
|
||||
lex_Init();
|
||||
lex_AddStrings(staticstrings);
|
||||
lex_AddStrings(localstrings);
|
||||
lex_AddStrings(lexer_strings);
|
||||
|
||||
//Macro arguments
|
||||
|
||||
id = lex_FloatAlloc(&tMacroArgToken);
|
||||
id = lex_FloatAlloc(&tMacroArgToken);
|
||||
lex_FloatAddFirstRange(id, '\\', '\\');
|
||||
lex_FloatAddSecondRange(id, '1', '9');
|
||||
id = lex_FloatAlloc(&tMacroUniqueToken);
|
||||
@@ -408,43 +478,45 @@ setuplex(void)
|
||||
|
||||
//Decimal constants
|
||||
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
lex_FloatAddFirstRange(id, '0', '9');
|
||||
lex_FloatAddSecondRange(id, '0', '9');
|
||||
lex_FloatAddRange(id, '0', '9');
|
||||
|
||||
//Binary constants
|
||||
|
||||
nBinaryID = id = lex_FloatAlloc(&tNumberToken);
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
nBinaryID = id;
|
||||
lex_FloatAddFirstRange(id, '%', '%');
|
||||
lex_FloatAddSecondRange(id, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatAddSecondRange(id, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
CurrentOptions.binary[1]);
|
||||
lex_FloatAddRange(id, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatAddRange(id, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
CurrentOptions.binary[1]);
|
||||
|
||||
//Octal constants
|
||||
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
lex_FloatAddFirstRange(id, '&', '&');
|
||||
lex_FloatAddSecondRange(id, '0', '7');
|
||||
lex_FloatAddRange(id, '0', '7');
|
||||
|
||||
//Gameboy gfx constants
|
||||
|
||||
nGBGfxID = id = lex_FloatAlloc(&tNumberToken);
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
nGBGfxID = id;
|
||||
lex_FloatAddFirstRange(id, '`', '`');
|
||||
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
CurrentOptions.gbgfx[3]);
|
||||
lex_FloatAddRange(id, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0]);
|
||||
lex_FloatAddRange(id, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1]);
|
||||
lex_FloatAddRange(id, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2]);
|
||||
@@ -452,7 +524,7 @@ setuplex(void)
|
||||
|
||||
//Hex constants
|
||||
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
id = lex_FloatAlloc(&tNumberToken);
|
||||
lex_FloatAddFirstRange(id, '$', '$');
|
||||
lex_FloatAddSecondRange(id, '0', '9');
|
||||
lex_FloatAddSecondRange(id, 'A', 'F');
|
||||
@@ -463,7 +535,7 @@ setuplex(void)
|
||||
|
||||
//ID 's
|
||||
|
||||
id = lex_FloatAlloc(&tIDToken);
|
||||
id = lex_FloatAlloc(&tIDToken);
|
||||
lex_FloatAddFirstRange(id, 'a', 'z');
|
||||
lex_FloatAddFirstRange(id, 'A', 'Z');
|
||||
lex_FloatAddFirstRange(id, '_', '_');
|
||||
@@ -474,6 +546,7 @@ setuplex(void)
|
||||
lex_FloatAddSecondRange(id, '\\', '\\');
|
||||
lex_FloatAddSecondRange(id, '@', '@');
|
||||
lex_FloatAddSecondRange(id, '#', '#');
|
||||
lex_FloatAddRange(id, '.', '.');
|
||||
lex_FloatAddRange(id, 'a', 'z');
|
||||
lex_FloatAddRange(id, 'A', 'Z');
|
||||
lex_FloatAddRange(id, '0', '9');
|
||||
@@ -484,7 +557,7 @@ setuplex(void)
|
||||
|
||||
//Local ID
|
||||
|
||||
id = lex_FloatAlloc(&tIDToken);
|
||||
id = lex_FloatAlloc(&tIDToken);
|
||||
lex_FloatAddFirstRange(id, '.', '.');
|
||||
lex_FloatAddSecondRange(id, 'a', 'z');
|
||||
lex_FloatAddSecondRange(id, 'A', 'Z');
|
||||
@@ -499,17 +572,16 @@ setuplex(void)
|
||||
|
||||
//@ID
|
||||
|
||||
id = lex_FloatAlloc(&tIDToken);
|
||||
id = lex_FloatAlloc(&tIDToken);
|
||||
lex_FloatAddFirstRange(id, '@', '@');
|
||||
|
||||
//Fixed point constants
|
||||
|
||||
id = lex_FloatAlloc(&tFixedPointToken);
|
||||
id = lex_FloatAlloc(&tFixedPointToken);
|
||||
lex_FloatAddFirstRange(id, '.', '.');
|
||||
lex_FloatAddFirstRange(id, '0', '9');
|
||||
lex_FloatAddSecondRange(id, '.', '.');
|
||||
lex_FloatAddSecondRange(id, '0', '9');
|
||||
lex_FloatAddRange(id, '.', '.');
|
||||
lex_FloatAddRange(id, '0', '9');
|
||||
|
||||
}
|
||||
|
||||
473
src/asm/lexer.c
473
src/asm/lexer.c
@@ -1,47 +1,45 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "asm/asm.h"
|
||||
#include "asm/fstack.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "types.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/rpn.h"
|
||||
#include "asm/fstack.h"
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "asmy.h"
|
||||
|
||||
struct sLexString {
|
||||
char *tzName;
|
||||
ULONG nToken;
|
||||
ULONG nNameLength;
|
||||
uint32_t nToken;
|
||||
uint32_t nNameLength;
|
||||
struct sLexString *pNext;
|
||||
};
|
||||
#define pLexBufferRealStart (pCurrentBuffer->pBufferRealStart)
|
||||
#define pLexBuffer (pCurrentBuffer->pBuffer)
|
||||
#define AtLineStart (pCurrentBuffer->oAtLineStart)
|
||||
|
||||
#define SAFETYMARGIN 1024
|
||||
#define pLexBufferRealStart (pCurrentBuffer->pBufferRealStart)
|
||||
#define pLexBuffer (pCurrentBuffer->pBuffer)
|
||||
#define AtLineStart (pCurrentBuffer->oAtLineStart)
|
||||
|
||||
extern size_t symvaluetostring(char *dest, size_t maxLength, char *sym);
|
||||
#define SAFETYMARGIN 1024
|
||||
|
||||
struct sLexFloat tLexFloat[32];
|
||||
struct sLexString *tLexHash[LEXHASHSIZE];
|
||||
YY_BUFFER_STATE pCurrentBuffer;
|
||||
ULONG nLexMaxLength; // max length of all keywords and operators
|
||||
uint32_t nLexMaxLength; // max length of all keywords and operators
|
||||
|
||||
ULONG tFloatingSecondChar[256];
|
||||
ULONG tFloatingFirstChar[256];
|
||||
ULONG tFloatingChars[256];
|
||||
ULONG nFloating;
|
||||
uint32_t tFloatingSecondChar[256];
|
||||
uint32_t tFloatingFirstChar[256];
|
||||
uint32_t tFloatingChars[256];
|
||||
uint32_t nFloating;
|
||||
enum eLexerState lexerstate = LEX_STATE_NORMAL;
|
||||
|
||||
#ifdef __GNUC__
|
||||
void
|
||||
strupr(char *s)
|
||||
void upperstring(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = toupper(*s);
|
||||
@@ -49,29 +47,25 @@ strupr(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
strlwr(char *s)
|
||||
void lowerstring(char *s)
|
||||
{
|
||||
while (*s) {
|
||||
*s = tolower(*s);
|
||||
s += 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void
|
||||
yyskipbytes(ULONG count)
|
||||
|
||||
void yyskipbytes(uint32_t count)
|
||||
{
|
||||
pLexBuffer += count;
|
||||
}
|
||||
|
||||
void
|
||||
yyunputbytes(ULONG count)
|
||||
void yyunputbytes(uint32_t count)
|
||||
{
|
||||
pLexBuffer -= count;
|
||||
}
|
||||
|
||||
void
|
||||
yyunput(char c)
|
||||
void yyunput(char c)
|
||||
{
|
||||
if (pLexBuffer <= pLexBufferRealStart)
|
||||
fatalerror("Buffer safety margin exceeded");
|
||||
@@ -79,10 +73,9 @@ yyunput(char c)
|
||||
*(--pLexBuffer) = c;
|
||||
}
|
||||
|
||||
void
|
||||
yyunputstr(char *s)
|
||||
void yyunputstr(char *s)
|
||||
{
|
||||
int i, len;
|
||||
int32_t i, len;
|
||||
|
||||
len = strlen(s);
|
||||
|
||||
@@ -93,114 +86,109 @@ yyunputstr(char *s)
|
||||
*(--pLexBuffer) = s[i];
|
||||
}
|
||||
|
||||
void
|
||||
yy_switch_to_buffer(YY_BUFFER_STATE buf)
|
||||
void yy_switch_to_buffer(YY_BUFFER_STATE buf)
|
||||
{
|
||||
pCurrentBuffer = buf;
|
||||
}
|
||||
|
||||
void
|
||||
yy_set_state(enum eLexerState i)
|
||||
void yy_set_state(enum eLexerState i)
|
||||
{
|
||||
lexerstate = i;
|
||||
}
|
||||
|
||||
void
|
||||
yy_delete_buffer(YY_BUFFER_STATE buf)
|
||||
void yy_delete_buffer(YY_BUFFER_STATE buf)
|
||||
{
|
||||
free(buf->pBufferStart - SAFETYMARGIN);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
YY_BUFFER_STATE
|
||||
yy_scan_bytes(char *mem, ULONG size)
|
||||
YY_BUFFER_STATE yy_scan_bytes(char *mem, uint32_t size)
|
||||
{
|
||||
YY_BUFFER_STATE pBuffer;
|
||||
YY_BUFFER_STATE pBuffer = malloc(sizeof(struct yy_buffer_state));
|
||||
|
||||
if ((pBuffer = malloc(sizeof(struct yy_buffer_state))) != NULL) {
|
||||
if ((pBuffer->pBufferRealStart =
|
||||
malloc(size + 1 + SAFETYMARGIN)) != NULL) {
|
||||
pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
memcpy(pBuffer->pBuffer, mem, size);
|
||||
pBuffer->nBufferSize = size;
|
||||
pBuffer->oAtLineStart = 1;
|
||||
pBuffer->pBuffer[size] = 0;
|
||||
return (pBuffer);
|
||||
}
|
||||
}
|
||||
fatalerror("Out of memory!");
|
||||
return (NULL);
|
||||
if (pBuffer == NULL)
|
||||
fatalerror("%s: Out of memory!", __func__);
|
||||
|
||||
pBuffer->pBufferRealStart = malloc(size + 1 + SAFETYMARGIN);
|
||||
|
||||
if (pBuffer->pBufferRealStart == NULL)
|
||||
fatalerror("%s: Out of memory for buffer!", __func__);
|
||||
|
||||
pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
memcpy(pBuffer->pBuffer, mem, size);
|
||||
pBuffer->nBufferSize = size;
|
||||
pBuffer->oAtLineStart = 1;
|
||||
pBuffer->pBuffer[size] = 0;
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
YY_BUFFER_STATE
|
||||
yy_create_buffer(FILE * f)
|
||||
YY_BUFFER_STATE yy_create_buffer(FILE *f)
|
||||
{
|
||||
YY_BUFFER_STATE pBuffer;
|
||||
YY_BUFFER_STATE pBuffer = malloc(sizeof(struct yy_buffer_state));
|
||||
|
||||
if ((pBuffer = malloc(sizeof(struct yy_buffer_state))) != NULL) {
|
||||
ULONG size;
|
||||
if (pBuffer == NULL)
|
||||
fatalerror("%s: Out of memory!", __func__);
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
uint32_t size;
|
||||
|
||||
if ((pBuffer->pBufferRealStart =
|
||||
malloc(size + 2 + SAFETYMARGIN)) != NULL) {
|
||||
char *mem;
|
||||
ULONG instring = 0;
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
pBuffer->pBufferRealStart = malloc(size + 2 + SAFETYMARGIN);
|
||||
|
||||
size = fread(pBuffer->pBuffer, sizeof(UBYTE), size, f);
|
||||
if (pBuffer->pBufferRealStart == NULL)
|
||||
fatalerror("%s: Out of memory for buffer!", __func__);
|
||||
|
||||
pBuffer->pBuffer[size] = '\n';
|
||||
pBuffer->pBuffer[size + 1] = 0;
|
||||
pBuffer->nBufferSize = size + 1;
|
||||
pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
|
||||
mem = pBuffer->pBuffer;
|
||||
size = fread(pBuffer->pBuffer, sizeof(uint8_t), size, f);
|
||||
|
||||
while (*mem) {
|
||||
if (*mem == '\"')
|
||||
instring = 1 - instring;
|
||||
pBuffer->pBuffer[size] = '\n';
|
||||
pBuffer->pBuffer[size + 1] = 0;
|
||||
pBuffer->nBufferSize = size + 1;
|
||||
|
||||
if (mem[0] == '\\' &&
|
||||
(mem[1] == '\"' || mem[1] == '\\')) {
|
||||
mem += 2;
|
||||
} else if (instring) {
|
||||
mem += 1;
|
||||
} else {
|
||||
if ((mem[0] == 10 && mem[1] == 13)
|
||||
|| (mem[0] == 13 && mem[1] == 10)) {
|
||||
mem[0] = ' ';
|
||||
mem[1] = '\n';
|
||||
mem += 2;
|
||||
} else if (mem[0] == 10 || mem[0] == 13) {
|
||||
mem[0] = '\n';
|
||||
mem += 1;
|
||||
} else if (mem[0] == '\n' && mem[1] == '*') {
|
||||
mem += 1;
|
||||
while (!(*mem == '\n' || *mem == '\0'))
|
||||
*mem++ = ' ';
|
||||
} else if (*mem == ';') {
|
||||
while (!(*mem == '\n' || *mem == '\0'))
|
||||
*mem++ = ' ';
|
||||
} else
|
||||
mem += 1;
|
||||
}
|
||||
char *mem = pBuffer->pBuffer;
|
||||
uint32_t instring = 0;
|
||||
|
||||
while (*mem) {
|
||||
if (*mem == '\"')
|
||||
instring = 1 - instring;
|
||||
|
||||
if ((mem[0] == '\\') && (mem[1] == '\"' || mem[1] == '\\')) {
|
||||
mem += 2;
|
||||
} else if (instring) {
|
||||
mem += 1;
|
||||
} else {
|
||||
if ((mem[0] == 10 && mem[1] == 13)
|
||||
|| (mem[0] == 13 && mem[1] == 10)) {
|
||||
mem[0] = ' ';
|
||||
mem[1] = '\n';
|
||||
mem += 2;
|
||||
} else if (mem[0] == 10 || mem[0] == 13) {
|
||||
mem[0] = '\n';
|
||||
mem += 1;
|
||||
} else if (mem[0] == '\n' && mem[1] == '*') {
|
||||
mem += 1;
|
||||
while (!(*mem == '\n' || *mem == '\0'))
|
||||
*mem++ = ' ';
|
||||
} else if (*mem == ';') {
|
||||
while (!(*mem == '\n' || *mem == '\0'))
|
||||
*mem++ = ' ';
|
||||
} else {
|
||||
mem += 1;
|
||||
}
|
||||
|
||||
pBuffer->oAtLineStart = 1;
|
||||
return (pBuffer);
|
||||
}
|
||||
}
|
||||
fatalerror("Out of memory!");
|
||||
return (NULL);
|
||||
|
||||
pBuffer->oAtLineStart = 1;
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
ULONG
|
||||
lex_FloatAlloc(struct sLexFloat *token)
|
||||
uint32_t lex_FloatAlloc(const struct sLexFloat *token)
|
||||
{
|
||||
tLexFloat[nFloating] = *token;
|
||||
|
||||
@@ -211,17 +199,15 @@ lex_FloatAlloc(struct sLexFloat *token)
|
||||
* Make sure that only non-zero ASCII characters are used. Also, check if the
|
||||
* start is greater than the end of the range.
|
||||
*/
|
||||
void
|
||||
lex_CheckCharacterRange(UWORD start, UWORD end)
|
||||
void lex_CheckCharacterRange(uint16_t start, uint16_t end)
|
||||
{
|
||||
if (start > end || start < 1 || end > 127) {
|
||||
errx(1, "Invalid character range (start: %u, end: %u)",
|
||||
start, end);
|
||||
start, end);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end)
|
||||
void lex_FloatDeleteRange(uint32_t id, uint16_t start, uint16_t end)
|
||||
{
|
||||
lex_CheckCharacterRange(start, end);
|
||||
|
||||
@@ -231,8 +217,7 @@ lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lex_FloatAddRange(ULONG id, UWORD start, UWORD end)
|
||||
void lex_FloatAddRange(uint32_t id, uint16_t start, uint16_t end)
|
||||
{
|
||||
lex_CheckCharacterRange(start, end);
|
||||
|
||||
@@ -242,8 +227,7 @@ lex_FloatAddRange(ULONG id, UWORD start, UWORD end)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end)
|
||||
void lex_FloatDeleteFirstRange(uint32_t id, uint16_t start, uint16_t end)
|
||||
{
|
||||
lex_CheckCharacterRange(start, end);
|
||||
|
||||
@@ -253,8 +237,7 @@ lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end)
|
||||
void lex_FloatAddFirstRange(uint32_t id, uint16_t start, uint16_t end)
|
||||
{
|
||||
lex_CheckCharacterRange(start, end);
|
||||
|
||||
@@ -264,8 +247,7 @@ lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end)
|
||||
void lex_FloatDeleteSecondRange(uint32_t id, uint16_t start, uint16_t end)
|
||||
{
|
||||
lex_CheckCharacterRange(start, end);
|
||||
|
||||
@@ -275,8 +257,7 @@ lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end)
|
||||
void lex_FloatAddSecondRange(uint32_t id, uint16_t start, uint16_t end)
|
||||
{
|
||||
lex_CheckCharacterRange(start, end);
|
||||
|
||||
@@ -286,43 +267,37 @@ lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end)
|
||||
}
|
||||
}
|
||||
|
||||
struct sLexFloat *
|
||||
lexgetfloat(ULONG nFloatMask)
|
||||
static struct sLexFloat *lexgetfloat(uint32_t nFloatMask)
|
||||
{
|
||||
if (nFloatMask == 0) {
|
||||
fatalerror("Internal error in lexgetfloat");
|
||||
}
|
||||
if (nFloatMask == 0)
|
||||
fatalerror("Internal error in %s", __func__);
|
||||
|
||||
int i = 0;
|
||||
int32_t i = 0;
|
||||
|
||||
while ((nFloatMask & 1) == 0) {
|
||||
nFloatMask >>= 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
return (&tLexFloat[i]);
|
||||
return &tLexFloat[i];
|
||||
}
|
||||
|
||||
ULONG
|
||||
lexcalchash(char *s)
|
||||
static uint32_t lexcalchash(char *s)
|
||||
{
|
||||
ULONG hash = 0;
|
||||
uint32_t hash = 0;
|
||||
|
||||
while (*s) {
|
||||
while (*s)
|
||||
hash = (hash * 283) ^ toupper(*s++);
|
||||
}
|
||||
|
||||
return (hash % LEXHASHSIZE);
|
||||
return hash % LEXHASHSIZE;
|
||||
}
|
||||
|
||||
void
|
||||
lex_Init(void)
|
||||
void lex_Init(void)
|
||||
{
|
||||
ULONG i;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < LEXHASHSIZE; i++) {
|
||||
for (i = 0; i < LEXHASHSIZE; i++)
|
||||
tLexHash[i] = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
tFloatingFirstChar[i] = 0;
|
||||
@@ -334,34 +309,33 @@ lex_Init(void)
|
||||
nFloating = 0;
|
||||
}
|
||||
|
||||
void
|
||||
lex_AddStrings(struct sLexInitString * lex)
|
||||
void lex_AddStrings(const struct sLexInitString *lex)
|
||||
{
|
||||
while (lex->tzName) {
|
||||
struct sLexString **ppHash;
|
||||
ULONG hash;
|
||||
uint32_t hash;
|
||||
|
||||
ppHash = &tLexHash[hash = lexcalchash(lex->tzName)];
|
||||
while (*ppHash)
|
||||
ppHash = &((*ppHash)->pNext);
|
||||
|
||||
if (((*ppHash) = malloc(sizeof(struct sLexString))) != NULL) {
|
||||
if (((*ppHash)->tzName =
|
||||
(char *) strdup(lex->tzName)) != NULL) {
|
||||
(*ppHash)->nNameLength = strlen(lex->tzName);
|
||||
(*ppHash)->nToken = lex->nToken;
|
||||
(*ppHash)->pNext = NULL;
|
||||
|
||||
strupr((*ppHash)->tzName);
|
||||
|
||||
if ((*ppHash)->nNameLength > nLexMaxLength)
|
||||
nLexMaxLength = (*ppHash)->nNameLength;
|
||||
|
||||
} else
|
||||
fatalerror("Out of memory!");
|
||||
} else
|
||||
*ppHash = malloc(sizeof(struct sLexString));
|
||||
if (*ppHash == NULL)
|
||||
fatalerror("Out of memory!");
|
||||
|
||||
(*ppHash)->tzName = (char *)strdup(lex->tzName);
|
||||
if ((*ppHash)->tzName == NULL)
|
||||
fatalerror("Out of memory!");
|
||||
|
||||
(*ppHash)->nNameLength = strlen(lex->tzName);
|
||||
(*ppHash)->nToken = lex->nToken;
|
||||
(*ppHash)->pNext = NULL;
|
||||
|
||||
upperstring((*ppHash)->tzName);
|
||||
|
||||
if ((*ppHash)->nNameLength > nLexMaxLength)
|
||||
nLexMaxLength = (*ppHash)->nNameLength;
|
||||
|
||||
lex += 1;
|
||||
}
|
||||
}
|
||||
@@ -376,42 +350,42 @@ lex_AddStrings(struct sLexInitString * lex)
|
||||
* The token types with the longest match from the current position in the
|
||||
* buffer will have their bits set in the float mask.
|
||||
*/
|
||||
void
|
||||
yylex_GetFloatMaskAndFloatLen(ULONG *pnFloatMask, ULONG *pnFloatLen)
|
||||
void yylex_GetFloatMaskAndFloatLen(uint32_t *pnFloatMask, uint32_t *pnFloatLen)
|
||||
{
|
||||
// Note that '\0' should always have a bit mask of 0 in the "floating"
|
||||
// tables, so it doesn't need to be checked for separately.
|
||||
/*
|
||||
* Note that '\0' should always have a bit mask of 0 in the "floating"
|
||||
* tables, so it doesn't need to be checked for separately.
|
||||
*/
|
||||
|
||||
char *s = pLexBuffer;
|
||||
ULONG nOldFloatMask = 0;
|
||||
ULONG nFloatMask = tFloatingFirstChar[(int)*s];
|
||||
uint32_t nOldFloatMask = 0;
|
||||
uint32_t nFloatMask = tFloatingFirstChar[(int32_t)*s];
|
||||
|
||||
if (nFloatMask != 0) {
|
||||
s++;
|
||||
nOldFloatMask = nFloatMask;
|
||||
nFloatMask &= tFloatingSecondChar[(int)*s];
|
||||
nFloatMask &= tFloatingSecondChar[(int32_t)*s];
|
||||
|
||||
while (nFloatMask != 0) {
|
||||
s++;
|
||||
nOldFloatMask = nFloatMask;
|
||||
nFloatMask &= tFloatingChars[(int)*s];
|
||||
nFloatMask &= tFloatingChars[(int32_t)*s];
|
||||
}
|
||||
}
|
||||
|
||||
*pnFloatMask = nOldFloatMask;
|
||||
*pnFloatLen = (ULONG)(s - pLexBuffer);
|
||||
*pnFloatLen = (uint32_t)(s - pLexBuffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the longest keyword/operator from the current position in the buffer.
|
||||
*/
|
||||
struct sLexString *
|
||||
yylex_GetLongestFixed()
|
||||
struct sLexString *yylex_GetLongestFixed()
|
||||
{
|
||||
struct sLexString *pLongestFixed = NULL;
|
||||
char *s = pLexBuffer;
|
||||
ULONG hash = 0;
|
||||
ULONG length = 0;
|
||||
uint32_t hash = 0;
|
||||
uint32_t length = 0;
|
||||
|
||||
while (length < nLexMaxLength && *s) {
|
||||
hash = (hash * 283) ^ toupper(*s);
|
||||
@@ -433,13 +407,12 @@ yylex_GetLongestFixed()
|
||||
return pLongestFixed;
|
||||
}
|
||||
|
||||
size_t
|
||||
CopyMacroArg(char *dest, size_t maxLength, char c)
|
||||
size_t CopyMacroArg(char *dest, size_t maxLength, char c)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
char *s;
|
||||
int argNum;
|
||||
|
||||
int32_t argNum;
|
||||
|
||||
switch (c) {
|
||||
case '1':
|
||||
case '2':
|
||||
@@ -459,35 +432,33 @@ CopyMacroArg(char *dest, size_t maxLength, char c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((s = sym_FindMacroArg(argNum)) == NULL)
|
||||
s = sym_FindMacroArg(argNum);
|
||||
|
||||
if (s == NULL)
|
||||
fatalerror("Macro argument not defined");
|
||||
|
||||
for (i = 0; s[i] != 0; i++) {
|
||||
if (i >= maxLength) {
|
||||
if (i >= maxLength)
|
||||
fatalerror("Macro argument too long to fit buffer");
|
||||
}
|
||||
|
||||
dest[i] = s[i];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static inline void
|
||||
yylex_StringWriteChar(char *s, size_t index, char c)
|
||||
static inline void yylex_StringWriteChar(char *s, size_t index, char c)
|
||||
{
|
||||
if (index >= MAXSTRLEN) {
|
||||
if (index >= MAXSTRLEN)
|
||||
fatalerror("String too long");
|
||||
}
|
||||
|
||||
s[index] = c;
|
||||
}
|
||||
|
||||
static inline void
|
||||
yylex_SymbolWriteChar(char *s, size_t index, char c)
|
||||
static inline void yylex_SymbolWriteChar(char *s, size_t index, char c)
|
||||
{
|
||||
if (index >= MAXSYMLEN) {
|
||||
if (index >= MAXSYMLEN)
|
||||
fatalerror("Symbol too long");
|
||||
}
|
||||
|
||||
s[index] = c;
|
||||
}
|
||||
@@ -498,14 +469,15 @@ yylex_SymbolWriteChar(char *s, size_t index, char c)
|
||||
*/
|
||||
void yylex_TrimEnd(char *s, size_t index)
|
||||
{
|
||||
int i;
|
||||
int32_t i = (int32_t)index - 1;
|
||||
|
||||
for (i = (int)index - 1; i >= 0 && (s[i] == ' ' || s[i] == '\t'); i--)
|
||||
while ((i >= 0) && (s[i] == ' ' || s[i] == '\t')) {
|
||||
s[i] = 0;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
yylex_ReadBracketedSymbol(char *dest, size_t index)
|
||||
size_t yylex_ReadBracketedSymbol(char *dest, size_t index)
|
||||
{
|
||||
char sym[MAXSYMLEN + 1];
|
||||
char ch;
|
||||
@@ -524,25 +496,26 @@ yylex_ReadBracketedSymbol(char *dest, size_t index)
|
||||
i += length;
|
||||
else
|
||||
fatalerror("Illegal character escape '%c'", ch);
|
||||
} else
|
||||
} else {
|
||||
yylex_SymbolWriteChar(sym, i++, ch);
|
||||
}
|
||||
}
|
||||
|
||||
yylex_SymbolWriteChar(sym, i, 0);
|
||||
|
||||
maxLength = MAXSTRLEN - index; // it's assumed we're writing to a T_STRING
|
||||
/* It's assumed we're writing to a T_STRING */
|
||||
maxLength = MAXSTRLEN - index;
|
||||
length = symvaluetostring(&dest[index], maxLength, sym);
|
||||
|
||||
if (*pLexBuffer == '}')
|
||||
pLexBuffer++;
|
||||
else
|
||||
yyerror("Missing }");
|
||||
fatalerror("Missing }");
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
void
|
||||
yylex_ReadQuotedString()
|
||||
static void yylex_ReadQuotedString(void)
|
||||
{
|
||||
size_t index = 0;
|
||||
size_t length, maxLength;
|
||||
@@ -566,21 +539,33 @@ yylex_ReadQuotedString()
|
||||
case '"':
|
||||
ch = '"';
|
||||
break;
|
||||
case ',':
|
||||
ch = ',';
|
||||
break;
|
||||
case '{':
|
||||
ch = '{';
|
||||
break;
|
||||
case '}':
|
||||
ch = '}';
|
||||
break;
|
||||
default:
|
||||
maxLength = MAXSTRLEN - index;
|
||||
length = CopyMacroArg(&yylval.tzString[index], maxLength, ch);
|
||||
length = CopyMacroArg(&yylval.tzString[index],
|
||||
maxLength, ch);
|
||||
|
||||
if (length != 0)
|
||||
index += length;
|
||||
else
|
||||
fatalerror("Illegal character escape '%c'", ch);
|
||||
fatalerror("Illegal character escape '%c'",
|
||||
ch);
|
||||
|
||||
ch = 0;
|
||||
break;
|
||||
}
|
||||
} else if (ch == '{') {
|
||||
// Get bracketed symbol within string.
|
||||
index += yylex_ReadBracketedSymbol(yylval.tzString, index);
|
||||
index += yylex_ReadBracketedSymbol(yylval.tzString,
|
||||
index);
|
||||
ch = 0;
|
||||
}
|
||||
|
||||
@@ -593,15 +578,14 @@ yylex_ReadQuotedString()
|
||||
if (*pLexBuffer == '"')
|
||||
pLexBuffer++;
|
||||
else
|
||||
yyerror("Unterminated string");
|
||||
fatalerror("Unterminated string");
|
||||
}
|
||||
|
||||
ULONG
|
||||
yylex_NORMAL()
|
||||
static uint32_t yylex_NORMAL(void)
|
||||
{
|
||||
struct sLexString *pLongestFixed = NULL;
|
||||
ULONG nFloatMask, nFloatLen;
|
||||
ULONG linestart = AtLineStart;
|
||||
uint32_t nFloatMask, nFloatLen;
|
||||
uint32_t linestart = AtLineStart;
|
||||
|
||||
AtLineStart = 0;
|
||||
|
||||
@@ -620,15 +604,20 @@ scanagain:
|
||||
}
|
||||
}
|
||||
|
||||
// Try to match an identifier, macro argument (e.g. \1),
|
||||
// or numeric literal.
|
||||
/*
|
||||
* Try to match an identifier, macro argument (e.g. \1),
|
||||
* or numeric literal.
|
||||
*/
|
||||
yylex_GetFloatMaskAndFloatLen(&nFloatMask, &nFloatLen);
|
||||
|
||||
// Try to match a keyword or operator.
|
||||
/* Try to match a keyword or operator. */
|
||||
pLongestFixed = yylex_GetLongestFixed();
|
||||
|
||||
if (nFloatLen == 0 && pLongestFixed == NULL) {
|
||||
// No keyword, identifier, operator, or numerical literal matches.
|
||||
/*
|
||||
* No keyword, identifier, operator, or numerical literal
|
||||
* matches.
|
||||
*/
|
||||
|
||||
if (*pLexBuffer == '"') {
|
||||
pLexBuffer++;
|
||||
@@ -638,52 +627,55 @@ scanagain:
|
||||
pLexBuffer++;
|
||||
yylex_ReadBracketedSymbol(yylval.tzString, 0);
|
||||
return T_STRING;
|
||||
} else {
|
||||
// It's not a keyword, operator, identifier, macro argument,
|
||||
// numeric literal, string, or bracketed symbol, so just return
|
||||
// the ASCII character.
|
||||
if (*pLexBuffer == '\n')
|
||||
AtLineStart = 1;
|
||||
|
||||
return *pLexBuffer++;
|
||||
}
|
||||
|
||||
/*
|
||||
* It's not a keyword, operator, identifier, macro argument,
|
||||
* numeric literal, string, or bracketed symbol, so just return
|
||||
* the ASCII character.
|
||||
*/
|
||||
if (*pLexBuffer == '\n')
|
||||
AtLineStart = 1;
|
||||
|
||||
return *pLexBuffer++;
|
||||
}
|
||||
|
||||
if (pLongestFixed == NULL || nFloatLen > pLongestFixed->nNameLength) {
|
||||
// Longest match was an identifier, macro argument, or numeric literal.
|
||||
/*
|
||||
* Longest match was an identifier, macro argument, or numeric
|
||||
* literal.
|
||||
*/
|
||||
struct sLexFloat *token = lexgetfloat(nFloatMask);
|
||||
|
||||
if (token->Callback) {
|
||||
int done = token->Callback(pLexBuffer, nFloatLen);
|
||||
int32_t done = token->Callback(pLexBuffer, nFloatLen);
|
||||
|
||||
if (!done)
|
||||
goto scanagain;
|
||||
}
|
||||
|
||||
pLexBuffer += nFloatLen;
|
||||
|
||||
if (token->nToken == T_ID && linestart) {
|
||||
if (token->nToken == T_ID && linestart)
|
||||
return T_LABEL;
|
||||
} else {
|
||||
else
|
||||
return token->nToken;
|
||||
}
|
||||
}
|
||||
|
||||
// Longest match was a keyword or operator.
|
||||
/* Longest match was a keyword or operator. */
|
||||
pLexBuffer += pLongestFixed->nNameLength;
|
||||
return pLongestFixed->nToken;
|
||||
}
|
||||
|
||||
ULONG
|
||||
yylex_MACROARGS()
|
||||
static uint32_t yylex_MACROARGS(void)
|
||||
{
|
||||
size_t index = 0;
|
||||
size_t length, maxLength;
|
||||
|
||||
while (*pLexBuffer == ' ' || *pLexBuffer == '\t') {
|
||||
while ((*pLexBuffer == ' ') || (*pLexBuffer == '\t'))
|
||||
pLexBuffer++;
|
||||
}
|
||||
|
||||
while (*pLexBuffer != ',' && (*pLexBuffer != '\n')) {
|
||||
while ((*pLexBuffer != ',') && (*pLexBuffer != '\n')) {
|
||||
char ch = *pLexBuffer++;
|
||||
|
||||
if (ch == '\\') {
|
||||
@@ -699,20 +691,32 @@ yylex_MACROARGS()
|
||||
case '\\':
|
||||
ch = '\\';
|
||||
break;
|
||||
case ',':
|
||||
ch = ',';
|
||||
break;
|
||||
case '{':
|
||||
ch = '{';
|
||||
break;
|
||||
case '}':
|
||||
ch = '}';
|
||||
break;
|
||||
default:
|
||||
maxLength = MAXSTRLEN - index;
|
||||
length = CopyMacroArg(&yylval.tzString[index], maxLength, ch);
|
||||
length = CopyMacroArg(&yylval.tzString[index],
|
||||
maxLength, ch);
|
||||
|
||||
if (length != 0)
|
||||
index += length;
|
||||
else
|
||||
fatalerror("Illegal character escape '%c'", ch);
|
||||
|
||||
fatalerror("Illegal character escape '%c'",
|
||||
ch);
|
||||
|
||||
ch = 0;
|
||||
break;
|
||||
}
|
||||
} else if (ch == '{') {
|
||||
index += yylex_ReadBracketedSymbol(yylval.tzString, index);
|
||||
index += yylex_ReadBracketedSymbol(yylval.tzString,
|
||||
index);
|
||||
ch = 0;
|
||||
}
|
||||
if (ch)
|
||||
@@ -722,7 +726,7 @@ yylex_MACROARGS()
|
||||
if (index) {
|
||||
yylex_StringWriteChar(yylval.tzString, index, 0);
|
||||
|
||||
// trim trailing white space at the end of the line
|
||||
/* trim trailing white space at the end of the line */
|
||||
if (*pLexBuffer == '\n')
|
||||
yylex_TrimEnd(yylval.tzString, index);
|
||||
|
||||
@@ -736,12 +740,10 @@ yylex_MACROARGS()
|
||||
return ',';
|
||||
}
|
||||
|
||||
fatalerror("Internal error in yylex_MACROARGS");
|
||||
return 0;
|
||||
fatalerror("Internal error in %s", __func__);
|
||||
}
|
||||
|
||||
ULONG
|
||||
yylex(void)
|
||||
uint32_t yylex(void)
|
||||
{
|
||||
switch (lexerstate) {
|
||||
case LEX_STATE_NORMAL:
|
||||
@@ -750,6 +752,5 @@ yylex(void)
|
||||
return yylex_MACROARGS();
|
||||
}
|
||||
|
||||
fatalerror("Internal error in yylex");
|
||||
return 0;
|
||||
fatalerror("Internal error in %s", __func__);
|
||||
}
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "asm/rpn.h"
|
||||
|
||||
#include "asmy.h"
|
||||
|
||||
struct sLexInitString localstrings[] = {
|
||||
{"adc", T_Z80_ADC},
|
||||
{"add", T_Z80_ADD},
|
||||
{"and", T_Z80_AND},
|
||||
{"bit", T_Z80_BIT},
|
||||
{"call", T_Z80_CALL},
|
||||
{"ccf", T_Z80_CCF},
|
||||
{"cpl", T_Z80_CPL},
|
||||
{"cp", T_Z80_CP},
|
||||
{"daa", T_Z80_DAA},
|
||||
{"dec", T_Z80_DEC},
|
||||
{"di", T_Z80_DI},
|
||||
{"ei", T_Z80_EI},
|
||||
{"ex", T_Z80_EX},
|
||||
{"halt", T_Z80_HALT},
|
||||
{"inc", T_Z80_INC},
|
||||
{"jp", T_Z80_JP},
|
||||
{"jr", T_Z80_JR},
|
||||
{"ld", T_Z80_LD},
|
||||
{"ldi", T_Z80_LDI},
|
||||
{"ldd", T_Z80_LDD},
|
||||
{"ldio", T_Z80_LDIO},
|
||||
{"ldh", T_Z80_LDIO},
|
||||
{"nop", T_Z80_NOP},
|
||||
{"or", T_Z80_OR},
|
||||
{"pop", T_Z80_POP},
|
||||
{"push", T_Z80_PUSH},
|
||||
{"res", T_Z80_RES},
|
||||
{"reti", T_Z80_RETI},
|
||||
{"ret", T_Z80_RET},
|
||||
{"rlca", T_Z80_RLCA},
|
||||
{"rlc", T_Z80_RLC},
|
||||
{"rla", T_Z80_RLA},
|
||||
{"rl", T_Z80_RL},
|
||||
{"rrc", T_Z80_RRC},
|
||||
{"rrca", T_Z80_RRCA},
|
||||
{"rra", T_Z80_RRA},
|
||||
{"rr", T_Z80_RR},
|
||||
{"rst", T_Z80_RST},
|
||||
{"sbc", T_Z80_SBC},
|
||||
{"scf", T_Z80_SCF},
|
||||
|
||||
/* Handled by globallex.c */
|
||||
/* { "set", T_POP_SET }, */
|
||||
|
||||
{"sla", T_Z80_SLA},
|
||||
{"sra", T_Z80_SRA},
|
||||
{"srl", T_Z80_SRL},
|
||||
{"stop", T_Z80_STOP},
|
||||
{"sub", T_Z80_SUB},
|
||||
{"swap", T_Z80_SWAP},
|
||||
{"xor", T_Z80_XOR},
|
||||
|
||||
{"nz", T_CC_NZ},
|
||||
{"z", T_CC_Z},
|
||||
{"nc", T_CC_NC},
|
||||
/* { "c", T_MODE_C }, */
|
||||
|
||||
{"[hl]", T_MODE_HL_IND},
|
||||
{"[hl+]", T_MODE_HL_INDINC},
|
||||
{"[hl-]", T_MODE_HL_INDDEC},
|
||||
{"[hli]", T_MODE_HL_INDINC},
|
||||
{"[hld]", T_MODE_HL_INDDEC},
|
||||
{"hl", T_MODE_HL},
|
||||
{"af", T_MODE_AF},
|
||||
{"[bc]", T_MODE_BC_IND},
|
||||
{"bc", T_MODE_BC},
|
||||
{"[de]", T_MODE_DE_IND},
|
||||
{"de", T_MODE_DE},
|
||||
{"[sp]", T_MODE_SP_IND},
|
||||
{"sp", T_MODE_SP},
|
||||
{"a", T_MODE_A},
|
||||
{"b", T_MODE_B},
|
||||
{"[$ff00+c]", T_MODE_C_IND},
|
||||
{"[c]", T_MODE_C_IND},
|
||||
{"c", T_MODE_C},
|
||||
{"d", T_MODE_D},
|
||||
{"e", T_MODE_E},
|
||||
{"h", T_MODE_H},
|
||||
{"l", T_MODE_L},
|
||||
|
||||
{NULL, 0}
|
||||
};
|
||||
296
src/asm/main.c
296
src/asm/main.c
@@ -1,6 +1,7 @@
|
||||
#include <math.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
@@ -8,25 +9,29 @@
|
||||
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/fstack.h"
|
||||
#include "asm/lexer.h"
|
||||
#include "asm/output.h"
|
||||
#include "asm/main.h"
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "extern/reallocarray.h"
|
||||
#include "extern/version.h"
|
||||
|
||||
int yyparse(void);
|
||||
void setuplex(void);
|
||||
extern int yyparse(void);
|
||||
|
||||
int cldefines_index;
|
||||
int cldefines_size;
|
||||
int32_t cldefines_index;
|
||||
int32_t cldefines_size;
|
||||
char **cldefines;
|
||||
|
||||
char *progname;
|
||||
|
||||
clock_t nStartClock, nEndClock;
|
||||
SLONG nLineNo;
|
||||
ULONG nTotalLines, nPass, nPC, nIFDepth, nErrors;
|
||||
int32_t nLineNo;
|
||||
uint32_t nTotalLines, nPass, nPC, nIFDepth, nUnionDepth, nErrors;
|
||||
bool skipElif;
|
||||
uint32_t unionStart[128], unionSize[128];
|
||||
|
||||
extern int yydebug;
|
||||
/* extern int yydebug; */
|
||||
|
||||
FILE *dependfile;
|
||||
|
||||
/*
|
||||
* Option stack
|
||||
@@ -40,73 +45,71 @@ struct sOptionStackEntry {
|
||||
struct sOptionStackEntry *pNext;
|
||||
};
|
||||
|
||||
struct sOptionStackEntry *pOptionStack = NULL;
|
||||
struct sOptionStackEntry *pOptionStack;
|
||||
|
||||
void
|
||||
opt_SetCurrentOptions(struct sOptions * pOpt)
|
||||
void opt_SetCurrentOptions(struct sOptions *pOpt)
|
||||
{
|
||||
if (nGBGfxID != -1) {
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
CurrentOptions.gbgfx[3]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
CurrentOptions.gbgfx[3]);
|
||||
}
|
||||
if (nBinaryID != -1) {
|
||||
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
CurrentOptions.binary[1]);
|
||||
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
CurrentOptions.binary[1]);
|
||||
}
|
||||
CurrentOptions = *pOpt;
|
||||
|
||||
if (nGBGfxID != -1) {
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
CurrentOptions.gbgfx[3]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
|
||||
CurrentOptions.gbgfx[0]);
|
||||
CurrentOptions.gbgfx[0]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
|
||||
CurrentOptions.gbgfx[1]);
|
||||
CurrentOptions.gbgfx[1]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
|
||||
CurrentOptions.gbgfx[2]);
|
||||
CurrentOptions.gbgfx[2]);
|
||||
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
|
||||
CurrentOptions.gbgfx[3]);
|
||||
CurrentOptions.gbgfx[3]);
|
||||
}
|
||||
if (nBinaryID != -1) {
|
||||
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
CurrentOptions.binary[1]);
|
||||
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[0],
|
||||
CurrentOptions.binary[0]);
|
||||
CurrentOptions.binary[0]);
|
||||
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[1],
|
||||
CurrentOptions.binary[1]);
|
||||
CurrentOptions.binary[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
opt_Parse(char *s)
|
||||
void opt_Parse(char *s)
|
||||
{
|
||||
struct sOptions newopt;
|
||||
|
||||
@@ -120,8 +123,7 @@ opt_Parse(char *s)
|
||||
newopt.gbgfx[2] = s[3];
|
||||
newopt.gbgfx[3] = s[4];
|
||||
} else {
|
||||
errx(1, "Must specify exactly 4 characters for "
|
||||
"option 'g'");
|
||||
errx(1, "Must specify exactly 4 characters for option 'g'");
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
@@ -129,21 +131,18 @@ opt_Parse(char *s)
|
||||
newopt.binary[0] = s[1];
|
||||
newopt.binary[1] = s[2];
|
||||
} else {
|
||||
errx(1, "Must specify exactly 2 characters for option "
|
||||
"'b'");
|
||||
errx(1, "Must specify exactly 2 characters for option 'b'");
|
||||
}
|
||||
break;
|
||||
case 'z':
|
||||
if (strlen(&s[1]) <= 2) {
|
||||
int result;
|
||||
int32_t result;
|
||||
|
||||
result = sscanf(&s[1], "%lx", &newopt.fillchar);
|
||||
if (!((result == EOF) || (result == 1))) {
|
||||
result = sscanf(&s[1], "%x", &newopt.fillchar);
|
||||
if (!((result == EOF) || (result == 1)))
|
||||
errx(1, "Invalid argument for option 'z'");
|
||||
}
|
||||
} else {
|
||||
errx(1, "Invalid argument for option 'z'");
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -154,116 +153,123 @@ opt_Parse(char *s)
|
||||
opt_SetCurrentOptions(&newopt);
|
||||
}
|
||||
|
||||
void
|
||||
opt_Push(void)
|
||||
void opt_Push(void)
|
||||
{
|
||||
struct sOptionStackEntry *pOpt;
|
||||
|
||||
if ((pOpt = malloc(sizeof(struct sOptionStackEntry))) != NULL) {
|
||||
pOpt->Options = CurrentOptions;
|
||||
pOpt->pNext = pOptionStack;
|
||||
pOptionStack = pOpt;
|
||||
} else
|
||||
pOpt = malloc(sizeof(struct sOptionStackEntry));
|
||||
|
||||
if (pOpt == NULL)
|
||||
fatalerror("No memory for option stack");
|
||||
|
||||
pOpt->Options = CurrentOptions;
|
||||
pOpt->pNext = pOptionStack;
|
||||
pOptionStack = pOpt;
|
||||
}
|
||||
|
||||
void
|
||||
opt_Pop(void)
|
||||
void opt_Pop(void)
|
||||
{
|
||||
if (pOptionStack) {
|
||||
struct sOptionStackEntry *pOpt;
|
||||
|
||||
pOpt = pOptionStack;
|
||||
opt_SetCurrentOptions(&(pOpt->Options));
|
||||
pOptionStack = pOpt->pNext;
|
||||
free(pOpt);
|
||||
} else
|
||||
if (pOptionStack == NULL)
|
||||
fatalerror("No entries in the option stack");
|
||||
|
||||
struct sOptionStackEntry *pOpt;
|
||||
|
||||
pOpt = pOptionStack;
|
||||
opt_SetCurrentOptions(&(pOpt->Options));
|
||||
pOptionStack = pOpt->pNext;
|
||||
free(pOpt);
|
||||
}
|
||||
|
||||
void
|
||||
opt_AddDefine(char *s)
|
||||
void opt_AddDefine(char *s)
|
||||
{
|
||||
char *value, *equals;
|
||||
if(cldefines_index >= cldefines_size)
|
||||
{
|
||||
|
||||
if (cldefines_index >= cldefines_size) {
|
||||
cldefines_size *= 2;
|
||||
cldefines = reallocarray(cldefines, cldefines_size,
|
||||
2 * sizeof(void *));
|
||||
if(!cldefines)
|
||||
{
|
||||
2 * sizeof(void *));
|
||||
if (!cldefines)
|
||||
fatalerror("No memory for command line defines");
|
||||
}
|
||||
}
|
||||
equals = strchr(s, '=');
|
||||
if(equals)
|
||||
{
|
||||
if (equals) {
|
||||
*equals = '\0';
|
||||
value = equals + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
value = "1";
|
||||
}
|
||||
cldefines[cldefines_index++] = s;
|
||||
cldefines[cldefines_index++] = value;
|
||||
}
|
||||
|
||||
void
|
||||
opt_ParseDefines()
|
||||
static void opt_ParseDefines(void)
|
||||
{
|
||||
int i;
|
||||
int32_t i;
|
||||
|
||||
for(i = 0; i < cldefines_index; i += 2)
|
||||
{
|
||||
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)
|
||||
void verror(const char *fmt, va_list args)
|
||||
{
|
||||
fprintf(stderr, "ERROR:\t");
|
||||
fprintf(stderr, "ERROR: ");
|
||||
fstk_Dump();
|
||||
fprintf(stderr, " :\n\t");
|
||||
fprintf(stderr, ":\n\t");
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
nErrors += 1;
|
||||
}
|
||||
|
||||
void
|
||||
yyerror(const char *fmt, ...)
|
||||
void yyerror(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
verror(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void
|
||||
fatalerror(const char *fmt, ...)
|
||||
void fatalerror(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
verror(fmt, args);
|
||||
va_end(args);
|
||||
|
||||
exit(5);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
void warning(const char *fmt, ...)
|
||||
{
|
||||
if (!CurrentOptions.warnings)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
fprintf(stderr, "warning: ");
|
||||
fstk_Dump();
|
||||
fprintf(stderr, ":\n\t");
|
||||
vfprintf(stderr, fmt, args);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"Usage: rgbasm [-hv] [-b chars] [-Dname[=value]] [-g chars] [-i path]\n"
|
||||
" [-o outfile] [-p pad_value] file.asm\n");
|
||||
"usage: rgbasm [-EhVvw] [-b chars] [-Dname[=value]] [-g chars] [-i path]\n"
|
||||
" [-M dependfile] [-o outfile] [-p pad_value] file.asm\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
char *ep;
|
||||
@@ -272,18 +278,15 @@ main(int argc, char *argv[])
|
||||
|
||||
char *tzMainfile;
|
||||
|
||||
dependfile = NULL;
|
||||
|
||||
cldefines_size = 32;
|
||||
cldefines = reallocarray(cldefines, cldefines_size,
|
||||
2 * sizeof(void *));
|
||||
if(!cldefines)
|
||||
{
|
||||
cldefines = reallocarray(cldefines, cldefines_size, 2 * sizeof(void *));
|
||||
if (!cldefines)
|
||||
fatalerror("No memory for command line defines");
|
||||
}
|
||||
|
||||
if (argc == 1)
|
||||
usage();
|
||||
|
||||
progname = argv[0];
|
||||
print_usage();
|
||||
|
||||
/* yydebug=1; */
|
||||
|
||||
@@ -296,25 +299,29 @@ main(int argc, char *argv[])
|
||||
DefaultOptions.fillchar = 0;
|
||||
DefaultOptions.verbose = false;
|
||||
DefaultOptions.haltnop = true;
|
||||
DefaultOptions.exportall = false;
|
||||
DefaultOptions.warnings = true;
|
||||
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
newopt = CurrentOptions;
|
||||
|
||||
while ((ch = getopt(argc, argv, "b:D:g:hi:o:p:v")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "b:D:g:hi:M:o:p:EVvw")) != -1) {
|
||||
switch (ch) {
|
||||
case 'b':
|
||||
if (strlen(optarg) == 2) {
|
||||
newopt.binary[0] = optarg[1];
|
||||
newopt.binary[1] = optarg[2];
|
||||
} else {
|
||||
errx(1, "Must specify exactly 2 characters for "
|
||||
"option 'b'");
|
||||
errx(1, "Must specify exactly 2 characters for option 'b'");
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
opt_AddDefine(optarg);
|
||||
break;
|
||||
case 'E':
|
||||
newopt.exportall = true;
|
||||
break;
|
||||
case 'g':
|
||||
if (strlen(optarg) == 4) {
|
||||
newopt.gbgfx[0] = optarg[1];
|
||||
@@ -322,8 +329,7 @@ main(int argc, char *argv[])
|
||||
newopt.gbgfx[2] = optarg[3];
|
||||
newopt.gbgfx[3] = optarg[4];
|
||||
} else {
|
||||
errx(1, "Must specify exactly 4 characters for "
|
||||
"option 'g'");
|
||||
errx(1, "Must specify exactly 4 characters for option 'g'");
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
@@ -331,25 +337,38 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case 'i':
|
||||
fstk_AddIncludePath(optarg);
|
||||
break;
|
||||
case 'M':
|
||||
dependfile = fopen(optarg, "w");
|
||||
if (dependfile == NULL)
|
||||
err(1, "Could not open dependfile %s", optarg);
|
||||
|
||||
break;
|
||||
case 'o':
|
||||
out_SetFileName(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
newopt.fillchar = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
|
||||
if (optarg[0] == '\0' || *ep != '\0')
|
||||
errx(1, "Invalid argument for option 'p'");
|
||||
}
|
||||
if (newopt.fillchar < 0 || newopt.fillchar > 0xFF) {
|
||||
errx(1, "Argument for option 'p' must be "
|
||||
"between 0 and 0xFF");
|
||||
}
|
||||
|
||||
if (newopt.fillchar < 0 || newopt.fillchar > 0xFF)
|
||||
errx(1, "Argument for option 'p' must be between 0 and 0xFF");
|
||||
|
||||
break;
|
||||
case 'V':
|
||||
printf("rgbasm %s\n", get_package_version_string());
|
||||
exit(0);
|
||||
case 'v':
|
||||
newopt.verbose = true;
|
||||
break;
|
||||
case 'w':
|
||||
newopt.warnings = false;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
print_usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
@@ -360,14 +379,20 @@ main(int argc, char *argv[])
|
||||
DefaultOptions = CurrentOptions;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
print_usage();
|
||||
|
||||
tzMainfile = argv[argc - 1];
|
||||
|
||||
setuplex();
|
||||
setup_lexer();
|
||||
|
||||
if (CurrentOptions.verbose) {
|
||||
if (CurrentOptions.verbose)
|
||||
printf("Assembling %s\n", tzMainfile);
|
||||
|
||||
if (dependfile) {
|
||||
if (!tzObjectname)
|
||||
errx(1, "Dependency files can only be created if an output object file is specified.\n");
|
||||
|
||||
fprintf(dependfile, "%s: %s\n", tzObjectname, tzMainfile);
|
||||
}
|
||||
|
||||
nStartClock = clock();
|
||||
@@ -375,31 +400,38 @@ main(int argc, char *argv[])
|
||||
nLineNo = 1;
|
||||
nTotalLines = 0;
|
||||
nIFDepth = 0;
|
||||
skipElif = true;
|
||||
nUnionDepth = 0;
|
||||
nPC = 0;
|
||||
nPass = 1;
|
||||
nErrors = 0;
|
||||
sym_PrepPass1();
|
||||
sym_SetExportAll(CurrentOptions.exportall);
|
||||
fstk_Init(tzMainfile);
|
||||
opt_ParseDefines();
|
||||
|
||||
if (CurrentOptions.verbose) {
|
||||
if (CurrentOptions.verbose)
|
||||
printf("Pass 1...\n");
|
||||
}
|
||||
|
||||
yy_set_state(LEX_STATE_NORMAL);
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
|
||||
if (yyparse() != 0 || nErrors != 0) {
|
||||
if (yyparse() != 0 || nErrors != 0)
|
||||
errx(1, "Assembly aborted in pass 1 (%ld errors)!", nErrors);
|
||||
}
|
||||
|
||||
if (nIFDepth != 0) {
|
||||
if (nIFDepth != 0)
|
||||
errx(1, "Unterminated IF construct (%ld levels)!", nIFDepth);
|
||||
|
||||
if (nUnionDepth != 0) {
|
||||
errx(1, "Unterminated UNION construct (%ld levels)!",
|
||||
nUnionDepth);
|
||||
}
|
||||
|
||||
nTotalLines = 0;
|
||||
nLineNo = 1;
|
||||
nIFDepth = 0;
|
||||
skipElif = true;
|
||||
nUnionDepth = 0;
|
||||
nPC = 0;
|
||||
nPass = 2;
|
||||
nErrors = 0;
|
||||
@@ -410,27 +442,25 @@ main(int argc, char *argv[])
|
||||
opt_SetCurrentOptions(&DefaultOptions);
|
||||
opt_ParseDefines();
|
||||
|
||||
if (CurrentOptions.verbose) {
|
||||
if (CurrentOptions.verbose)
|
||||
printf("Pass 2...\n");
|
||||
}
|
||||
|
||||
if (yyparse() != 0 || nErrors != 0) {
|
||||
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;
|
||||
/ (double)CLOCKS_PER_SEC;
|
||||
if (CurrentOptions.verbose) {
|
||||
printf("Success! %ld lines in %d.%02d seconds ", nTotalLines,
|
||||
(int) timespent, ((int) (timespent * 100.0)) % 100);
|
||||
printf("Success! %u 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));
|
||||
(int)(60 / timespent * nTotalLines));
|
||||
}
|
||||
out_WriteObject();
|
||||
return 0;
|
||||
|
||||
@@ -3,146 +3,132 @@
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "asm/mymath.h"
|
||||
#include "asm/symbol.h"
|
||||
|
||||
#define fix2double(i) ((double)(i/65536.0))
|
||||
#define double2fix(d) ((SLONG)(d*65536.0))
|
||||
#ifndef PI
|
||||
#define PI (acos(-1))
|
||||
#define fx2double(i) ((double)((i) / 65536.0))
|
||||
#define double2fx(d) ((int32_t)((d) * 65536.0))
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define the _PI symbol
|
||||
*/
|
||||
void
|
||||
math_DefinePI(void)
|
||||
void math_DefinePI(void)
|
||||
{
|
||||
sym_AddEqu("_PI", double2fix(PI));
|
||||
sym_AddEqu("_PI", double2fx(M_PI));
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a fixed point value
|
||||
*/
|
||||
void
|
||||
math_Print(SLONG i)
|
||||
void math_Print(int32_t i)
|
||||
{
|
||||
if (i >= 0)
|
||||
printf("%ld.%05ld", i >> 16,
|
||||
((SLONG) (fix2double(i) * 100000 + 0.5)) % 100000);
|
||||
printf("%d.%05d", i >> 16,
|
||||
((int32_t)(fx2double(i) * 100000 + 0.5)) % 100000);
|
||||
else
|
||||
printf("-%ld.%05ld", (-i) >> 16,
|
||||
((SLONG) (fix2double(-i) * 100000 + 0.5)) % 100000);
|
||||
printf("-%d.%05d", (-i) >> 16,
|
||||
((int32_t)(fx2double(-i) * 100000 + 0.5)) % 100000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate sine
|
||||
*/
|
||||
SLONG
|
||||
math_Sin(SLONG i)
|
||||
int32_t math_Sin(int32_t i)
|
||||
{
|
||||
return (double2fix(sin(fix2double(i) * 2 * PI / 65536)));
|
||||
return double2fx(sin(fx2double(i) * 2 * M_PI / 65536));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate cosine
|
||||
*/
|
||||
SLONG
|
||||
math_Cos(SLONG i)
|
||||
int32_t math_Cos(int32_t i)
|
||||
{
|
||||
return (double2fix(cos(fix2double(i) * 2 * PI / 65536)));
|
||||
return double2fx(cos(fx2double(i) * 2 * M_PI / 65536));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate tangent
|
||||
*/
|
||||
SLONG
|
||||
math_Tan(SLONG i)
|
||||
int32_t math_Tan(int32_t i)
|
||||
{
|
||||
return (double2fix(tan(fix2double(i) * 2 * PI / 65536)));
|
||||
return double2fx(tan(fx2double(i) * 2 * M_PI / 65536));
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate arcsine
|
||||
*/
|
||||
SLONG
|
||||
math_ASin(SLONG i)
|
||||
int32_t math_ASin(int32_t i)
|
||||
{
|
||||
return (double2fix(asin(fix2double(i)) / 2 / PI * 65536));
|
||||
return double2fx(asin(fx2double(i)) / 2 / M_PI * 65536);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate arccosine
|
||||
*/
|
||||
SLONG
|
||||
math_ACos(SLONG i)
|
||||
int32_t math_ACos(int32_t i)
|
||||
{
|
||||
return (double2fix(acos(fix2double(i)) / 2 / PI * 65536));
|
||||
return double2fx(acos(fx2double(i)) / 2 / M_PI * 65536);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate arctangent
|
||||
*/
|
||||
SLONG
|
||||
math_ATan(SLONG i)
|
||||
int32_t math_ATan(int32_t i)
|
||||
{
|
||||
return (double2fix(atan(fix2double(i)) / 2 / PI * 65536));
|
||||
return double2fx(atan(fx2double(i)) / 2 / M_PI * 65536);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate atan2
|
||||
*/
|
||||
SLONG
|
||||
math_ATan2(SLONG i, SLONG j)
|
||||
int32_t math_ATan2(int32_t i, int32_t j)
|
||||
{
|
||||
return (double2fix
|
||||
(atan2(fix2double(i), fix2double(j)) / 2 / PI * 65536));
|
||||
return double2fx(atan2(fx2double(i), fx2double(j)) / 2 / M_PI * 65536);
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiplication
|
||||
*/
|
||||
SLONG
|
||||
math_Mul(SLONG i, SLONG j)
|
||||
int32_t math_Mul(int32_t i, int32_t j)
|
||||
{
|
||||
return (double2fix(fix2double(i) * fix2double(j)));
|
||||
return double2fx(fx2double(i) * fx2double(j));
|
||||
}
|
||||
|
||||
/*
|
||||
* Division
|
||||
*/
|
||||
SLONG
|
||||
math_Div(SLONG i, SLONG j)
|
||||
int32_t math_Div(int32_t i, int32_t j)
|
||||
{
|
||||
return (double2fix(fix2double(i) / fix2double(j)));
|
||||
return double2fx(fx2double(i) / fx2double(j));
|
||||
}
|
||||
|
||||
/*
|
||||
* Round
|
||||
*/
|
||||
SLONG
|
||||
math_Round(SLONG i)
|
||||
int32_t math_Round(int32_t i)
|
||||
{
|
||||
return double2fix(round(fix2double(i)));
|
||||
return double2fx(round(fx2double(i)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ceil
|
||||
*/
|
||||
SLONG
|
||||
math_Ceil(SLONG i)
|
||||
int32_t math_Ceil(int32_t i)
|
||||
{
|
||||
return double2fix(ceil(fix2double(i)));
|
||||
return double2fx(ceil(fx2double(i)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Floor
|
||||
*/
|
||||
SLONG
|
||||
math_Floor(SLONG i)
|
||||
int32_t math_Floor(int32_t i)
|
||||
{
|
||||
return double2fix(floor(fix2double(i)));
|
||||
return double2fx(floor(fx2double(i)));
|
||||
}
|
||||
|
||||
621
src/asm/output.c
621
src/asm/output.c
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,18 @@
|
||||
.Dd February 26, 2015
|
||||
.\" Copyright © 2010 Anthony J. Bentley <anthony@anjbe.name>
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.Dd April 17, 2017
|
||||
.Dt RGBASM 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
@@ -6,11 +20,12 @@
|
||||
.Nd Game Boy assembler
|
||||
.Sh SYNOPSIS
|
||||
.Nm rgbasm
|
||||
.Op Fl hv
|
||||
.Op Fl EhVvw
|
||||
.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 M Ar dependfile
|
||||
.Op Fl o Ar outfile
|
||||
.Op Fl p Ar pad_value
|
||||
.Ar file
|
||||
@@ -29,6 +44,8 @@ Add string symbol to the compiled source code. This is equivalent to
|
||||
.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.
|
||||
@@ -45,13 +62,22 @@ The
|
||||
option disables this behavior.
|
||||
.It Fl i Ar path
|
||||
Add an include path.
|
||||
.It Fl M Ar dependfile
|
||||
Print
|
||||
.Xr make 1
|
||||
dependencies to
|
||||
.Ar dependfile .
|
||||
.It Fl o Ar outfile
|
||||
Write an object file to the given filename.
|
||||
.It Fl p Ar pad_value
|
||||
When padding an image, pad with this value.
|
||||
The default is 0x00.
|
||||
.It Fl V
|
||||
Print the version of the program and exit.
|
||||
.It Fl v
|
||||
Be verbose.
|
||||
.It Fl w
|
||||
Disable warning output.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
Assembling a basic source file is simple:
|
||||
@@ -64,10 +90,15 @@ run through
|
||||
and
|
||||
.Xr rgbfix 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr rgbasm 5 ,
|
||||
.Xr rgbfix 1 ,
|
||||
.Xr rgblink 1 ,
|
||||
.Xr rgbds 7
|
||||
.Xr rgbds 5 ,
|
||||
.Xr rgbds 7 ,
|
||||
.Xr gbz80 7
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally written by Carsten S\(/orensen as part of the ASMotor package,
|
||||
and was later packaged in RGBDS by Justin Lloyd.
|
||||
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
|
||||
number of contributors at
|
||||
.Lk https://github.com/rednex/rgbds .
|
||||
|
||||
1121
src/asm/rgbasm.5
Normal file
1121
src/asm/rgbasm.5
Normal file
File diff suppressed because it is too large
Load Diff
303
src/asm/rpn.c
303
src/asm/rpn.c
@@ -2,19 +2,19 @@
|
||||
* Controls RPN expressions for objectfiles
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "asm/mylink.h"
|
||||
#include "types.h"
|
||||
#include "asm/symbol.h"
|
||||
#include "asm/asm.h"
|
||||
#include "asm/main.h"
|
||||
#include "asm/rpn.h"
|
||||
#include "asm/symbol.h"
|
||||
|
||||
void
|
||||
mergetwoexpressions(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
#include "linkdefs.h"
|
||||
|
||||
void mergetwoexpressions(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
*expr = *src1;
|
||||
memcpy(&(expr->tRPN[expr->nRPNLength]), src2->tRPN, src2->nRPNLength);
|
||||
@@ -23,13 +23,13 @@ mergetwoexpressions(struct Expression * expr, struct Expression * src1,
|
||||
expr->isReloc |= src2->isReloc;
|
||||
expr->isPCRel |= src2->isPCRel;
|
||||
}
|
||||
#define joinexpr() mergetwoexpressions(expr,src1,src2)
|
||||
|
||||
#define joinexpr() mergetwoexpressions(expr, src1, src2)
|
||||
|
||||
/*
|
||||
* Add a byte to the RPN expression
|
||||
*/
|
||||
void
|
||||
pushbyte(struct Expression * expr, int b)
|
||||
void pushbyte(struct Expression *expr, int b)
|
||||
{
|
||||
expr->tRPN[expr->nRPNLength++] = b & 0xFF;
|
||||
}
|
||||
@@ -37,47 +37,45 @@ pushbyte(struct Expression * expr, int b)
|
||||
/*
|
||||
* Reset the RPN module
|
||||
*/
|
||||
void
|
||||
rpn_Reset(struct Expression * expr)
|
||||
void rpn_Reset(struct Expression *expr)
|
||||
{
|
||||
expr->nRPNLength = expr->nRPNOut = expr->isReloc = expr->isPCRel = 0;
|
||||
expr->nRPNLength = 0;
|
||||
expr->nRPNOut = 0;
|
||||
expr->isReloc = 0;
|
||||
expr->isPCRel = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the next rpn byte in expression
|
||||
*/
|
||||
UWORD
|
||||
rpn_PopByte(struct Expression * expr)
|
||||
uint16_t rpn_PopByte(struct Expression *expr)
|
||||
{
|
||||
if (expr->nRPNOut == expr->nRPNLength) {
|
||||
return (0xDEAD);
|
||||
} else
|
||||
return (expr->tRPN[expr->nRPNOut++]);
|
||||
if (expr->nRPNOut == expr->nRPNLength)
|
||||
return 0xDEAD;
|
||||
|
||||
return expr->tRPN[expr->nRPNOut++];
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the current expression is relocatable
|
||||
*/
|
||||
ULONG
|
||||
rpn_isReloc(struct Expression * expr)
|
||||
uint32_t rpn_isReloc(const struct Expression *expr)
|
||||
{
|
||||
return (expr->isReloc);
|
||||
return expr->isReloc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if the current expression can be pc-relative
|
||||
*/
|
||||
ULONG
|
||||
rpn_isPCRelative(struct Expression * expr)
|
||||
uint32_t rpn_isPCRelative(const struct Expression *expr)
|
||||
{
|
||||
return (expr->isPCRel);
|
||||
return expr->isPCRel;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add symbols, constants and operators to expression
|
||||
*/
|
||||
void
|
||||
rpn_Number(struct Expression * expr, ULONG i)
|
||||
void rpn_Number(struct Expression *expr, uint32_t i)
|
||||
{
|
||||
rpn_Reset(expr);
|
||||
pushbyte(expr, RPN_CONST);
|
||||
@@ -88,11 +86,10 @@ rpn_Number(struct Expression * expr, ULONG i)
|
||||
expr->nVal = i;
|
||||
}
|
||||
|
||||
void
|
||||
rpn_Symbol(struct Expression * expr, char *tzSym)
|
||||
void rpn_Symbol(struct Expression *expr, char *tzSym)
|
||||
{
|
||||
if (!sym_isConstant(tzSym)) {
|
||||
struct sSymbol *psym;
|
||||
const struct sSymbol *psym;
|
||||
|
||||
rpn_Reset(expr);
|
||||
|
||||
@@ -106,241 +103,277 @@ rpn_Symbol(struct Expression * expr, char *tzSym)
|
||||
while (*tzSym)
|
||||
pushbyte(expr, *tzSym++);
|
||||
pushbyte(expr, 0);
|
||||
} else
|
||||
rpn_Number(expr, sym_GetConstantValue(tzSym));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
expr->isReloc = 1;
|
||||
pushbyte(expr, RPN_BANK);
|
||||
while (*tzSym)
|
||||
pushbyte(expr, *tzSym++);
|
||||
pushbyte(expr, 0);
|
||||
} else
|
||||
yyerror("BANK argument must be a relocatable identifier");
|
||||
}
|
||||
|
||||
int
|
||||
rpn_RangeCheck(struct Expression * expr, struct Expression * src, SLONG low,
|
||||
SLONG high)
|
||||
{
|
||||
*expr = *src;
|
||||
|
||||
if (rpn_isReloc(src)) {
|
||||
pushbyte(expr, RPN_RANGECHECK);
|
||||
pushbyte(expr, low);
|
||||
pushbyte(expr, low >> 8);
|
||||
pushbyte(expr, low >> 16);
|
||||
pushbyte(expr, low >> 24);
|
||||
pushbyte(expr, high);
|
||||
pushbyte(expr, high >> 8);
|
||||
pushbyte(expr, high >> 16);
|
||||
pushbyte(expr, high >> 24);
|
||||
return (1);
|
||||
} else {
|
||||
return (expr->nVal >= low && expr->nVal <= high);
|
||||
rpn_Number(expr, sym_GetConstantValue(tzSym));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
rpn_CheckHRAM(struct Expression * expr, struct Expression * src)
|
||||
void rpn_BankSelf(struct Expression *expr)
|
||||
{
|
||||
rpn_Reset(expr);
|
||||
|
||||
/*
|
||||
* This symbol is not really relocatable, but this makes the assembler
|
||||
* write this expression as a RPN patch to the object file.
|
||||
*/
|
||||
expr->isReloc = 1;
|
||||
|
||||
pushbyte(expr, RPN_BANK_SELF);
|
||||
}
|
||||
|
||||
void rpn_BankSymbol(struct Expression *expr, char *tzSym)
|
||||
{
|
||||
/* The @ symbol is treated differently. */
|
||||
if (sym_FindSymbol(tzSym) == pPCSymbol) {
|
||||
rpn_BankSelf(expr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sym_isConstant(tzSym)) {
|
||||
rpn_Reset(expr);
|
||||
|
||||
/*
|
||||
* Check that the symbol exists by evaluating and discarding the
|
||||
* value.
|
||||
*/
|
||||
sym_GetValue(tzSym);
|
||||
|
||||
expr->isReloc = 1;
|
||||
pushbyte(expr, RPN_BANK_SYM);
|
||||
while (*tzSym)
|
||||
pushbyte(expr, *tzSym++);
|
||||
pushbyte(expr, 0);
|
||||
} else {
|
||||
yyerror("BANK argument must be a relocatable identifier");
|
||||
}
|
||||
}
|
||||
|
||||
void rpn_BankSection(struct Expression *expr, char *tzSectionName)
|
||||
{
|
||||
rpn_Reset(expr);
|
||||
|
||||
/*
|
||||
* This symbol is not really relocatable, but this makes the assembler
|
||||
* write this expression as a RPN patch to the object file.
|
||||
*/
|
||||
expr->isReloc = 1;
|
||||
|
||||
pushbyte(expr, RPN_BANK_SECT);
|
||||
while (*tzSectionName)
|
||||
pushbyte(expr, *tzSectionName++);
|
||||
pushbyte(expr, 0);
|
||||
}
|
||||
|
||||
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
|
||||
{
|
||||
*expr = *src;
|
||||
pushbyte(expr, RPN_HRAM);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGNOT(struct Expression * expr, struct Expression * src)
|
||||
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
|
||||
{
|
||||
*expr = *src;
|
||||
pushbyte(expr, RPN_LOGUNNOT);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGOR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_LOGOR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal || src2->nVal);
|
||||
pushbyte(expr, RPN_LOGOR);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGAND(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_LOGAND(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal && src2->nVal);
|
||||
pushbyte(expr, RPN_LOGAND);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_HIGH(struct Expression *expr, const struct Expression *src)
|
||||
{
|
||||
*expr = *src;
|
||||
|
||||
expr->nVal = (expr->nVal >> 8) & 0xFF;
|
||||
|
||||
pushbyte(expr, RPN_CONST);
|
||||
pushbyte(expr, 8);
|
||||
pushbyte(expr, 0);
|
||||
pushbyte(expr, 0);
|
||||
pushbyte(expr, 0);
|
||||
|
||||
pushbyte(expr, RPN_SHR);
|
||||
|
||||
pushbyte(expr, RPN_CONST);
|
||||
pushbyte(expr, 0xFF);
|
||||
pushbyte(expr, 0);
|
||||
pushbyte(expr, 0);
|
||||
pushbyte(expr, 0);
|
||||
|
||||
pushbyte(expr, RPN_AND);
|
||||
}
|
||||
|
||||
void rpn_LOW(struct Expression *expr, const struct Expression *src)
|
||||
{
|
||||
*expr = *src;
|
||||
|
||||
expr->nVal = expr->nVal & 0xFF;
|
||||
|
||||
pushbyte(expr, RPN_CONST);
|
||||
pushbyte(expr, 0xFF);
|
||||
pushbyte(expr, 0);
|
||||
pushbyte(expr, 0);
|
||||
pushbyte(expr, 0);
|
||||
|
||||
pushbyte(expr, RPN_AND);
|
||||
}
|
||||
|
||||
void rpn_LOGEQU(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal == src2->nVal);
|
||||
pushbyte(expr, RPN_LOGEQ);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGGT(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_LOGGT(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal > src2->nVal);
|
||||
pushbyte(expr, RPN_LOGGT);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGLT(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_LOGLT(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal < src2->nVal);
|
||||
pushbyte(expr, RPN_LOGLT);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGGE(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_LOGGE(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal >= src2->nVal);
|
||||
pushbyte(expr, RPN_LOGGE);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGLE(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_LOGLE(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal <= src2->nVal);
|
||||
pushbyte(expr, RPN_LOGLE);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_LOGNE(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_LOGNE(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal != src2->nVal);
|
||||
pushbyte(expr, RPN_LOGNE);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_ADD(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_ADD(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal + src2->nVal);
|
||||
pushbyte(expr, RPN_ADD);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_SUB(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_SUB(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal - src2->nVal);
|
||||
pushbyte(expr, RPN_SUB);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_XOR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_XOR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal ^ src2->nVal);
|
||||
pushbyte(expr, RPN_XOR);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_OR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_OR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal | src2->nVal);
|
||||
pushbyte(expr, RPN_OR);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_AND(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_AND(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal & src2->nVal);
|
||||
pushbyte(expr, RPN_AND);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_SHL(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_SHL(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal << src2->nVal);
|
||||
pushbyte(expr, RPN_SHL);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_SHR(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_SHR(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal >> src2->nVal);
|
||||
pushbyte(expr, RPN_SHR);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_MUL(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_MUL(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
expr->nVal = (expr->nVal * src2->nVal);
|
||||
pushbyte(expr, RPN_MUL);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_DIV(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_DIV(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
if (src2->nVal == 0)
|
||||
fatalerror("division by zero");
|
||||
|
||||
expr->nVal = (expr->nVal / src2->nVal);
|
||||
pushbyte(expr, RPN_DIV);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_MOD(struct Expression * expr, struct Expression * src1,
|
||||
struct Expression * src2)
|
||||
void rpn_MOD(struct Expression *expr, const struct Expression *src1,
|
||||
const struct Expression *src2)
|
||||
{
|
||||
joinexpr();
|
||||
if (src2->nVal == 0)
|
||||
fatalerror("division by zero");
|
||||
|
||||
expr->nVal = (expr->nVal % src2->nVal);
|
||||
pushbyte(expr, RPN_MOD);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_UNNEG(struct Expression * expr, struct Expression * src)
|
||||
void rpn_UNNEG(struct Expression *expr, const struct Expression *src)
|
||||
{
|
||||
*expr = *src;
|
||||
expr->nVal = -expr->nVal;
|
||||
pushbyte(expr, RPN_UNSUB);
|
||||
}
|
||||
|
||||
void
|
||||
rpn_UNNOT(struct Expression * expr, struct Expression * src)
|
||||
void rpn_UNNOT(struct Expression *expr, const struct Expression *src)
|
||||
{
|
||||
*expr = *src;
|
||||
expr->nVal = expr->nVal ^ 0xFFFFFFFF;
|
||||
expr->nVal = ~expr->nVal;
|
||||
pushbyte(expr, RPN_UNNOT);
|
||||
}
|
||||
|
||||
761
src/asm/symbol.c
761
src/asm/symbol.c
File diff suppressed because it is too large
Load Diff
35
src/extern/err.c
vendored
35
src/extern/err.c
vendored
@@ -21,45 +21,59 @@
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "extern/err.h"
|
||||
|
||||
extern char *progname;
|
||||
#include "extern/err.h"
|
||||
|
||||
void rgbds_vwarn(const char *fmt, va_list ap)
|
||||
{
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
fprintf(stderr, "warning");
|
||||
if (fmt) {
|
||||
fputs(": ", stderr);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fputs (": ", stderr);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
perror(0);
|
||||
}
|
||||
|
||||
void rgbds_vwarnx(const char *fmt, va_list ap)
|
||||
{
|
||||
fprintf (stderr, "%s: ", progname);
|
||||
if (fmt) vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, "warning");
|
||||
if (fmt) {
|
||||
fputs(": ", stderr);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
|
||||
noreturn void rgbds_verr(int status, const char *fmt, va_list ap)
|
||||
{
|
||||
vwarn(fmt, ap);
|
||||
fprintf(stderr, "error");
|
||||
if (fmt) {
|
||||
fputs(": ", stderr);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
noreturn void rgbds_verrx(int status, const char *fmt, va_list ap)
|
||||
{
|
||||
vwarnx(fmt, ap);
|
||||
fprintf(stderr, "error");
|
||||
if (fmt) {
|
||||
fputs(": ", stderr);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void rgbds_warn(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vwarn(fmt, ap);
|
||||
va_end(ap);
|
||||
@@ -68,6 +82,7 @@ void rgbds_warn(const char *fmt, ...)
|
||||
void rgbds_warnx(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vwarnx(fmt, ap);
|
||||
va_end(ap);
|
||||
@@ -76,6 +91,7 @@ void rgbds_warnx(const char *fmt, ...)
|
||||
noreturn void rgbds_err(int status, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
verr(status, fmt, ap);
|
||||
va_end(ap);
|
||||
@@ -84,6 +100,7 @@ noreturn void rgbds_err(int status, const char *fmt, ...)
|
||||
noreturn void rgbds_errx(int status, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
verrx(status, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
13
src/extern/reallocarray.c
vendored
13
src/extern/reallocarray.c
vendored
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
|
||||
/* $OpenBSD: reallocarray.c,v 1.2 2014/12/08 03:45:00 bcook Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
|
||||
*
|
||||
@@ -15,22 +15,21 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.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))
|
||||
#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
|
||||
|
||||
void *
|
||||
rgbds_reallocarray(void *optr, size_t nmemb, size_t size)
|
||||
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) {
|
||||
if (((nmemb >= MUL_NO_OVERFLOW) || (size >= MUL_NO_OVERFLOW)) &&
|
||||
(nmemb > 0) && (SIZE_MAX / nmemb < size)) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
9
src/extern/strlcat.c
vendored
9
src/extern/strlcat.c
vendored
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: strlcat.c,v 1.14 2015/01/15 03:54:12 millert Exp $ */
|
||||
/* $OpenBSD: strlcat.c,v 1.14 2015/01/15 03:54:12 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
@@ -16,8 +16,8 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* Appends src to string dst of size dsize (unlike strncat, dsize is the
|
||||
@@ -26,8 +26,7 @@
|
||||
* Returns strlen(src) + MIN(dsize, strlen(initial dst)).
|
||||
* If retval >= dsize, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
rgbds_strlcat(char *dst, const char *src, size_t dsize)
|
||||
size_t rgbds_strlcat(char *dst, const char *src, size_t dsize)
|
||||
{
|
||||
const char *odst = dst;
|
||||
const char *osrc = src;
|
||||
@@ -51,5 +50,5 @@ rgbds_strlcat(char *dst, const char *src, size_t dsize)
|
||||
}
|
||||
*dst = '\0';
|
||||
|
||||
return(dlen + (src - osrc)); /* count does not include NUL */
|
||||
return dlen + (src - osrc); /* count does not include NUL */
|
||||
}
|
||||
|
||||
16
src/extern/strlcpy.c
vendored
16
src/extern/strlcpy.c
vendored
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
|
||||
/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
@@ -16,16 +16,15 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/*
|
||||
* Copy string src to buffer dst of size dsize. At most dsize-1
|
||||
* chars will be copied. Always NUL terminates (unless dsize == 0).
|
||||
* Returns strlen(src); if retval >= dsize, truncation occurred.
|
||||
*/
|
||||
size_t
|
||||
rgbds_strlcpy(char *dst, const char *src, size_t dsize)
|
||||
size_t rgbds_strlcpy(char *dst, const char *src, size_t dsize)
|
||||
{
|
||||
const char *osrc = src;
|
||||
size_t nleft = dsize;
|
||||
@@ -33,7 +32,10 @@ rgbds_strlcpy(char *dst, const char *src, size_t dsize)
|
||||
/* Copy as many bytes as will fit. */
|
||||
if (nleft != 0) {
|
||||
while (--nleft != 0) {
|
||||
if ((*dst++ = *src++) == '\0')
|
||||
char n = *src++;
|
||||
*dst++ = n;
|
||||
|
||||
if (n == '\0')
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -41,10 +43,10 @@ rgbds_strlcpy(char *dst, const char *src, size_t dsize)
|
||||
/* Not enough room in dst, add NUL and traverse rest of src. */
|
||||
if (nleft == 0) {
|
||||
if (dsize != 0)
|
||||
*dst = '\0'; /* NUL-terminate dst */
|
||||
*dst = '\0'; /* NUL-terminate dst */
|
||||
while (*src++)
|
||||
;
|
||||
}
|
||||
|
||||
return(src - osrc - 1); /* count does not include NUL */
|
||||
return (src - osrc - 1); /* count does not include NUL */
|
||||
}
|
||||
|
||||
34
src/extern/version.c
vendored
Normal file
34
src/extern/version.c
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.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 <string.h>
|
||||
|
||||
#include "extern/version.h"
|
||||
|
||||
const char *get_package_version_string(void)
|
||||
{
|
||||
static char s[50];
|
||||
|
||||
/* The following conditional should be simplified by the compiler. */
|
||||
if (strlen(BUILD_VERSION_STRING) == 0) {
|
||||
snprintf(s, sizeof(s), "v%d.%d.%d", PACKAGE_VERSION_MAJOR,
|
||||
PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCH);
|
||||
return s;
|
||||
} else {
|
||||
return BUILD_VERSION_STRING;
|
||||
}
|
||||
}
|
||||
134
src/fix/main.c
134
src/fix/main.c
@@ -22,21 +22,18 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "extern/version.h"
|
||||
|
||||
char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"usage: rgbfix [-Ccjsv] [-i game_id] [-k licensee_str] [-l licensee_id]\n"
|
||||
"usage: rgbfix [-CcjsVv] [-i game_id] [-k licensee_str] [-l licensee_id]\n"
|
||||
" [-m mbc_type] [-n rom_version] [-p pad_value] [-r ram_size]\n"
|
||||
" [-t title_str] file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *rom;
|
||||
int ch;
|
||||
@@ -65,15 +62,13 @@ main(int argc, char *argv[])
|
||||
char *id; /* game ID in ASCII */
|
||||
char *newlicensee; /* new licensee ID, two ASCII characters */
|
||||
|
||||
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 */
|
||||
int licensee = 0; /* old licensee ID */
|
||||
int cartridge = 0; /* cartridge hardware ID */
|
||||
int ramsize = 0; /* RAM size ID */
|
||||
int version = 0; /* mask ROM version number */
|
||||
int padvalue = 0; /* 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) {
|
||||
while ((ch = getopt(argc, argv, "Cci:jk:l:m:n:p:sr:t:Vv")) != -1) {
|
||||
switch (ch) {
|
||||
case 'C':
|
||||
coloronly = true;
|
||||
@@ -84,10 +79,9 @@ main(int argc, char *argv[])
|
||||
case 'i':
|
||||
setid = true;
|
||||
|
||||
if (strlen(optarg) != 4) {
|
||||
errx(1, "Game ID %s must be exactly 4 "
|
||||
"characters", optarg);
|
||||
}
|
||||
if (strlen(optarg) != 4)
|
||||
errx(1, "Game ID %s must be exactly 4 characters",
|
||||
optarg);
|
||||
|
||||
id = optarg;
|
||||
break;
|
||||
@@ -97,10 +91,9 @@ main(int argc, char *argv[])
|
||||
case 'k':
|
||||
setnewlicensee = true;
|
||||
|
||||
if (strlen(optarg) != 2) {
|
||||
errx(1, "New licensee code %s is not the "
|
||||
"correct length of 2 characters", optarg);
|
||||
}
|
||||
if (strlen(optarg) != 2)
|
||||
errx(1, "New licensee code %s is not the correct length of 2 characters",
|
||||
optarg);
|
||||
|
||||
newlicensee = optarg;
|
||||
break;
|
||||
@@ -108,61 +101,59 @@ main(int argc, char *argv[])
|
||||
setlicensee = true;
|
||||
|
||||
licensee = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
if (optarg[0] == '\0' || *ep != '\0')
|
||||
errx(1, "Invalid argument for option 'l'");
|
||||
}
|
||||
if (licensee < 0 || licensee > 0xFF) {
|
||||
errx(1, "Argument for option 'l' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
|
||||
if (licensee < 0 || licensee > 0xFF)
|
||||
errx(1, "Argument for option 'l' must be between 0 and 255");
|
||||
|
||||
break;
|
||||
case 'm':
|
||||
setcartridge = true;
|
||||
|
||||
cartridge = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
if (optarg[0] == '\0' || *ep != '\0')
|
||||
errx(1, "Invalid argument for option 'm'");
|
||||
}
|
||||
if (cartridge < 0 || cartridge > 0xFF) {
|
||||
errx(1, "Argument for option 'm' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
|
||||
if (cartridge < 0 || cartridge > 0xFF)
|
||||
errx(1, "Argument for option 'm' must be between 0 and 255");
|
||||
|
||||
break;
|
||||
case 'n':
|
||||
setversion = true;
|
||||
|
||||
version = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
|
||||
if (optarg[0] == '\0' || *ep != '\0')
|
||||
errx(1, "Invalid argument for option 'n'");
|
||||
}
|
||||
if (version < 0 || version > 0xFF) {
|
||||
errx(1, "Argument for option 'n' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
|
||||
if (version < 0 || version > 0xFF)
|
||||
errx(1, "Argument for option 'n' must be between 0 and 255");
|
||||
|
||||
break;
|
||||
case 'p':
|
||||
resize = true;
|
||||
|
||||
padvalue = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
|
||||
if (optarg[0] == '\0' || *ep != '\0')
|
||||
errx(1, "Invalid argument for option 'p'");
|
||||
}
|
||||
if (padvalue < 0 || padvalue > 0xFF) {
|
||||
errx(1, "Argument for option 'p' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
|
||||
if (padvalue < 0 || padvalue > 0xFF)
|
||||
errx(1, "Argument for option 'p' must be between 0 and 255");
|
||||
|
||||
break;
|
||||
case 'r':
|
||||
setramsize = true;
|
||||
|
||||
ramsize = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
|
||||
if (optarg[0] == '\0' || *ep != '\0')
|
||||
errx(1, "Invalid argument for option 'r'");
|
||||
}
|
||||
if (ramsize < 0 || ramsize > 0xFF) {
|
||||
errx(1, "Argument for option 'r' must be "
|
||||
"between 0 and 255");
|
||||
}
|
||||
|
||||
if (ramsize < 0 || ramsize > 0xFF)
|
||||
errx(1, "Argument for option 'r' must be between 0 and 255");
|
||||
|
||||
break;
|
||||
case 's':
|
||||
super = true;
|
||||
@@ -170,22 +161,24 @@ main(int argc, char *argv[])
|
||||
case 't':
|
||||
settitle = true;
|
||||
|
||||
if (strlen(optarg) > 16) {
|
||||
errx(1, "Title %s is greater than the "
|
||||
"maximum of 16 characters", optarg);
|
||||
}
|
||||
if (strlen(optarg) > 16)
|
||||
errx(1, "Title \"%s\" is greater than the maximum of 16 characters",
|
||||
optarg);
|
||||
|
||||
if (strlen(optarg) == 16)
|
||||
warnx("Title %s is 16 chars, it is best to "
|
||||
"keep it to 15 or fewer", optarg);
|
||||
warnx("Title \"%s\" is 16 chars, it is best to keep it to 15 or fewer",
|
||||
optarg);
|
||||
|
||||
title = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
printf("rgbfix %s\n", get_package_version_string());
|
||||
exit(0);
|
||||
case 'v':
|
||||
validate = true;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
print_usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
@@ -194,15 +187,16 @@ main(int argc, char *argv[])
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
print_usage();
|
||||
|
||||
/*
|
||||
* Open the ROM file
|
||||
*/
|
||||
|
||||
if ((rom = fopen(argv[argc - 1], "rb+")) == NULL) {
|
||||
rom = fopen(argv[argc - 1], "rb+");
|
||||
|
||||
if (rom == NULL)
|
||||
err(1, "Error opening file %s", argv[argc - 1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write changes to ROM
|
||||
@@ -266,7 +260,7 @@ main(int argc, char *argv[])
|
||||
* characters).
|
||||
*/
|
||||
|
||||
fseek(rom,0x13F,SEEK_SET);
|
||||
fseek(rom, 0x13F, SEEK_SET);
|
||||
fwrite(id, 1, 4, rom);
|
||||
}
|
||||
|
||||
@@ -332,8 +326,7 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
|
||||
if (!setlicensee)
|
||||
warnx("You should probably set both '-s' and "
|
||||
"'-l 0x33'");
|
||||
warnx("You should probably set both '-s' and '-l 0x33'");
|
||||
|
||||
fseek(rom, 0x146, SEEK_SET);
|
||||
fputc(3, rom);
|
||||
@@ -360,6 +353,7 @@ main(int argc, char *argv[])
|
||||
long romsize, newsize;
|
||||
int headbyte;
|
||||
uint8_t *buf;
|
||||
|
||||
fseek(rom, 0, SEEK_END);
|
||||
romsize = ftell(rom);
|
||||
newsize = 0x8000;
|
||||
@@ -433,9 +427,8 @@ main(int argc, char *argv[])
|
||||
* Offset 0x14D: Header Checksum
|
||||
*/
|
||||
|
||||
uint8_t headcksum;
|
||||
uint8_t headcksum = 0;
|
||||
|
||||
headcksum = 0;
|
||||
fseek(rom, 0x134, SEEK_SET);
|
||||
for (int i = 0; i < (0x14D - 0x134); ++i)
|
||||
headcksum = headcksum - fgetc(rom) - 1;
|
||||
@@ -447,15 +440,14 @@ main(int argc, char *argv[])
|
||||
* Offset 0x14E–0x14F: Global Checksum
|
||||
*/
|
||||
|
||||
uint16_t globalcksum;
|
||||
|
||||
globalcksum = 0;
|
||||
uint16_t globalcksum = 0;
|
||||
|
||||
rewind(rom);
|
||||
for (int i = 0; i < 0x14E; ++i)
|
||||
globalcksum += fgetc(rom);
|
||||
|
||||
int byte;
|
||||
|
||||
fseek(rom, 0x150, SEEK_SET);
|
||||
while ((byte = fgetc(rom)) != EOF)
|
||||
globalcksum += byte;
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
.Dd February 26, 2015
|
||||
.\" Copyright © 2010 Anthony J. Bentley <anthony@anjbe.name>
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.Dd April 17, 2017
|
||||
.Dt RGBFIX 1
|
||||
.Os RGBDS Manual
|
||||
.Sh NAME
|
||||
@@ -6,7 +20,7 @@
|
||||
.Nd Game Boy checksum fixer
|
||||
.Sh SYNOPSIS
|
||||
.Nm rgbfix
|
||||
.Op Fl Ccjsv
|
||||
.Op Fl CcjsVv
|
||||
.Op Fl i Ar game_id
|
||||
.Op Fl k Ar licensee_str
|
||||
.Op Fl l Ar licensee_id
|
||||
@@ -88,9 +102,14 @@ Set the title string
|
||||
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
|
||||
.Pq Fl c No or Fl C .
|
||||
.Po Fl c
|
||||
or
|
||||
.Fl C
|
||||
.Pc .
|
||||
If both this and the game ID are set, the game ID will overwrite the
|
||||
overlapping portion of the title.
|
||||
.It Fl V
|
||||
Print the version of the program and exit.
|
||||
.It Fl v
|
||||
Validate the header and fix checksums: the Nintendo character area
|
||||
.Pq Ad 0x104 Ns \(en Ns Ad 0x133 ,
|
||||
@@ -135,5 +154,6 @@ SurvivalKids.gbc
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
was originally released by Carsten S\(/orensen as a standalone program called
|
||||
gbfix.
|
||||
It was later integrated with the ASMotor package, which became RGBDS.
|
||||
gbfix, and was later packaged in RGBDS by Justin Lloyd. It is now maintained by
|
||||
a number of contributors at
|
||||
.Lk https://github.com/rednex/rgbds .
|
||||
|
||||
1824
src/gbz80.7
Normal file
1824
src/gbz80.7
Normal file
File diff suppressed because it is too large
Load Diff
202
src/gfx/gb.c
Normal file
202
src/gfx/gb.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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(const 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(const struct Options opts, const 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(const 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(const struct Options opts,
|
||||
const 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(const struct Options opts, const 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);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user