Should not be followed for C files, to avoid mucking `blame`s,
but will be applied during the gradual C++ rollout, since that
will likely touch most lines in the codebase anyway.
Enhances some warnings as well as the sanitizers (Clang especially complained about it)
The `-f*` flags are to get better stack traces out of the sanitizers, as recommended
by Clang's docs: https://clang.llvm.org/docs/AddressSanitizer.html#usage
GCC's docs claim that these optimizations should not hinder the debugging
experience, and Clang's don't mention optimization flags at all.
Remove already-enabled warnings as pointed out by #969
Comments added to the CMakeLists because the Makefile format does not really allow them
"Plain" list also sorted alphabetically, the rest (somewhat) thematically
Attempting to build with this gave an "undefined reference to `yydebug'"
error (maybe a version issue with bison?), and I don't think it's been
used for recent parser debugging either.
Remove unreachable argument presence check (handled by `getopt`)
Merge allocation paths into a single `realloc` call
Avoid searching for string lengths multiple times
Tiny (compatible) change: no space between last dependent and colon if
`-MT` or `-MQ` is specified
* Add Bash completion script for RGBASM
Should have large feature parity with the Zsh completion
Co-authored-by: DaKnig <[email protected]>
* Register RGBASM Bash completion in `checkdiff`
Co-authored-by: ISSOtm <[email protected]>
* Add scramble flags to RGBLINK
-S and -W will scramble ROMX and WRAMX respectively.
* Modify scramble CLI
CLI now takes a list of comma-separated values.
Added arg_error to clean up messages.
Co-authored-by: Eldred Habert <[email protected]>
* Document scrambling functionality
Co-authored-by: Eldred Habert <[email protected]>
* Implement -Wtruncation=level
-Wtruncation=0 is the same as the current -Wno-truncation.
-Wtruncation=2 is the same as the current -Wtruncation.
-Wtruncation=1 is the new default; it's less strict, allowing
N-bit values to be between -2**N and 2**N (exclusive).
* Implement generic "parametrized warning" system
* Test more `Wtruncation` variants
Co-authored-by: ISSOtm <[email protected]>
* Reword label definition docs
A bunch of short sentences isn't very readable, this should be better
* Use correct wording for "computing difference"
Co-authored-by: Rangi <[email protected]>
* Explain how to define a label before mentioning local ones
* Move double-colon paragraph to make the explanation flow better
* Clarify what a label's value is
Co-authored-by: Rangi <[email protected]>
I think we've earned it, at least for being maintainers for a couple years.
I believe the work done by those before us is more important (relicensing & cleanup),
but we've both made significant changes on top of what they made possible.
`TIMER & BATTERY` is 0, but even `|` would only be checking if
*either* is set; instead, imply BATTERY as soon as TIMER is given,
printing a warning if it was not given.
`startCapture` did not initialize `lexerState->atLineStart`;
its final value is a consequence of the separate but similar
behaviors within `lexer_CaptureRept` and `lexer_CaptureMacroBody`.
- Don't warn if the non-zero byte being written is the same as the original byte
- Add a `-O` / `--overwrite` flag to silence all such warnings
Fixes#897
`DEF`, `REDEF`, etc disable EQUS expansion, and reading
macro or OPT arguments sets the lexer to raw mode.
Syntax errors resume normal parsing at the line's end,
but should resume normal tokenization even before that.
This message is only printed for identifiers parsed as
`T_LABEL` (since they're at the start of a line) but
already defined as macros. Otherwise it may not be
relevant, e.g. for `MyLabel;:` or `My Label::`.
The `git config --global --unset core.autocrlf` command
was failing in the "Create release artifacts" workflow,
so this is an alternate method of fixing issue #841.
Fixes#881 by moving the task from the lexer to the parser.
This both alleviates the need for backtracking in the lexer,
removing what is (was) arguably a hack, and causes tokenization
boundaries to be properly respected, fixing the issue mentioned above.
Co-authored-by: Rangi <[email protected]>
* Reinstate PUSHS clearing the SECTION scope
Otherwise you can use `PUSHS` to simulate the old `ds -21`, and possibly cause bugs
* Have PUSHS push LOAD block state as well
It does not make sense not to, and coud cause bugs.
Redefining an EQUS constant will now update its filename,
like redefining a SET/= constant.
Attempting to redefine as EQUS a non-EQUS constant will
print an appropriate error message.
This also standardizes on `sym` versus `symbol` as a
variable name (which pairs with `symName`).
- `out_PushSection` should not set `currentSection` to NULL because
PUSHS, PUSHC, and PUSHO consistently keep the current section,
charmap, and options, even though the stack has been pushed.
- `Callback__FILE__` does not need to assert that `fileName` is not
empty because `__FILE__`'s value is quoted, and can safely be empty.
- `YY_FATAL_ERROR` and `YYLMAX` are not needed since the lexer is
not generated with flex.
Expanding empty strings is valid but pointless;
macro args already skipped doing so, now other
`beginExpansion` calls do too.
This also fixes failed interpolations (which were
already non-fatal) to continue reading characters,
not evaluate to their initial '{' character.
This combines 0.5.0 and post-0.5.0 features:
print and println, strfmt, for loops,
def assignments, redef equs, {interpolation},
new macro syntax, and \<bracketed macro args>
Bison 3.1 introduces "typed midrule values", which would write
`<captureTerminated>{ ... }` and `$$` instead of `{ ... }` and
`$<captureTerminated>[1-9]`, but rgbds supports 3.0 or even lower.
Widths and fractional widths greater than 255 would overflow a
uint8_t and wrap around to smaller values.
Total formatted lengths greater than the avilable buffer size
would overflow it and potentially corrupt memory.
Fixes#830Closes#831
Widths and fractional widths greater than 255 would overflow a
uint8_t and wrap around to smaller values.
Total formatted lengths greater than the avilable buffer size
would overflow it and potentially corrupt memory.
Fixes#830Closes#831
Previously a '.' could be past the truncation limit but still
cause the identifier to be marked as local, violating an
assertion in `sym_AddLocalLabel`.
Fixes#832
This shortens the lexer by 100 lines and simplifies
access to expansion contents, since it usually needs the
deepest one, not the top-level one.
Fixes#813
lexerState->expansionOfs is always either set to 0, or updated by
adding a positive quantity:
if (distance > lexerState->expansions->distance) {
lexerState->expansionOfs += distance - lexerState->expansions->distance;
...
}
so it will always be positive or zero.
Only two sites were for distances greater than 1:
a `shiftChars(2)`, trivial to just do two `shiftChar()`s;
and `shiftChars(size)` in `reportGarbageChar`, which
can be a `for` loop, and should be fixed anyway to
"avoid having to peek further than 0".
Instead of defining `LOOKUP_PRE_NEST` and `LOOKUP_POST_NEST`,
pass a variable name and a block to `lookupExpansion`; it
will assign successive looked-up expansions to the variable
and use them in the block.
The technique of using `__VA_ARGS__` to allow commas within a
block passed to a macro is not original, and should be stable.
This macro was only used twice, in `beginExpansion` and
`lexer_DumpStringExpansions`, with `getExpansionAtDistance`
already containing an inlined and slightly modified version
of `lookupExpansion` (retaining the `LOOKUP_PRE_NEST` and
`LOOKUP_POST_NEST` macros, but with both of them doing nothing).
Not using an X macro here makes the actual control flow in both
places more obvious, and I think the repeated code is acceptable
for the same reasons as the similar-but-distinct implementations
of `readString`, `appendStringLiteral`, `yylex_NORMAL`, and
`yylex_RAW`.
This decoding required high lookahead, and was not even
consistently useful (the `garbage_char` test case was not
valid UTF-8 and so did not benefit from `reportGarbageChar`).
This limits UTF-8 handling to the `STRLEN` and `STRSUB`
built-in functions, and to charmap conversion.
Fixes the test case from #800
The `out.gb` output was corrected, since the two "test"
fragments have a different order in ROM than in SRAM.
It is effectively:
; ROM0[$0000], fragments ordered by size
jr Label
dw Label
db 0
; SRAM[$a000], fragments ordered by .o order
ds 1 ; db 0
ds 2 ; jr Label
Label: ; $a003
ds 2 ; dw Label
Macro args were already handled by `peek`, and character escapes
do not exist outside of string literals.
This only affects the error message printed when a non-whitespace
character comes after the backslash. Instead of "Illegal character
escape '%s'", it will print "Begun line continuation, but
encountered character '%s'".
It still gets written to the object file, generating Valgrind warnings
about using uninitialized memory. To silence those errors, and make
output more reproducible, init the line no to a dummy (0) value.
Explicit {interpolation} can still achieve this, but
to match DEF, REDEF, and PURGE, these new directives that
define symbols do not expand string EQUS.
Currently INCBIN gives an error if your start position == file size.
This means you cannot include an empty file.
It also means the text of the error message is incorrect
(as the start is not greater, but equal to the length of the file)
We'll use "-rcX" instead of "-pre" to allow multiple ones, jic
Additionally, they will be able to be detected using __RGBDS_RC__
Finally, adapt everything version-related to this new system
GitHub's ubuntu-18.04 environment installs gcc 7.3.0.
The latest ubuntu-20.04 environment installs gcc 9.3.0.
Version 9.3.0 is incompatible with building libpng 1.6.37,
as of 2021-03-04.
Fixes#783
* Store all the local symbols in object files, not only the ones that need linker patches.
This generates better map/sym files, and thus allows for better debugging as well.
* Add comments explaining the ->src and the (void)arg;
This was removed in b3c0db218d
(along with two unrelated changes).
Removing this hack introduced issue #742, whereby INCLUDing
a file without a trailing newline can cause a syntax error.
A more proper fix would involve Bison's tracking locations,
but for now the EOF-newline hack fixes the issue while only
affecting some reported errors (expecting "newline"
instead of "end of file").
Fixes#742
* Mark `error` as a `format` function, to properly scan its format
* Fix the call to error() from parser.y:
- Use '%s' to avoid passing an arbitrary format
- Simplify yyerror overall
* Fix size parameter of %.*s format being an int... bonkers standard.
* Report the number of arguments required and provided on a STRFMT mismatch
* Add an assert to check for a very unlikely bug
This applies to macro arguments, DB, DW, DL, DS,
PRINT, PRINTLN, EXPORT, PURGE, and OPT.
It also removes support for empty entries in DB/DW/DL.
(Deprecating it would require keeping parser support,
which is ambiguous with trailing commas.)
Fixes#753
* Fix compatibility of rgblink -O and -t
The -t "tiny mode" option makes ROM0 cover 0x8000 bytes,
not 0x4000. The -O "overlay" option fills areas uncovered
by sections with data from an overlay file. These needed
to cooperate so that the calculated uncovered overlay size
does not exceed the actual size of the ROM.
Fixes#754
* Print link test names like asm tests do
* Make the three test.sh scripts more similar
In exponent(), 'base *= base;' should not run
when base is 65536, since it overflows an int32_t.
This also optimizes exponent() based on
gcc and clang -O3 test cases in godbolt.org.
Fixes#683 and #691
The lexer's raw mode for reading macro args already attempted
to handle semicolons inside string literals, versus outside ones
which start comments. This change reuses the same function for
reading string literals in normal and raw modes, also handling:
- Commas in strings versus between macro args
- Character escapes
- {Interpolations} and \1-\9 args inside vs. outside strings
- Multi-line string literals
Macro args now allow escaping '\', '"', and '\\'.
A consistent model for expanding macro args and interpolations,
within macro args, string literals, and normal context:
- "{S}" should always equal the contents of S
- "\1" should always act like quoting the value of \1
In preparation for an upcoming change
Makes for nicer error messages, complaining about EOF instead of newlines
The hack had to be kept for the lexer raw mode to avoid a bug;
see the relevant code comment for more info.
Simplify the mess that was option setting (2 redundant variables !?)
Move options to a separate file
Have "modules" own their options, and OPT only access them (less redundancy)
Simplify code, respect naming conventions better
- Make it work inside pipelines
- Add RGBFIX tests to the suite
- Be more flexible in accepted MBC names
- Add warnings for dangerous or nonsensical input params
- Improve man page
This is not used in all bison versions, which causes a
"defined but not used" warning for the 'rgbasm_yytnamerr'
replacement, treated as an error by 'make develop'.
Removal of colon-less labels lifted the grammar ambiguity that
prevented `RL` from being usable as a variable declarator.
Thus, reinstate its functionality.
Fixes#669Closes#368Closes#624
Deprecate PRINTT, PRINTV, PRINTI, and PRINTF
Default STRFMT("%f") to 5 fractional digits like "{f:}"
Any use of string formatting will share this default
Document the existing `ROUND`, `CEIL`, and `FLOOR` functions
Also update the trig function docs for searchability
Implement `POW` and `LOG`
Addresses part of #675
Implement ** for integer exponents
** has higher precedence than -, like Python, so -3**4 == -(3**4) == 81
- POSIX sh actually does NOT support `+=`,
but Bash does even in compatibility mode
- `mawk` does not fully support POSIX EREs (regexes),
so work around its lack of brace support
Fixes building on Debian, apparently.
Use better constructs where possible
- <<< instead of echo|
- Parameter expansions instead of `cut`
- Etc.
Improves performance and reliability somewhat
Also, accept "d" between diff line info parts
They are auto-generated, so they wouldn't normally contain Liquid
(The post-processor may insert some, but it has control over the `raw` tags)
Some code introduced as examples contains `{{` due to nested brace expansions,
which was interpreted as (invalid) Liquid. This fixes such problems.
Additionally, Jekyll generates warnings about excerpts being part of a Liquid
block (the `{% raw %}`). This is fine, since doc pages don't use excerpts.
After discussion (starting there:
https://github.com/gbdev/rgbds/pull/594#issuecomment-706437458
), it was decided that plain nested macros should not be
allowed.
Since #590 is fixed, EQUS can be used as a workaround;
multiline strings (#589) will make that easier on the
user when implemented.
Fixes#588, supersedes and closes#594.
Additionally, closes#388.
The old "find symbol with auto scope" function is now three:
- One finds the exact name passed to it, skipping any checks
This is useful e.g. if such checks were already performed.
- One checks that the name is not scoped, and calls the first.
This is useful for names that cannot be scoped, such as checking for EQUS.
Doing this instead of the third should improve performance somehwat, since
this specific case is hit by the lexer each time an identifier is read.
- The last one checks if the name should be expanded (`.loc` → `Glob.loc`),
and that the local part is not scoped. This is essentially the old function.
Use C11 standard _Noreturn instead of attributes (except, of course, MSVC)
Remove unused helpers
Avoid trapping in release builds, in favor of just unreachability
Improve shim when __builtin_* are not available
When a user tried to overwrite a builtin symbol, it would change its
type despite the error, making the second try succeed. This is
problematic, as the location of a builtin symbol cannot be updated.
Build type no longer defaults to Release (!)
have separate options for extra warning flags and sanitizers
toss DEVELOP macro
Fix sanitizers with CMake while I'm at it :|
Since the lexer buffer wraps, the refilling gets handled in two steps:
First, iff the buffer would wrap, the buffer is refilled until its end.
Then, if more characters are requested, that amount is refilled too.
An important detail is that `read()` may not return as many characters as
requested; for this reason, the first step checks if its `read()` was
"full", and skips the second step otherwise.
This is also where a bug lied.
After a *lot* of trying, I eventually managed to reproduce the bug on an
OpenBSD VM, and after adding a couple of `assert`s in `peekInternal`, this
is what happened, starting at line 724:
0. `lexerState->nbChars` is 0, `lexerState->index` is 19;
1. We end up with `target` = 42, and `writeIndex` = 19;
2. 42 + 19 is greater than `LEXER_BUF_SIZE` (= 42), so the `if` is entered;
3. Within the first `readChars`, **`read` only returns 16 bytes**,
advancing `writeIndex` to 35 and `target` to 26;
4. Within the second `readChars`, a `read(26)` is issued, overflowing the
buffer.
The bug should be clear now: **the check at line 750 failed to work!** Why?
Because `readChars` modifies `writeIndex`.
The fix is simply to cache the number of characters expected, and use that.
They were expanded during the capture, and there was no easy way to
avoid expanding them (believe me, after three hours and somehow an OOM, I
gave up trying).
The biggest problem was simply that the length of children expansions was
not accounted for when skipping over the parent... this took a lot of
arduous debugging, but it finally works!
And fix line counting with expansion-made newlines.
This has the same bug as the old lexer (equs-newline's output does not
print the second warning as being part of the expansion).
Additionally, we regress equs-recursion, as we are no longer able to
catch this specific EQUS recursion. Simply enough, the new expansion
begins **after** the old one ends! I have found no way to handle that.
Add keywords and identifiers
Add comments
Add number literals
Add strings
Add a lot of new tokens
Add (and clean up) IF etc.
Improve reporting of unexpected chars / garbage bytes
Fix bug with and improved error messages when failing to open file
Add verbose-level messages about how files are opened
Enforce that files finish with a newline
Fix chars returned not being cast to unsigned char (may conflict w/ EOF)
Return null path when no file is open, rather than crash
Unify and improve error printing slightly
Known to be missing: macro expansion, REPT blocks, EQUS expansions
Description blurb is already inline from new stylesheet
`Xr` links are already handled by `mandoc` now
Handle spaces between both dashes in long options
Remove `<head>` modifications, as fragments are generated instead
Make links to other man pages work
Add a table of contents to rgbasm(5)
Make the OS at the bottom of all pages 'Linux'
Apply post-processor that used to be used
This requires some special-casing for `jr @` because the `jr` opcode has
already been emitted, but not the operand, so PC points to the middle.
Moved the RGBLINK test to RGBASM's folder, and created a new RGBLINK test.
The code expected to never get "known" expressions passed in, as RGBASM
otherwise patches the bytes in by itself; however, JR cannot be patched in
by RGBASM unless the section's base address is known as well!
This allows whitespace between the brackets and the register.
This also fixes#531
Note that `$ff00 + c` is still treated as a single token, because trying to
use an expression on the left side causes a shift/reduce conflict.
This isn't great, but most people seem to be either used to it as-is, or
using the new `ldh a, [c]` syntax.
If this causes problems with a lexer rewrite, it'll be deprecated; but for
now, keep it around, as the support is clunky but bearable.
Create a new file, platform.h, for platform-specific hacks
for MSVC, this includes defining strncasecmp to _stricmp and
strdup to _strdup, among other things like defining missing
stat macros
Change some things not supported in MSVC, like _Static_assert,
to their counterparts (in this case, static_assert)
Replace usage of VLAs with malloc and free
Update getopt_long and use the getopt implementation from musl
on Windows.
Use comments to show which functions from platform.h are being used
While compiling for empscripten there is a duplicate symbol conflict with these two variables. And as they are only used locally, and do not need a symbol exported they can just be static.
This should hopefully work torwards compatibility with more systems.
I've tried to make this as general as possible but some small assumptions
about the compiler are made. I've also tried to recreate the build process
as closely as possible, but I had to change some things slightly to work
with CMake (version strings, mainly).
For now, it doesn't allow in-source builds, as that could overwrite the
Makefile.
This adds:
- Support for more build systems
- Automatic dependency generation
- Performance gains (especially when using i.e. Ninja)
Defaults to Release build.
This one's really stupid; printing an int with %hhu gives a warning
even though a regular unsigned char is promoted to an int before
printing anyway. Silence it so the build with Clang works.
This is a regression introduced in 5c24de3
GCC with the -std=c11 defines __STRICT_ANSI__. DJGPP checks if
__STRICT_ANSI__ is defined and if so doesn't define some things
mandated by POSIX such as struct stat, PATH_MAX, and others.
The -std=gnu11 option does not define this macro, so use it instead.
_DEFAULT_SOURCE isn't needed as no GNU nor BSD-specific functions
are used. Remove it.
Fix the last two occurrences of incorrect format specifiers for standard
fixed-width integer types.
`macro_GetArg` had not been changed after the previous commit; however,
the old code relied on the `macroArgs->args` array being at least
`MAXMACROARGS` entries large (which was the case until the last commit).
The boundary against which it checked would have better been written as
`sizeof(macroArgs->args)/sizeof(macroArgs->args[0])`, I guess, but what's
done is done.
This should help make RGBDS portable to systems with 16-bit integers,
like DOS.
For kicks, use the macros for 16-bit and 8-bit integers.
Fix other miscellaneous things, like #include ordering and other
printf-format related things.
Reduce repitition in math.c while I'm there.
This didn't break unless the first uninitialized byte was non-zero,
which happened to be the case on someone's Windows machine.
Would it be worth it setting up Valgrind in CI?
Fixes#307
RGBFIX can handle padding, so there's no reason why
we can't add an option to disable padding in rgblink.
Signed-off-by: JL2210 <[email protected]>
This includes not checking the result of malloc and
using the wrong type in sizeof. Only the latter was
caught by scan-build.
Also use more idiomatic sizeof().
Signed-off-by: JL2210 <[email protected]>
It's possible that the unsigned integer may overflow to zero,
and then we might use zero-allocated memory.
This is incredibly unlikely, and I would even go so far as to say
that this is a false positive. Fix it anyway, to silence this warning:
src/link/patch.c:92:24: warning: Use of zero-allocated memory
stack.buf[stack.size] = value;
~~~~~~~~~~~~~~~~~~~~~ ^
Deal with overflow, and check for zero to get rid of the warning.
Signed-off-by: JL2210 <[email protected]>
Yet another case caught by scan-build:
src/link/patch.c:188:21: warning: Division by zero
value = popRPN() % value;
~~~~~~~~~^~~~~~~
Just copy over the code from the division case, with a few modifications.
Signed-off-by: JL2210 <[email protected]>
It's possible that if the FILE passed to yy_create_buffer is at the
end-of file, there may be a null pointer dereference.
This should hopefully fix that.
Found with clang-tools' scan-build:
src/asm/lexer.c:281:25: warning: Array access (via field 'pBuffer')
results in a null pointer dereference
pBuffer->pBuffer[size] = 0;
~~~~~~~ ^
1 warning generated.
Signed-off-by: JL2210 <[email protected]>
As 444 and 555 seem to be used for no apparent reason, use the more
conventional 644 and 755.
/man is typically unused or a symlink to /share/man now, so just use
/share/man.
Signed-off-by: JL2210 <[email protected]>
Note: I wanted to enable `-Og` on `develop`, but this generated warnings
(thus, errors) that aren't in `-O0`. Needs further investigation, but
annoyingly some of those are within `extern/` code, thus requiring
different flags, which AFAIK is only possible (sanely) with GNU Make.
This reverts commit 06fe27c516.
According to Microsoft's documentation
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/tmpfile?view=vs-2019
`tmpfile` attempts to create the temporary file at the **root** folder
This seems to assume that the user has admin rights; might be a compat
thing, idk, but it breaks on people's computers.
(CI didn't catch it, annoyingly.)
Reverting to make RGBASM usable on most Windows computers.
(Sanely-configured ones, at least.)
Another solution to #446 needs to be figured out, yay...
See individual comments within `rgbds.css` for more info
Not too fond of having to modify `mandoc.css`, but I did my best to
modify as little as possible
Adds links to argument descriptions in synopsis
Adds links to man pages in the set (not to external ones)
Removes artifact from the way long opts are encoded
Makes description blurb inline, consistently with terminal output
This touched a lot more code than initially expected, for two reasons.
First, this broke a big RGBASM assumption: that sections are always being
written to at their end. This plus other problems required touching
basically the entirety of `section.c`.
Second, I tried different solutions to solve the above problem, and along
the way I cleaned up many things around. (I believe that keeping this to
"cleanup" commits yields subpar results, and since it's boring they get
postponed anyways.)
RGBLINK support still needs to be added, but this will come next.
> Any kind of sequence can be defined using either left recursion or right
> recursion, but you should always use left recursion, because it can
> parse a sequence of any number of elements with bounded stack space.
https://www.gnu.org/software/bison/manual/html_node/Recursion.html
This should significantly improve performance: on pokecrystal builds, perf
reported as much CPU time spent on `yyparse` as on `sym_UseNewMacroArgs`
Measurements show ~6 seconds of improvement on that codebase.
This also fixes#321, as a bonus, due to saner management!
This was utterly stupid. The check right above ensured that `sym` was NULL,
ergo that the argument to `yyerror` *would* segfault.
The only two call sites cannot pass a non-NULL pointer anyways, which I'm
betting is why this went unnoticed.
I did what an optimizing compiler would do anyways: remove the dead code.
After discussing with some Windows user, this actually seems to be
a common thing to do (it seemed weird to me, but I know Windows' handling
of DLLs is weird anyways), so bundle that runtime and reinstate the
full test run for Win32.
As suggested by https://github.com/rednex/rgbds/issues/350#issuecomment-498030458
The order `count` then `byte` was decided after some discussion:
- First argument consistent with single-arg syntax
- Intuitive at least to some people other than myself
- Consistent with other assemblers, at least ca65
This causes it to auto-update whenever the current section's attributes are
updated, simplifying the code and eliminating redundancy.
This should also overall reduce overhead (one extra function call on each
PC evaluation, but less bookkeeping for each byte output)
This avoids redundancy between them (and also having to port fixes and features)
The error messages have been preserved through a string reporting mechanism
Make the bool field an actual bool
Rename `iReloc` to a more exact `isKnown` (as was already pointed out by some
comments)
Make the value of `BANK(symbol)` consistent when the argument is invalid
The syntax was `charmap "anything", "string"`; the second string was
already handled by `const`, but to the same effect... the ambiguous
declaration has been removed, leaving us at "only" two reduce/reduce
conflicts.
This was made separate with the intention of supporting multiple versions,
but after some discussion this was decided against, so better improve
readability instead.
"fixed" and "aligned" location checking advanced the target location to places
regardless of the associated free space, potentially breaking the assumption
that the location was always further in memory than the free space's base.
Rather than adding more code to try keeping that assumption true, harden
`isLocationSuitable` and handle that case as well.
This script allows diffing two Game Boy ROMs using `xxd` and `diff` and
attempts to augment the diff using information pulled from SYM files.
It's not part of RGBDS proper, but can be useful to debug tests (when ROMs fail
to match).
Windows does not honor `%F` nor `%T` in `strftime`. These are worked around
by writing the full format they serve as a short for.
However, Windows also treats `%z` and `%Z` identically, where SUS instead
requires `%z` to output a ±XXXX offset.
Since the current information is broken (no information), this isn't *breaking*
anything, but at least provides something a human will probably understand.
`__ISO_8601_UTC__` is unaffected because it hardcodes the timezone character,
only `__ISO_8601_LOCAL__` suffers from this.
The files being diffed (especially for variants) are temp files, so their
names are pretty nondescript. This improve error output, using ANSI escape
sequences to make those lines stand out.
Fixes rednex/#446.
I am not sure this is the best (in cases where the target directory
is not writable but the target file is), but maybe this can be
toggled via a flag, for example.
This option allows for automatic dependency detection and generation:
as soon as a missing file is found, it is output to the dep file, and
assembly immediately aborts. (No .o file is produced, even if `-o` was
speicified.) This doesn't cause an error, either; the point is that once
the file is added to the dep file, the Makefile is re-parsed, and this
time the file will be generated, so the dep list builds up automatically.
This mimicks GCC's option and behavior.
Allows overriding the output file in dependencies, which also allows
outputting those without also outputting the object file.
This, again, mimicks GCC's option.
Stop using that bitfield for everything, including what can be determined otherwise
It also makes it easier to have a sane state, since some bits were (supposedly)
mutually exclusive
This is actually not necessary, because RGBLINK would warn about missing labels.
Besides, through semi-esoteric ways, it is possible to define more labels in this scope,
and there's no reason to prevent that.
`char` has implementation-defined signedness, and if it's chosen to be unsigned,
then -1 gets converted to 255, which is then promoted back to `int` as... 255,
always failing the loop condition in src/link/main.c:118
`int8_t` has the correct signedness, but considering `musl_getopt_long_only`
returns `int`, better use that so as not to lose any bits
POSIX leaves undefined the order of output if stderr is injected into stdout,
and in practice it differs on Windows (Linux buffers both streams separately,
Windows interleaves them as they arrive without buffering).
This should help testing on other platforms
This macro hid away the arguments to the underlying call, and served
no purpose beyond saving the programmer some typing. This is 2019,
people have IDEs (even Vim!) with autocompletion.
That folder contains external code, and modifying it to conform to our
code style would make applying upstream patches, amongst others,
problematic. Therefore, skip checking it.
Ideally, the folder should also be excluded from `make checkpatch`,
but I haven't figured out a way to do that yet.
Since the RGBLINK rewrite, there have been no .l files in the whole codebase
(RGBASM has the C file directly, for better and for worse)
Since flex isn't used anymore, it's a good idea to remove it from the Makefile
so people don't think it's a dependency.
Those are only useful for locking file IO across threads, but RGBLINK is
single-threaded anyways, so they don't matter. Plus, they aren't provided by
mingw, so that'll remove part of the problem
The error was due to casting `const` away for permuting argv
elements, which is necessary for a libc for compatibility with older
systems, but not for us.
Checkpatch will complain about the style not being followed, but this is not
our code, so it can be ignored.
Both `getopt_long` and `getopt_long_only` are GNU-specific, so we'll be
copying musl's implementation for portability.
This was retrieved as of commit 90251cf73dfdd44e7a3f085d236e89a7dff1b00b.
musl is licensed as MIT, which is compatible (being identical...) to RGBDS'.
The file is being copied as-is, without a copyright notice or attribution,
but this is only to have a verbatim copy in the history. Those will be added
in the next commit.
The goal was to improve readability, but along the way a few things were
gained.
- Sorted sym and map files
- Infrastructure for supporting multiple .o versions
- Valgrind-proof, as far as my testing goes anyways
- Improved verbosity messages
- Added error checking
- Performance improvements, see end of commit message
The readability improvement was spurred while trying to make sense of the
old code while trying to implement features such as sorted sym and map
files.
I also did my best to remove hardcoded logic, such that modifications
should be doable; for example, "RAM loading" sections, which are linked
against a different location than the one they're stored at.
Some work remains to be done, see the "TODO:" and "FIXME:" comments.
Further, while regression tests pass, this new linker should be tested on
different codebases (ideally while instrumented with `make develop` and
under valgrind).
The few errors spotted in the man pages (alignment) need to be corrected.
Finally, documentation comments need to be written, I have written a lot of
them but not all.
This also provides a significant performance boost (benchmarked with a
51994-symbol project):
Current master RGBLINK:
2.02user 0.03system 0:02.06elapsed 99%CPU (0avgtext+0avgdata 84336maxresident)k
0inputs+11584outputs (0major+20729minor)pagefaults 0swaps
Rewritten RGBLINK:
0.19user 0.06system 0:00.63elapsed 40%CPU (0avgtext+0avgdata 32460maxresident)k
23784inputs+11576outputs (0major+7672minor)pagefaults 0swaps
The stdlib functions specify the difference between `err` and `errx`
is that the former prints a message obtained with `strerror`.
However, RGBDS' implementation breaks that contract, and `warn`'s puts the
added semicolon in the wrong place.
This is especially useful when an EQUS expands to another one, to help
track them.
This is done separately from the file stack as the EQUS stack is separate
(which is itself because EQUS are managed *way* differently).
Macro and rept buffers were not always being terminated with newlines
and/or were vulnerable to the final newline being escaped, allowing
buffer overflows to occur. Now, they are terminated with newlines using
the same mechanism as the file buffer.
Null characters in the middle of strings interact badly with the RGBDS
codebase, which assumes null-terminated strings. There is no reason to
support null characters in input source code, so the simplest way to deal
with null characters is to reject them early.
They do not take any room, so they can only be used to define symbols at
a given location. I ran into trouble with such a SECTION failing to be
placed where specified, which doesn't make sense.
This way, it also makes sense to have such a SECTION in the middle of
another one, but that should be fine, since there's no actual overlap.
f29d768 forgot to switch these two `expr->nVal` to `src1->nVal`
This won't break anything, since this wasn't published yet.
I checked, and didn't see any other missed changes.
Reported by pret, I confirmed that `1 && 1` evaluated to 0.
This is good for debugging Makefiles on systems I don't have (eg. macOS)
End users will not be affected by this, and CI provides a persistent log
so clobbering isn't much of an issue.
Some errors are only tripped in `out_WriteObject`, which was
basically a stub when `-o` wasn't specified. Now, instead,
errors are checked in a separate function before out_WriteFile
The old error stack was fairly obtuse and hard to use for debugging.
This improves it notably by ensuring all line numbers are relative
to the file, and not, say, the macro definition.
This is a breaking change if you were parsing the old stack, but
the change should be painless, and the new stack only brings more info.
The syntax is unchanged for files, macros see their name prefixed
with the file they're defined in and a pair of colors, REPT blocks
simply append a '::REPT~n' to the context they're in, where 'n' is
the number of iterations the REPT has done.
This is especially helpful in macro-heavy code such as rgbds-structs.
If a line ended with a string's closing quote, or a newline escape, then
skipping over that line via IF/ELIF/ELSE would fail to count that line,
offsetting the rest of the file.
I have no idea why but for some reason 9829be1 changed *specifically*
`if_skip_to_else` to have incorrect behavior on string endings. The incorrect
behavior on newline escapes seems to have been here since the beginning.
Also added a test to check for both of those behaviors in both functions.
Honestly, it baffles me that nobody ever noticed. I didn't until I started
working on #395.
Unlike macros, REPTs and INCLUDEs, this recursion depth is independent.
This is intentional, because string expansions work very differently.
While it's easy to know when a string expansion begins, checking where it
ends is much more complicated, since the expansion's contents are simply
injected back into the lex buffer. Therefore, the depth has to be checked
after lexing took place.
Because of this, the placement of the expansion end check is somewhat
haphazard, but I think it's good. While I have no certainty, all tests
ended with all expansions properly ended, and I couldn't find any pitfalls.
Finally, `pCurrentStringExpansion` has been made global so error printing
can use it to tell the user if an error occurred inside of an expansion.
REPT blocks nested in macros (and possibly other cases) leaked
memory on every call. Unlike most other memory leaks, which would
be freed at the end of program execution if they were done properly,
those piled up the more compilation went on.
I believe memory usage could have started being fairly high on
large projects following the "one master file INCLUDEs all the rest"
so this may have actually been worth it.
sym_SetMacroArgID used a `sprintf` that could write no \0.
In practice this was benign because %u cannot print 256 chars,
but better future-proof this.
(And REPT.)
Not exactly a *recursion* limit, more like a *stack depth* limit,
but calling it "recursion" conveys its purpose better.
The default of 64 is super overkill: even in a a project with
what I believe to be above-average levels of nesting, the
level only peaked at 6.
Keeping in mind the purpose of this is to catch infinite
recursion, which is still caught quickly (in usual cases, anyways),
this default seems sensible.
And it passes tests. What more do you need?
This adds two new directives: newcharmap and setcharmap.
newcharmap creates a new charmap and switches to it.
setcharmap switches to an existing charmap.
While working on #392, I noticed that the macro-@ test (as well
as the line-continuation test, but for that one see #393)
printed an additional '@(-1)' entry which doesn't make sense.
When trying to skip over nested if statements, if there was no whitespace
after an "if", then that "if" would not be recognized. That's a problem since
"if(" and "if{" are also valid ways to start an if statement. This change
will make it so that they are recognized correctly.
c75a953 broke my (previously-working) project that defined, via
macros, 'sizeof_.player'.
A test was added to confirm that those are indeed accepted
outside of macros.
Should partially cover #178 and close#270.
This allows printing numbers in different bases and without the dollar prefix
This is especially useful in macros because the dollar isnt a valid character
for symbol names, requiring heavy `STRSUB` usage.
When trying to fix a section becoming too large, the size it reached is necessary to know whether to optimize away a few bytes or split it entirely.
This error is also commonly encountered when INCBINing too large a slice of a file, in which case the amount of bytes by which the section is too large is again an useful information
Previously, a PUSHS before a SECTION directive would cause rgbasm to crash when encountering a subsequent POPS.
This is because the subsequently-called out_setCurrentSection() expected the new section to be non-null, which wasn’t the case in this situation. This has been addressed by allowing the ‘null’ section to be set in this function, and only dereferencing it (to set nPC) if a non-null section is to be set.
In practice, this means that PUSHS/POPS can now be used to push/restore a context without a section.
Charmap's previous structure was using brute-force comparison for
converting the strings in source files. It always compared given
strings to all of the strings in charmap, which was very costly
in huge projects.
For its improvement, I changed its structure into trie, which is
being used in many string-processing areas. It's now much faster
than before.
There is a bug in processing the comments in source files. It's
related to #326. And this bug comes out when you comment something
with the character ';', and include the quotation mark without its
pair in it.
The lastest version of rgbds compiler has a step to parse the given
source to convert its line endings to a unified one, and it
processes quotation marks even before it processes the comments.
I edited a little bit of the source, and it works fine now.
If the type char is signed, then in the function
yylex_GetFloatMaskAndFloatLen(), *s can have a negative value and be converted
to a negative int32_t which is then used as an array index. It should be
converted to uint8_t instead to ensure that the value is in the bounds of the
tFloatingFirstChar, tFloatingSecondChar, and tFloatingChars arrays.
The createpatch() function was using a fixed-size buffer. I've changed it
to be dynamically allocated. I saw that the RPN format used in patches is
slightly different from the one used internally in the assembler, so I
added a new member to the Expression struct to track the patch size.
I've also limited the RPN expression length to 1MB. I realized that the
patch RPN expression could potentially be longer than the internal RPN
expression, so the internal expression would need a limit smaller than
UINT32_MAX. I thought 1MB would be a reasonable limit.
When a macro arg appears in a symbol name, the contents are appended.
However, the contents of the macro arg were not being validated.
Any character, regardless of whether it was allowed in a symbol name,
would be appended. With this change, the contents of the macro arg
are now validated character by character. The symbol name is considered
to end at the last valid character. The remainder of the macro arg is
treated as though it followed the symbol name in the asm source code.
It seemed that the consensus in our discussions of signed integer
overflow, which invokes undefined behavior in C, was that integer
arithmetic should be two's complement and there should be no warning for
overflows. I have implemented that by converting values to unsigned types
when appropriate. These changes will mostly preserve existing behavior,
except for a few cases that were being handled incorrectly before.
The case of dividing INT_MIN by -1 previously resulted in a CPU
exception and program termination. Now, that case is detected and results
in a warning and a value of INT_MIN.
Similarly, INT_MIN % -1 would have resulted in a CPU exception. Since this
is a mathematically valid operation with a result of 0, it now simply
gives that result without a warning.
I noticed that in rpn.c, there were attempts in certain operation handlers
to validate the nVal members of the source expressions even when the
expressions may have been relocatable expressions with meaningless numbers
for the nVal member. This could have caused spurious errors/warnings, so I
made those handlers confirm that isReloc is false before validating nVal.
Also, integer constants that are too large now result in a warning. The
post-conversion values have not been changed, in order to preserve
backward compatibility.
Standalone bracketed symbols like the following weren't being zero-terminated.
X EQUS {Y}
This doesn't apply to bracketed symbols that aren't standalone, but are
instead found in a string. For example, the following works even without this
fix.
X EQUS "{Y}"
This branch was meant to contain changes that were considered too risky
to be in master. However, there is not enough activity in the repository
to justify its presence. Both branches are always pointing at the same
commit.
Signed-off-by: Antonio Niño Díaz <[email protected]>
When the while loop in `ParseSymbol` stops because of the symbol length,
`copied` will have the value of `MAXSYMLEN`, which is obviously not
greater than `MAXSYMLEN`. Changing the condition to `>=` fixes the
issue.
As a bonus, the correct union field will now be used. It shouldn't
matter, but it's technically UB to use a wrong one.
The linker script now allows you to assign a section with the same
attributes as in the source.
To do this, I've removed a check from AssignSectionAddressAndBankByName
that would never be triggered, due to that condition being checked
before. Shouldn't this and IsSectionSameTypeBankAndAttrs be condensed
into a single function?
Currently, all symbols are assigned a filename and line when they're
first encountered and added to the internal hash table. This is often
not expected and leads to erroneous error messages.
The original list only existed because the documentation was split
across multiple files. When all keywords are described in a single
document, Ctrl+F suffices to find them.
Two variables, pSection->Data and tSymbols, were previously set to
dummymem, a global variable that was otherwise not used.
As this can potentially cause alignment warnings on Clang, this commit
replaces that mechanism with a plain old NULL pointer, which is more
generally used as a dummy pointer value.
Signed-off-by: Antonio Niño Díaz <[email protected]>
We no longer assume that the test repos don’t exist when we run
run-tests.sh. This allows developers to choose to keep them, to allow
them to run the tests more quickly.
- Add the test repos to the .gitignore.
- Check if the directory for each repo already exists, before trying to
clone it.
- Do a git pull for each repo, to ensure that existing copies of repos
are up-to-date.
Signed-off-by: Antonio Niño Díaz <[email protected]>
This ensures that build breaks to any of the test projects don’t immediately cause rgbds tests to fail.
On clone, I’ve set it up to pull the commits since the day before the desired commit. Sadly, this will clone more recent commits that we’re not testing, but at least it ensures that the desired commit can be checked out. This is hopefully a good enough replacement for —depth=1.
Signed-off-by: Ben10do <[email protected]>
Two variables, pSection->Data and tSymbols, were previously set to ‘dummymem’, a global variable that was otherwise not used.
As this can potentially cause alignment warnings on Clang, this commit replaces that mechanism with a plain old NULL pointer, which is more generally used as a dummy pointer value.
Signed-off-by: Ben10do <[email protected]>
We no longer assume that the test repos don’t exist when we run run-tests.sh. This allows developers to choose to keep them, to allow them to run the tests more quickly.
- Add the test repos to the .gitignore.
- Check if the directory for each repo already exists, before trying to clone it.
- Do a `git pull` for each repo, to ensure that existing copies of repos are up-to-date.
Signed-off-by: Ben10do <[email protected]>
A regression was spotted in rgbfix 0.3.7, where we would accidentally include the first byte of the existing checksum when calculating a global checksum. We now correctly ignore both of the existing checksum bytes.
This was spotted when running rgbfix on the Pokémon Gold/Silver betas, as they have a non-zero global checksum.
Fixes#280.
Signed-off-by: Ben10do <[email protected]>
The following mnemonics are now valid:
- ld
- ldh
- ldio
The following are valid as operands:
- [$ff00+c]
- [$ff00 + c]
- [c]
This is done for consistency with 'ld [$FF00+n],a' and variations of it.
Signed-off-by: Antonio Niño Díaz <[email protected]>
The tests are not exhaustive, there are some conditions that aren't
checked. The tests are based in the C standard rules about undefined
behaviour.
This is a compatibility break but, hopefully, all projects are using
sane values. If not, there is no guarantee that the projects will build
in any platform where RGBDS can be compiled, so it would be better to
fix them.
Even though, technically, the left shift of a negative value is always
undefined, some projects rely on its current behaviour. This is the
reason why this doesn't cause a fatal error.
Signed-off-by: Antonio Niño Díaz <[email protected]>
GCC has an Undefined Behavior Sanitizer (ubsan), which enables run-time
checks of undefined behaviour. It has been enabled for the `develop`
build target.
A small bug detected with it has been fixed.
Signed-off-by: Antonio Niño Díaz <[email protected]>
The Linux kernel expects the SPDX license tag to be in the first line of
all source code files. The reason is that they have many different
license headers, and this simplifies the work for any tool that has to
determine the license of each file.
In this project, the license headers follow the same pattern, so it
isn't useful.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Previously, the output file was opened before trying to open the
overlay. Because of this, rgblink generated an empty output file if the
overlay couldn't be opened.
Now the overlay is opened (and checked) before the output file, so the
output file is only generated if the overlay is found.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Rewrite rgbfix to perform most actions in memory.
Limit file operations to a small number that can be reasonably checked,
and do the majority of the actual work on a buffered header in memory
where operations won't fail.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Limit file operations to a small number that can be reasonably checked,
and do the majority of the actual work on a buffered header in memory
where operations won't fail.
Enable a lot of GCC warnings and cleanup Makefile and compiler macros
Most of the warnings in the GCC documentation have been enabled. As the
build system was using `-Werror`, this made the new builds very
susceptible to any minor change in the compiler. To fix that, this
option has been removed from the default Makefile target and it is only
used when the code is compiled through `make develop`.
The file `stdnoreturn.h` has been modified to remove support for
compilers that aren't actually tested. It now has defines for
`__attribute__((unused))` and it has been renamed to `helpers.h`.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Added define 'unused_' for '__attribute__((unused))'. The oldest version
of GCC with online docs (GCC 2.95.3, released in March 16, 2001 [1])
already has support for this attribute, so it doesn't make sense to
check the version.
Renamed 'noreturn' to 'noreturn_' for consistency.
[1] https://gcc.gnu.org/onlinedocs/
Signed-off-by: Antonio Niño Díaz <[email protected]>
`__attribute__((noreturn))` has been supported since GCC 2.5, that was
released October 22, 1993. It doesn't make sense to check if the version
is at least that one, we are compiling for C99, that is more modern. [1]
Also, remove the MSVC check. This code is never compiled with it so
there may be problems that need to be solved to make it compile. All
releases cross-compiled from linux. If there is an actual need to
support MSVC, the compiler definitions can be added again.
Also, if the compiler is not supported, the compiler helpers default to
nothing, so the code can still compile.
[1] https://gcc.gnu.org/onlinedocs/
Signed-off-by: Antonio Niño Díaz <[email protected]>
Remove '-Werror' from the default make target to make it easy for
regular users of RGBDS to compile the source code. Only a few basic
warnings are left in that target.
All the warnings have been moved to a new target called 'develop'. This
target is now the one used in Travis CI to check for problems during
compilation.
Signed-off-by: Antonio Niño Díaz <[email protected]>
-Wformat-truncation is set to 1 instead of 2 because in some cases the
return value of snprintf is used to warn about truncations but GCC still
creates a warning for it, preventing the compilation from continuing.
Signed-off-by: Antonio Niño Díaz <[email protected]>
-Wsign-compare has been disabled because flex generates a comparison
that triggers a warning and cannot be fixed in the code.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Fix a few warnings related needed to build the source with this option.
Add new exception to .checkpatch.conf.
Signed-off-by: Antonio Niño Díaz <[email protected]>
When '@' is used as argument of any instruction (LD, JR, JP, etc), the
address it refers to is the address of the first byte of the
instruction. When '@' is used with DB/DW/DL, it refers to the same
address it is being placed at. This means that instructions need an
offset of 1 byte and others need an offset of 0 bytes.
The assembler doesn't evaluate anything related to '@' because it would
only work in sections with a fixed base address. It is left to the
linker. This means that the offset needs to be added to the RPN
expression of the patch that is saved in the linker. It isn't enough by
adding an offset to the final expresion. The following value wouldn't be
calculated correctly (even if it doesn't make sense):
JP @ * @
The correct patch is `(@ - 1) * (@ - 1)`, not `(@ * @) - 1`.
This patch introduces an offset on 1 byte by default in every line, and
sets it to 0 only if a DB/DW/DL is detected.
Signed-off-by: Antonio Niño Díaz <[email protected]>
This change removes 2 reduce/reduce conflicts in the parser while
preserving the behaviour of the rules.
Note that now each list with empty elements will only print a warning
per line.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Previously, JR was only allowed to labels (in the same section, or
different sections). When trying to JR to an address specified as a
numeric value, rgbasm would fail to calculate the JR offset (as it
doesn't know the final address of the JR so it can't calculate the
difference).
This patch makes rgblink calculate the offset whenever there is a JR.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Images are allowed to have any arbitrary height if the width is 8. If
the height is not a multiple of 8, the number of tiles calculated won't
be an exact number and it will be rounded down. This patch increases the
number of tiles allocated in this case to prevent rgbgfx from accessing
memory that hasn't been allocated.
The buffers are now initialized to 0 with calloc instead of being
created with malloc.
Signed-off-by: Antonio Niño Díaz <[email protected]>
For example:
PrintMacro : MACRO
PRINTT \1
ENDM
PrintMacro STRCAT(\"Hello\"\, \
\" world\\n\")
It is possible to have spaces after the '\' and before the newline
character. This is needed because Windows line endings "\r\n" are
converted to " \n" before the lexer has a chance to handle them.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Lines can be continuated after a newline character ('\n'):
DB 1, 2, 3, 4 \
5, 6, 7, 8
This doesn't work for now in lists of arguments of macros.
It is possible to have spaces after the '\' and before the newline
character. This is needed because Windows line endings "\r\n" are
converted to " \n" before the lexer has a chance to handle them.
Signed-off-by: Antonio Niño Díaz <[email protected]>
rgbasm tries to optimize any loads from/to $FF00-$FFFF and generate
LDH 2-byte opcodes instead of regular LD 3-byte opcodes. This is a bit
inconsistent as it only works for constant values. If a load is trying
to access a label in a HRAM floating section, or a section found in a
different object file, this optimization doesn't work.
This means that a simple refactor or code could allow rgbasm to perform
the optimzation or prevent it from doing so. For certain projects, like
disassemblies, this is a problem.
This patch adds flag -L to rgbasm to disable the optimization, and
doesn't change the behaviour of any other existing code.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Use snprintf instead of other unsafe functions. That way it is possible
to limit the size of the buffer and to ensure that it never overflows.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Newlines have to be handled before comments or comments won't be able to
handle line endings that don't include at least one LF character.
Also, document an obscure comment syntax: Anything that follows a '*'
placed at the start of a line is also a comment until the end of the
line.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Previously, JR was only allowed if the destination label was in the same
section as the JR. This patch removes this restriction. The check to see
if the relative value overflows is now done when linking the ROM.
Signed-off-by: Antonio Niño Díaz <[email protected]>
PRINTV prints integers in hexadecimal, PRINTI prints them in signed
decimal. For example:
PRINTT "Error at line "
PRINTI __LINE__
PRINTT "\n"
Signed-off-by: Antonio Niño Díaz <[email protected]>
Small tests like the ones included in this repository are good to test
individual features, but it is also a good idea to test some real
projects.
Signed-off-by: Antonio Niño Díaz <[email protected]>
strncpy is designed to output to fixed‐width buffers, not C strings
(hence its weird null termination behavior). In this case it happens to
work correctly due to the length check but, for style reasons, I would
rather use snprintf. Especially in this case, where it shortens the
code a bit.
By removing this dependency, all of the code of this repository is
licensed under the MIT license.
Signed-off-by: Antonio Niño Díaz <[email protected]>
There was only one place where `strlcat` was used, and `snprintf`
actually does a better job at what the code was trying to achieve.
Signed-off-by: Antonio Niño Díaz <[email protected]>
With permission from the main authors [1], most of the code has been
relicensed under the MIT license.
SPDX license identifiers are used so that the license headers in source
code files aren't too large.
Add CONTRIBUTORS.rst file.
[1] https://github.com/rednex/rgbds/issues/128
Signed-off-by: Antonio Niño Díaz <[email protected]>
Travis seems to be having some problems with OSX builds, so it's better
to disable them temporarily.
Signed-off-by: Antonio Niño Díaz <[email protected]>
NULL error messages have been given a description.
Messages that weren't descriptive enough now also print the name of the
function that has failed.
Signed-off-by: Antonio Niño Díaz <[email protected]>
ROMX and WRAMX bank numers are stored in an object file as their number
minus one. This means that this offset has to be applied somewhere.
The old code applied the fix for ROMX and WRAMX in two different places.
It looks like the patch that added support for WRAMX didn't set the
offset correctly in 'src/link/assign.c'. When this was fixed, it was
done in the wrong place, in 'src/asm/asm.y'. This patch moves the fix to
'src/link/assign.c'.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Now, when POPS is executed, it restores the symbol scope of the
corresponding PUSHS. That way, the local symbols previously available
can be used again after the POPS.
This is useful in cases like this one:
```
SECTION "Section 1", ROMX
BigFunction:
...
.loop:
...
PUSHS
SECTION "Section 2", ROMX
DataForBigFunction:
DB 1, 2, 3, 4, 5
POPS
ld a,BANK(DataForBigFunction)
ld hl,DataForBigFunction
...
jr .loop
```
Signed-off-by: Antonio Niño Díaz <[email protected]>
The bank of a section can be requested with `BANK("Section Name")`, and
the bank of the current section with `BANK(@)`. In both cases, the bank
number is resolved by the linker.
New commands have been added to the list of RPN commands of object
files, and the rest has been moved so that new additions don't force a
new change in the number of the enumerations.
Increase object file version, as it is now incompatible with the old
format.
Update manpages to reflect the new ways of using `BANK()` and the new
format of the object files.
Signed-off-by: Antonio Niño Díaz <[email protected]>
It made sense to have them in different files when the toolchain
targeted systems other than the GB. Now, there are no generic and
system-specific keywords because there is only one supported system.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Not all occurrences have been replaced, in some cases they have been
left as they were before (like in rgbgfx and when they are in the
interface of a C standard library function).
Signed-off-by: Antonio Niño Díaz <[email protected]>
This warning was added in 781c90b940 as a
way of catching the following cases, which are most likely programmer
mistakes:
DB 1,, 2
DB 1, 2,
However, the warning was also triggered in the following case:
DB
It can be used as a replacement of:
DS 1
In this case, it shouldn't output a warning.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Even though this behaviour is documented (empty elements are treated as
0), it can be misleading. By having a warning, compatibility is
maintained and potential problems in the code can be detected.
Signed-off-by: Antonio Niño Díaz <[email protected]>
It was removed in commit 6198cc185c, but
the documentation wasn't updated back then.
It makes more sense to reintroduce it now than to remove it from the
docs.
Signed-off-by: Antonio Niño Díaz <[email protected]>
In some implementations of libc the function fread has the attribute
`warn_unused_result`, that is treated as an error by the compiler as
specified in the flags passed to it.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Now, the object file in which each definition is (as well as the source
file and line) are printed with the error message.
Signed-off-by: Antonio Niño Díaz <[email protected]>
This is useful to generate error messages when there is a symbol that
appears in more than one object file.
Signed-off-by: Antonio Niño Díaz <[email protected]>
When trying to define a symbol with a name that is used by another one,
print the location of the first definition in the error message.
Signed-off-by: Antonio Niño Díaz <[email protected]>
The previous change has broken compatibility of object files, so it is
needed to increment the version number to make the linker reject files
generated with the old code.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Unions allow multiple memory allocations (using ds, etc.) to share the
same space in memory.
This allows games to use the same memory for different purposes,
depending on their state.
This also adds documentation on how to use the new UNION, NEXTU, and
ENDU keywords.
This option has been added to all programs of the toolchain, and it
prints the version string of the toolchain.
Manpages and help command line output updated.
Add missing 'w' flag to the command line output of rgbasm. It was
correctly documented in the manpages.
Signed-off-by: Antonio Niño Díaz <[email protected]>
If the folder where the code is compiled is a valid git repository, the
version string is generated with `git describe`. If it isn't a valid
repository, a string included in the source code is used instead. This
one must be updated regularly as the toolchain is developed.
Signed-off-by: Antonio Niño Díaz <[email protected]>
In addition, make some formatting changes, and add some extra error handling (for when ELIF, ELSE, or ENDC are encountered without a corresponding IF).
This ensures that the test scripts are correctly run with the Bourne shell, regardless of the (potentially more exotic) shell that is used to invoke the script.
Previously, if the user wanted to modify CFLAGS, it was necessary to add
the options used in the Makefile as well, which doesn't make sense.
This patch splits CFLAGS into CFLAGS and the previously removed
REALCFLAGS so that the user can modify the arguments passed to the
compiler without having to worry about things like passing the list of
include directories.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Some commands, such as `DS`, `BANK[n]`, etc, don't allow the use of
negative constants, but there wasn't any check to prohibit the code from
trying to do so.
This patch adds the `uconst` type to the parser to use when a constant
is expected, but it mustn't be negative.
Signed-off-by: Antonio Niño Díaz <[email protected]>
- Local labels can now be exported.
- Local labels can be declared as Scope.Label in addition of .Label.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Local symbols can now be referenced outside the scope of their parent, by using the syntax “Parent.Chlid”.
- Local symbol names are now stored internally as “Parent.Child”.
- The symbol’s scope field no longer forms a linked list of the prior local symbols; it will now always contain the parent.
- Add the ability use EXPORT and GLOBAL with local symbols.
- Reduce duplication between findsymbol() and findpsymbol(), as well as between sym_AddLocalReloc() and sym_AddReloc().
There are two ways in which the assembly process can fail:
1. If there is a really big problem that compromises the whole process,
the assembler has to stop right there and generate an error message.
This happens with unterminated REPT loops, macros, etc.
2. If the problem isn't that big and the process can still continue,
even though the final result is invalid, the assembler can try to
continue and warn the user about all errors it finds in the code.
This patch clarifies the use of each function and replaces the function
used in two places by the correct one.
Signed-off-by: Antonio Niño Díaz <[email protected]>
This is hard to detect in MACROs, as there are legitimate uses for
MACROs that call themselves recursively.
For an EQUS, the problem is that its value may be modified at different
points in the source code, so the only way to detect a possible problem
is by doing an analysis at each usage of the EQUS.
Also, since an EQUS may expand to the name of a MACRO and a MACRO can
use an EQUS, it becomes even harder to check all possible problems that
come out of it. It's better to let this task to the programmer.
Signed-off-by: Antonio Niño Díaz <[email protected]>
When allocating a section, allocate only the max possible size for that
type (only applies to ROM0 and ROMX).
When finding an overflow, in any kind of section, output an error with
the location of the line of code that caused the overflow.
Signed-off-by: Antonio Niño Díaz <[email protected]>
The max size of some section types depends on the flags passed to
rgblink. Instead of doing in rgbasm some checks (for the sections with
fixed size) and others in rgblink, all checks are now done in rgblink.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Instead of allocating 0x4000 bytes for all sections and resize them as
needed, allocate 0x8000 bytes and don't let them to be resized. This is
the max possible size (ROM0 when ROMX sections aren't present).
Buffers are not needed for RAM sections, this patch changes the code so
that it only allocates buffers for ROM sections.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Files that weren't found with the absolute path weren't added as
dependencies even if they were found after considering the list of
include directories.
This patch makes rgbasm print the complete path (including the include
directory path) in these cases.
Signed-off-by: Antonio Niño Díaz <[email protected]>
For some reason, `No` looks weird in the HTML version of the docs.
Some other random fixes.
Tables in src/asm/rgbasm.5 are still broken in the HTML docs.
Signed-off-by: Antonio Niño Díaz <[email protected]>
When including a linkerscript from a parent one, the lexer didn't
include a newline character because the INCLUDE command was handled
before reaching the newline. This behaviour is needed to parse the last
line of a linkerscript correctly (it doesn't have a newline character).
However, this meant that when the included file was being parsed, the
first line was considered a continuation of the last line of the parent
script (the INCLUDE command), which means that the first line of an
included linkerscript could only contain a comment (or nothing at all).
This patch adds a newline character to the buffer used by the lexer so
that the parser will receive a newline and it will handle the first line
of the included file as expected.
Signed-off-by: Antonio Niño Díaz <[email protected]>
`LD HL,n16` and `LD SP,n16` are handled in a different rule as
`LD r16,n16`, but they are also part of that rule.
This patch converts the `LD r16,n16` rule into two rules, one for doing
`LD BC,n16` and other one for `LD DE,n16`.
Signed-off-by: Antonio Niño Díaz <[email protected]>
rgblink option -w has been restored to its previous behaviour: make WRAM
a continous section instead of spliting it into WRAM0 and WRAMX.
To enable DMG mode, option -d has to be used instead. This option
automatically enables -w.
Update tests.
Signed-off-by: Antonio Niño Díaz <[email protected]>
If the next release is going to break compatibility with older object
file formats it doesn't make sense to keep this.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Added `__TIMESTAMP_ISO_8601_LOCAL__` and `__TIMESTAMP_ISO_8601_UTC__`,
with the correct ISO 8601 representation of time and date from years to
seconds (including local timezone in the local time string).
Also, if the current time cannot be obtained from the OS, it will output
a warning and the time strings will be filled with '?' instead of
numbers and characters.
Signed-off-by: Antonio Niño Díaz <[email protected]>
If they don't have quotes when passed to sym_AddString() they can't be
used at all by the assembler. I suppose nobody actually used them, they
seem to have been broken forever.
Added a comment to the function to say how to use it correctly for
strings.
Signed-off-by: Antonio Niño Díaz <[email protected]>
IMPORT is simply useless, any symbol that isn't found in the current
file is automatically flagged as imported symbol.
Signed-off-by: Antonio Niño Díaz <[email protected]>
Files can now be included with the following syntax:
INCLUDE "path.link"
The maximum include depth is 5.
Fixed linkerscript parser and lexer error messages so that they are more
informative (show file and line of the error).
Man page updated.
Signed-off-by: Antonio Niño Díaz <[email protected]>
The error message shouldn't specify the name of the binary, that's
supposed to be known by the caller.
Update test reference outputs.
Signed-off-by: Antonio Niño Díaz <[email protected]>
It compares the results of the operators with the expected result if
doing the same thing manually.
Signed-off-by: Antonio Niño Díaz <[email protected]>
They work with the 16-bit registers BC, DE and HL, returning the
corresponding 8-bit register. HIGH() works with AF as well, returning A.
They also work with any kind of constant or symbol, generating a RPN
patch in the object file if the value is not defined at assembly time.
They work with macro arguments as well.
Signed-off-by: Antonio Niño Díaz <[email protected]>
A lot of warnings are being added (and more will come) so it makes sense
to be able to disable them in legacy source that generates warnings but
is otherwise correct.
Signed-off-by: AntonioND <[email protected]>
Remove support for RGB0 and RGB1-2 object files, reducing the amount of duplicate work that needs doing when maintaining the linker in the future.
A new error message has also been implemented if an unsupported object file version has been encounted, which informs the user that they should reassemble.
Replace spaces by tabs for consistency. The rest of the codebase uses
tabs, so the linkerscript parser has to change.
Removed trailing tabs in all codebase.
Signed-off-by: AntonioND <[email protected]>
getsymbank() is used for more things than just when the code explicitly
has a BANK() operator, which causes a lot of noise when building code
that has more than one object file and places variables on HRAM or OAM.
Signed-off-by: AntonioND <[email protected]>
When calculating the difference of addresses between two labels, for it
to be defined, either:
- Both of them must have their absolute address defined.
- They belong to the same section, so their relative addresses are
compatible.
This patch adds a check to make sure that any other case is detected so
that the programmer can correct the code.
This applies to rgbasm. The difference of labels can be used, for
example, as argument of DS. The linker can't resize sections, which
means that the final value must be defined when creating the object
file.
Signed-off-by: AntonioND <[email protected]>
Instead of converting from ROMX to ROM0 with -t and preventing the use
of WRAMX at all with -w, make each option prohibit the type of section
they affect.
This is a good idea because it can prevent a developer from making
mistakes when switching from using the options to not using them.
Generally, a change from using one single bank to multiple banks is
something that will take a lot of effort, and forgetting sections in
ROM0 or WRAM0 will only make the free space of those areas to be
reduced (and maybe prevent compilation), but it won't cause any problems
because of a forgotten bank swap in the code.
Signed-off-by: AntonioND <[email protected]>
Check all sections when testing BANK().
Add scripts to verify the tests and update the reference if needed.
Signed-off-by: AntonioND <[email protected]>
Improve error messages generated by `errx()`, `warnx()` and similar.
Set `progname` to a static string with the name of the program so that
the path of the binary isn't included in error messages.
Signed-off-by: AntonioND <[email protected]>
Instead of returning the internal representation of the linker, return
0 when using BANK() on a label in HRAM.
Also, generate a warning when calculating the bank of labels in OAM
and HRAM, as there is no valid reason for doing it, so it's likely a
programming mistake.
Signed-off-by: AntonioND <[email protected]>
- Rename the “Installing RGBDS (UNIX)” section to “Building RGBDS”, as that’s what we’re doing, regardless of platform.
- Update references of Mac OS X to macOS.
- State that only libpng and pkg-config need to be downloaded with Homebrew; the others are pre-installed along with Xcode.
- State that RGBDS itself is available through Homebrew.
Due to recent changes, lots of tests generated a slightly different
error output.
- bank-noexist : This test doesn't generate any error output now as
unknown labels are left for the linker to resolve.
- null-in-macro : This test used to crash. Now, the parser verifies that
a MACRO ends in ENDM, generating an error message if not.
Signed-off-by: AntonioND <[email protected]>
This patch isn't used because it's meant to be an optimization for
labels in the memory region 0x2000-0x20FF. That memory region doesn't
have anything special on the Game Boy, and there are no instructions
optimized to read or write from there, so it was probably meant for
another hardware that was supported by ASMotor in the past.
Signed-off-by: AntonioND <[email protected]>
This function produces a similar output to the other error handlers, including printing to stderr, and including a stack trace. However, ‘warning’ is displayed instead of ‘ERROR’, and the compilation does not fail.
This function is now used for the deprecation warnings, ensuring that these errors can be found.
Even though the bank number was read from the linkerscript and the
linker verified that each section could be mapped in the final rom, the
bank number was never actually set by the linkerscript parser.
Signed-off-by: AntonioND <[email protected]>
To make the behaviour of the linkerscript consistent, every section read
from an object file must have an unique name. This is needed as the
linkerscript uses the name of sections to place them and it expects
every section to have a different name.
This doesn't break compatibility with the old behaviour that allowed to
continue sections if they had the same name, bank number and starting
address. That's still allowed because `rgbasm` outputs a single section
if this functionality is used, it is transparent to `rgblink`.
Signed-off-by: AntonioND <[email protected]>
They are still working, they just output a warning.
`jp [hl]` is confusing as it may be thought that the CPU reads the value
pointed by hl and jumps to it.
`ldi a,hl` and `ldd a,hl` are also confusing as they load from the
address pointed by `hl`, the correct mnemonic should say `[hl]`.
Signed-off-by: AntonioND <[email protected]>
Print the name of each section along with the size, base and end
addresses. If a section is empty, don't print the end address, as it
can overflow if the base address is 0.
Signed-off-by: AntonioND <[email protected]>
Previously, some instances of the number of banks for each section remained hardcoded. These have been replaced with BANK_COUNT_* constants.
As a side-effect, this could fix a theoretical bug when using BANK(label) when the label is in a high SRAM bank (≥ 4).
Yay, more refactoring of the section assignment… This version of the linker will allocate sections by their alignment, and then by their size (largest first, in both cases).
In future, this may be improved by using dense packing (as suggested by #83).
Aligned sections can now be created with out_NewAlignedSection(). This information is stored in created object files, and read by the linker.
The names of each section are also included in the object file, enabling potential improvements to error messages in the future.
Instead of reading into a pre-sized buffer, this function now uses malloc to create a buffer, and resizes it if necessary.
This reduces the risk of memory issues if a long string (< 255 chars) was encountered.
Ensure that IF constructs, REPT blocks, and MACRO defintions are terminated with ENDC, ENDR, or ENDM respectively. If they are not, print an error and stop assembly.
As well as aiding a forgetful programmer, this reduces the risk of memory problems if the file ends less than four bytes after the block starts.
Deduplicates and generalises a lot of code in assign.c:
- Replace area_AllocAbs*AnyBank() with area_AllocAbsAnyBank() function
that accepts a section type parameter
- Replace area_Alloc*AnyBank() with area_AllocAnyBank()
- Replace FindLargest*() with FindLargestSection()
- Replace Assign*Sections() with AssignBankedSections()
- Add VerifyAndSetBank(), which enables bank checks (and addition with
BANK_*) to be centralised
- Refactor the initialisation of AssignSections(), removing some magic
numbers and only setting MaxAvail[i] once
- Overhaul the duplicated cases throughout AssignSections()
Previously, the copyrept() and copymacro() functions would halt their
first loop (in which they determine the length of the block)
prematurely, causing an underflow when setting len, eventually causing
memory issues.
Whilst this doesn’t solve the len underflow entirely (e.g. if the file
ends immediately without an ENDR/ENDM), it should help with this exact
scenario of null bytes (as #50).
Previously, if BANK is used when defining a section that’s not ROMX,
WRMAX, SRAM or VRAM, a second error message would appear, e.g. “(null)
bank value $1 out of range $5d to $0”.
This would appear due to the usage of uninitialised variables. This
change ensures that the uninitialised variables are not accessed when
using an invalid section.
This also silences compiler warnings about usage of uninitialised
variables.
GNU make actually looks for ‘GNUmakefile’, not ‘GNUMakefile’.
Consequently, GNU make would erroneously attempt to use the standard
makefile, instead of the GNU-specific one. This would cause an error
when attempting to import png.h, due to PNGFLAGS not being correctly
set.
Increase number of include paths that can be passed through the
command line interface. The previous number, 16, is only good enough
for small projects. 128 is still an arbitrary number, but it is harder
to reach.
The code that adds an include path to the array of paths doesn't check
the lenght of the path (which can cause overflows because of strcpy).
It doesn't check if the max number of paths has been reached, either.
This patch adds error messages for such cases, giving the user more
information than before and crashing the assembly instead of
continuing and failing when it can't find a file to include.
GNU Make 3.x doesn't support the "!=" syntax for shell assignment,
although 4.x does, BSD Makes do, and it has been submitted to POSIX
for possible inclusion in the standard. Unfortunately, GNU Make 3.x
is still in common use, so provide an alternative makefile (GNU Make
reads "GNUmakefile" instead of "Makefile" by default) that sets the
variables and then reuses the rest of the default Makefile.
Symbols are created when using a label in the wild, even if they aren't defined. Solely using a symbol as an argument to BANK() skips this, so the symbol is never created.
This evaluates the argument instead of trying to find a symbol. This way, symbols that don't exist are created when passed into BANK().
2014-02-01 21:14:56 -05:00
1236 changed files with 34143 additions and 11475 deletions
Please ensure that the three assets below work properly.
Once that's done, replace this text with the changelog, un-draft the release, and update the `release` branch.
By the way, if you forgot to update `include/version.h`, RGBASM's version test is gonna fail in the tag's regression testing! (Use `git push --delete origin <tag>` to delete it)
draft:true# Don't publish the release quite yet...
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>`__.
The documentation of this toolchain can be viewed online
`here <https://rgbds.gbdev.io/docs/>`__, it is generated from the man pages
found in this repository.
If you want to contribute or maintain RGBDS, and have questions regarding the code, its organisation, etc. you can find me `on GBDev <https://gbdev.io/chat>`__ or via mail at ``rgbds at eldred dot fr``.
1. Installing RGBDS
-------------------
The `installation procedure <https://rgbds.gbdev.io/install>`__ is available
online for various platforms. `Building from source <https://rgbds.gbdev.io/install/source>`__
is possible using ``make`` or ``cmake``; follow the link for more detailed instructions.
..code::sh
make
sudo make install
..code::sh
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install build
2. RGBDS Folder Organization
----------------------------
The RGBDS source code file structure somewhat resembles the following:
-``.github/`` - files and scripts related to the integration of the RGBDS codebase with
GitHub.
*``actions/`` - scripts used by workflow files.
*``workflows/`` - CI workflow description files.
-``contrib/`` - scripts and other resources which may be useful to users and developers of
RGBDS.
*``zsh_compl`` contains tab completion scripts for use with zsh. Put them somewhere in your ``fpath``, and they should auto-load.
*``bash_compl`` contains tab completion scripts for use with bash. Run them with ``source`` somewhere in your ``.bashrc``, and they should load every time you open a shell.
-``include/`` - header files for each respective C files in `src`.
-``src/`` - source code and manual pages for RGBDS.
* Note that the code unique to each RGBDS tool is stored in its respective subdirectory
(rgbasm -> ``src/asm/``, for example). ``src/extern/`` contains code imported from external sources.
-``test/`` - testing framework used to verify that changes to the code don't break or modify the behavior of RGBDS.
-``.clang-format`` - code style for automated formatting with |clang-format|_. The C code does not currently follow this style, but all C++ code should.
3. History
----------
- Around 1997, Carsten Sørensen (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
- 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.
- 2018, codebase relicensed under the MIT license.
- 2020, repository is moved to the `gbdev <https://github.com/gbdev>`__ organisation. The `rgbds.gbdev.io <https://rgbds.gbdev.io>`__ website serving documentation and downloads is created.
<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><ahref="expr_int.htm">Integer and Boolean expressions</a>
<li><ahref="expr_fix.htm">Fixed-point expressions and functions</a>
<li><ahref="expr_str.htm">String expressions, functions and formatting</a>
<li><ahref="ds.htm">Declaring variables in a RAM section</a>
<li><ahref="miscfunc.htm">Other functions</a>
</ul>
<hr>
<p>Last updated 02 July 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<p><dfn>DS</dfn> allocates a number of bytes. The content is undefined. This is the preferred method of allocationg space in a <ahref="section.htm">RAM section</a>. You can however also use DB and DW without any arguments.</p>
<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 <ahref="export.htm">exported and imported</a>. They don't change their value during the link process.</p>
<h1>See also:</h1>
<ul>
<li><ahref="expr_int.htm">Integer and Boolean expressions</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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>
<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>
<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>
<thscope="col">Name</th>
<thscope="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><ahref="symbols.htm">Symbols</a>
<li><ahref="expr_int.htm">Integer and Boolean expressions</a>
<li><ahref="expr_str.htm">String expressions, functions and formatting</a>
<li><ahref="miscfunc.htm">Other functions</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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>
<thscope="col">Operator</th>
<thscope="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 <ahref="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><ahref="symbols.htm">Symbols</a>
<li><ahref="expr_fix.htm">Fixed-point expressions and functions</a>
<li><ahref="expr_str.htm">String expressions, functions and formatting</a>
<li><ahref="miscfunc.htm">Other functions</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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>
<thscope="col">Character sequence</th>
<thscope="col">Meaning</th>
<thscope="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>
<thscope="col">Name</th>
<thscope="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><ahref="symbols.htm">Symbols</a>
<li><ahref="expr_int.htm">Integer and Boolean expressions</a>
<li><ahref="expr_fix.htm">Fixed-point expressions and functions</a>
<li><ahref="miscfunc.htm">Other functions</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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><ahref="expr_str.htm">String expressions, functions and formatting</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<li>The <ahref="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 <ahref="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 <ahref="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><ahref="fail.htm">FAIL and WARN</a> commands.</li>
<li><ahref="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 <ahref="equs.htm">string symbols</a> left the linecounter in a sorry state. Jeff Frohwein again.</li>
<li><ahref="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 <ahref="symbols.htm">symbol name</A>. Jeff....</li>
<li>The <ahref="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 <ahref="expr_str.htm">{} constructs</a></li>
<li><ahref="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><ahref="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 <ahref="pops.htm">POPS and PUSHS</A>. Jeff Frohweins doing again.<BR>
<ahref="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 <ahref="expr_int.htm">Gameboy graphics
integer (`)</A> using the <ahref="usage.htm">commandline</A> or the new <ahref="opt.htm">OPT</A> command. Cool idea by (surprise surprise) Jeff Frohwein.<BR>
Also, an option stack has been added. Look up <ahref="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>
<ahref="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>
<FONTSIZE="-1"><I><PALIGN=RIGHT>Last updated 21 September 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</A></P></I></FONT>
<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 <ahref="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><ahref="expr_str.htm">String expressions, functions and formatting</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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 <ahref="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><ahref="expr_str.htm">String expressions, functions and formatting</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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 <ahref="export.htm">EXPORT</a> at the same time.</p>
<p>Labels will normally change their value during the <ahref="../link.htm">link process</a> and are thus <em>not</em> constant.</p>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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>
<pid="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 <ahref="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 <ahref="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><ahref="shift.htm">SHIFT</a>
</ul>
<hr>
<p>Last updated 02 July 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<p>There's a few other functions that do various useful things:</p>
<table>
<caption>Other functions</caption>
<thead>
<tr>
<thscope="col">Name</th>
<thscope="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><ahref="section.htm">Sections</a>
<li><ahref="symbols.htm">Symbols</a>
<li><ahref="presym.htm">Predeclared symbols</a>
<li><ahref="if.htm">Conditional assembling</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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><ahref="opt.htm">Changing options while assembling</a>
</ul>
<hr>
<p>Last updated 20 July 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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><ahref="section.htm">Sections</a>
</ul>
<hr>
<p>Last updated 18 July 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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 <ahref="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><ahref="asm/expr_int.htm">Integer and Boolean expressions</a>
<li><ahref="asm/expr_fix.htm">Fixed-point expressions and functions</a>
<li><ahref="asm/expr_str.htm">String expressions, functions and formatting</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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 <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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><ahref="macro.htm#labelsuffix">\@</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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 <ahref="equ.htm">equated</a> symbols:</p>
<table>
<caption>Defined symbols</caption>
<thead>
<tr>
<thscope="col">Name</th>
<thscope="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>
<thscope="col">Command</th>
<thscope="col">Meaning</th>
</tr>
</thead>
<tr>
<td>RSRESET</td>
<td>Resets the <ahref="presym.htm">_RS</a> counter to zero</td>
</tr>
<tr>
<td>RSSET <i>constexpr</i></td>
<td>Sets the <ahref="presym.htm">_RS</a> counter to <i>constexpr</i></td>
</tr>
<tr>
<td>RB <i>constexpr</i></td>
<td>Sets the preceding symbol to <ahref="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 <ahref="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><ahref="expr_int.htm">Integer and Boolean expressions</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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 <ahref="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>
<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 <ahref="expr_str.htm">\@</a> for the sectionname and determines correct sectiontype etc as arguments for SECTION</p>
<h1>See also:</h1>
<ul>
<li><ahref="../link.htm">xLink</a> documentation
<li><ahref="expr_int.htm">Integer and Boolean expressions</a>
<li><ahref="expr_str.htm">String expressions, functions and formatting</a>
<li><ahref="pops.htm">POPS and PUSHS:</a> The section stack.
</ul>
<hr>
<p>Last updated 18 July 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<p>SETs are like <ahref="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><ahref="expr_int.htm">Integer and Boolean expressions</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<p><dfn>SHIFT</dfn> is a special command only available in <ahref="macro.htm">macros</a>. Very useful in <ahref="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><ahref="macro.htm">Macros</a>
<li><ahref="rept.htm">Automatically repeating blocks of code</a>
</ul>
<hr>
<p>Last updated 21 June 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<li><ahref="labels.htm">Label</a>. Used to assign a memory location with a name
<li><ahref="equ.htm">EQUate</a>. Give a constant a name.
<li><ahref="set.htm">SET</a>. Same as EQUate but with a subtle difference. You can change the value of a SET during assembling.
<li><ahref="rs.htm">Structures (the RS group)</a>. Define a structure easily.
<li><ahref="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><ahref="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><ahref="presym.htm">Predeclared symbols</a>
<li><ahref="export.htm">Importing and exporting symbols</a>
<li><ahref="purge.htm">Purging symbols</a>
</ul>
<hr>
<p>Last updated 02 July 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<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 <ahref="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 <ahref="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 <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<h1><abbrtitle="Rednex Game Boy Development System">RGBDS</abbr>—ASMotor General Information</h1>
<h2>Table of Contents</h2>
<ul>
<li><ahref="#license">License</a>
<li><ahref="#Author">The Author</a>
<li><ahref="#Introduction">Introduction</a>
<li><ahref="#Installation">Installation</a>
<li><ahref="#Documentation">The Documentation</a>
<li><ahref="#History">History</a>
</ul>
<h2id="license">License</h2>
<p>The <dfn>ASMotor</dfn> package (<ahref="asm.htm">xAsm</a>, <ahref="link.htm">xLink</a>, <ahref="fix.htm">RGBFix</a>, examples and <ahref="#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 (<ahref="asm.htm">xAsm</a>, <ahref="link.htm">xLink</a>, <ahref="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.
<p>Get the latest version from my web page at <ahref="http://www.matilde.demon.co.uk">http://www.matilde.demon.co.uk</a>
<h2id="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 <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<li><ahref="#operationtg"> Operation for Gameboy</a>
<li><ahref="#smallmode"> Operation for Gameboy small mode</a>
<li><ahref="#psion2"> Operation for Psion2 relocatable modules</a>
</ul>
<hr>
<h2id="history">History</h2>
<table>
<caption>The history of xLink</caption>
<thead>
<tr>
<thscope="col">Version</th>
<thscope="col">Dated</th>
<thscope="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><ahref="#usage">-s switch and mapfile option</A> added</td>
</tr>
<tr>
<td>1.03</td>
<td>23 Mar. 97</td>
<td>
<ul>
<li><ahref="#usage">Mapfile</A> now shows BSS, VRAM and HRAM areas</li>
<li>There was a bug regarding <ahref="#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. <ahref="#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>
<h2id="usage">Usage</h2>
<pre> xlink [options] linkfile</pre>
<p>Options are preceded by a hyphen (-) and go as follows:
z<b>HX</b> : Set the byte value (hex format) used for uninitialised data (default is ? for random)
</pre>
<h2id="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.
<h2id="operationtg">Operation for Gameboy (-tg)</h2>
<p><ahref="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 <ahref="fix.htm">RGBFix</a> to do this.
<h3id="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 <ahref="fix.htm">RGBFix</a> to do this.
<hr>
<p>Last updated 08 October 1997 by <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
<p>I developed the RGB0 fileformat mainly because I needed a suitable dataformat to hold the output from <ahref="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>
<h2id="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
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>
<h2id="rpn">Rpn Data</h2>
<p>Expressions in the objectfile are stored as <abbrtitle="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>
<thscope="col">Byte value</th>
<thscope="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 <ahref="mailto:[email protected]">Carsten Sorensen</a></p>
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.