Compare commits

...
506 Commits
Author SHA1 Message Date
ISSOtm 76c1995559 Fix CI 2021-04-01 11:38:07 +02:00
Rangi ae84570f04 Revise RGBASM manual 2021-03-31 18:35:09 -04:00
Rangi 094a31ef8c Update RGBASM command-line manual 2021-03-31 18:17:18 -04:00
ISSOtm 291dcf3b6c Update RGBASM manual 2021-04-01 00:11:41 +02:00
Rangi a890bd072b Fix "INCBIN"
Examples: (...s are optional)

ld [b @:...] = "Dockerfile"
ld [b @:...] = "Dockerfile"[451:...]
ld [b @:...] = "Dockerfile"[23:5]
ld [b @:5] = "Dockerfile"[23:...]
2021-03-31 18:06:14 -04:00
Rangi 2f6c808ccb Revise instruction reference 2021-03-31 17:59:12 -04:00
ISSOtm e80907abd0 Update instruction reference 2021-03-31 23:26:57 +02:00
Rangi 25d39155d3 Support ld a, a±c±LOW(bc) as well as ld a, a±c±c 2021-03-30 12:36:11 -04:00
Rangi 77021d229b Support ld [c], a and ld a, [c] 2021-03-30 12:02:29 -04:00
Rangi 1b250b90b2 Implement ds <len> ==> ld [b @:<len>], ? 2021-03-30 11:54:39 -04:00
Rangi e2b4723489 Fix lexing @ 2021-03-30 11:52:25 -04:00
Rangi 2507413162 Fix lexing a., b., etc 2021-03-30 11:41:44 -04:00
Rangi e023a84d04 Allow 'ld a, a±c±<r8>' or 'ld a, a±<r8>±c' for adc/sbc 2021-03-30 11:27:19 -04:00
Rangi 34c127d9c3 Allow ld [b @:<len>] = "file.bin"[<ofs>:...] 2021-03-30 10:51:48 -04:00
Rangi 9a930988c2 Implement db, dw, dl, ds, and INCBIN with ld
To do: let the `b` in `ld [b @]` be optional, and allow
`ld [b @:<len>] = "file.bin"[<ofs>:...]`
2021-03-30 10:47:05 -04:00
Rangi 8c4204c542 Make 'w' and '...' tokens, and make '@' a separate token
Now '@' is valid as a relocexpr_no_str, in 'BANK(@)', and
in 'DEF(@)', but not in general T_ID or T_LABEL contexts

This will make it easier to implement INCBIN with 'ld'
2021-03-30 10:17:09 -04:00
Rangi 663c1930ec Factor out 'ld a, a+c+' and 'ld a, a-c-' prefixes
This fixes all the shift/reduce and reduce/reduce conflicts
2021-03-30 09:57:08 -04:00
Rangi 30ccf43f44 Factor out individual 'ld <r16>,' prefixes 2021-03-30 09:43:34 -04:00
Rangi fdc17adbcb Factor out common ld a, prefix 2021-03-30 09:19:58 -04:00
Rangi cc196954f3 Consolidate some parser rules with reg_ss and reg_r
There are now 5 shift/reduce conflicts and 3 reduce/reduce conflicts
2021-03-29 20:52:24 -04:00
Rangi 55b6cfff84 Prevent GitHub Actions from running any workflows 2021-03-29 19:50:13 -04:00
Rangi 1fc73b04eb Parse ld instructions as discussed
There are 13 shift/reduce conflicts, so some instructions
may need different formats.

This also does not yet implement `db`, `dw`, `dl`, `ds`,
or `INCBIN` using `ld`.

The `lexerState->nextToken` solution to lexing something
like "a.2" as three tokens instead of one identifier
is taken from the first commit in rgbds PR #799.
2021-03-29 19:42:18 -04:00
Rangi d05703c692 Release 0.5.0-rc2 2021-03-28 17:15:44 -04:00
Rangi 5dbfafcc55 Update man page copyrights to 2021 2021-03-28 16:37:15 -04:00
Rangi a265b85d9d Report "1 error", not "1 errors", when assembly is aborted
This matches other such pluralized error messages
2021-03-28 15:55:32 -04:00
Rangi 28abf03c0a Output USED space, not FREE space, in the .map file
Fixes #808
2021-03-28 15:49:44 -04:00
Rangi 7e7f92f18c Assign section locations to all UNIONs/FRAGMENTs
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
2021-03-28 15:21:17 -04:00
Eldred Habert 7461170956 Add LOAD FRAGMENT pc test (#800)
Reproduces a reported problem, fix pending
2021-03-28 15:11:20 -04:00
Rangi 57d966d6e0 Merge pull request #804 from Rangi42/normal-backslash
Backslash in normal lexer mode must be a line continuation
2021-03-26 13:33:11 -04:00
Rangi 17752d7094 Backslash in normal lexer mode must be a line continuation
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'".
2021-03-26 13:23:05 -04:00
ISSOtm 4216f0a9b0 Init top-level fstack node line number
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.
2021-03-25 11:26:58 +01:00
ISSOtm e3fde986ad Remove hashmap collision warning
It was only used to check hashmap collision rate in the wild,
but it no longer has a purpose and produces spurious messages
2021-03-23 21:34:08 +01:00
Rangi aa99ed056c Do not evaluate an untaken ELIF's condition
Fixes #764
2021-03-23 16:20:24 +01:00
ISSOtm 46d6652df1 Fix missing .sym/.map symbols in SECTION UNION/FRAGMENTs
Only the first "slice"'s symbols were considered, forgetting some symbols
2021-03-22 23:23:06 +01:00
ISSOtm 5406674cdd Install groff to build PDFs correctly in CI 2021-03-20 02:09:47 +01:00
ISSOtm 5d2e2e2182 Make docs update script also produce PDFs
See rgbds-www#12
2021-03-20 01:53:26 +01:00
ISSOtm a929f36bc5 Replace UTF-8 hyphens with ASCII ones in man pages 2021-03-20 01:25:17 +01:00
ISSOtm bdb84a901f Use sub-sections for the different symbol types
This will make them appear in the ToC, and generate HTML anchors for them
2021-03-19 11:04:22 +01:00
Rangi 093631ca0b Revise rgbasm(5) string symbol documentation
Clarify the differences between EQUS expansion and {interpolation}
2021-03-19 01:48:36 +01:00
Rangi 7e127a4e52 Don't expand string symbols in MACRO and FOR symbol names
Explicit {interpolation} can still achieve this, but
to match DEF, REDEF, and PURGE, these new directives that
define symbols do not expand string EQUS.
2021-03-19 01:48:36 +01:00
Rangi b8093847dc New definition syntax with leading DEF keyword
This will enable fixing #457 later once the old
definition syntax is removed.
2021-03-19 01:48:36 +01:00
Rangi 8d1b56bcf5 rgblink identifies patches' PC sections after reading all sections
Fixes #794
2021-03-18 23:53:54 +01:00
ISSOtm 5fb7fcf461 Fix description of rgbgfx -h
The old description was backwards and mostly confusing.
2021-03-18 15:35:01 +01:00
Rangi ee900ae7a3 Add a missing newline to a verbosePrint 2021-03-17 20:53:25 -04:00
ISSOtm 3ca58e13dc Fix verbose messages claiming non-existent errors
They were confusing when trying to debug other things
2021-03-14 18:52:16 +01:00
ISSOtm aaa4e17454 Add verbose messages for early exit from -MG
Should help debugging Make invocations
2021-03-14 18:28:05 +01:00
daid a81d383f75 Alignment mask was incorrectly checked for 1 instead of 0
This caused an `ALIGN[1]` to be ignored.
2021-03-11 13:24:59 +01:00
ISSOtm 60019cf476 Fix a bunch of Clang warnings
As reported by #789
Should avoid relying on 32-bit int (for implicit conversions)
and account for more extreme uses of RGBDS.
2021-03-10 10:56:57 +01:00
ISSOtm 5a6a44cbc1 Fix master documentation updater
Its path was not synced with a recent change
2021-03-10 01:15:51 +01:00
ISSOtm b61a187b19 Add forgotten __RGBDS_RC__ symbol 2021-03-10 01:09:18 +01:00
ISSOtm 6382f13647 Release 0.5.0-rc1 2021-03-10 01:04:23 +01:00
ISSOtm 714d39c86f Make some INCBIN errors non-fatal 2021-03-10 01:02:45 +01:00
ISSOtm f11241c2ae Add INCBIN tests 2021-03-10 01:02:45 +01:00
daid cb47ac8b97 Change the start position check on INCBIN
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)
2021-03-10 01:02:45 +01:00
ISSOtm 028e7af7d1 Prepare release candidates
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
2021-03-10 00:06:32 +01:00
ISSOtm e141da1d94 Compute fallback version string at compile time 2021-03-09 23:59:34 +01:00
ISSOtm 35367282e4 Add workflow to auto-prepare a release
Just push a tag beginning with "v" and a number to trigger it
2021-03-09 22:58:42 +01:00
ISSOtm 4c0fa6732e Fix release doc creation workflow 2021-03-09 22:58:42 +01:00
ISSOtm e9d9a44687 Make release doc update also register docs 2021-03-09 22:58:42 +01:00
ISSOtm 611bd46e0b Ignore CRLF vs LF for syntax error test check 2021-03-09 22:58:32 +01:00
ISSOtm e67254093e Delete version test if stale 2021-03-09 22:58:00 +01:00
ISSOtm 3ce3d2f662 Explicitly force tested projects to use tested bins 2021-03-09 22:56:59 +01:00
ISSOtm 3da9d81071 Ignore DLLs too
Since you may want to put them next to the EXEs here
2021-03-09 22:46:17 +01:00
Rangi 88646093ca Swap the Name and Type columns in Predeclared Symbols 2021-03-05 17:00:06 -05:00
Rangi 0a0427afbb windows-xbuild CI uses ubuntu-18.04 for its gcc 7.3.0 (#784)
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
2021-03-05 11:27:12 -05:00
Rangi 88048cdcd7 Clarify the character encoding example in rgbasm.5 2021-03-05 10:08:43 -05:00
Rangi c878ff8775 Report slack totals at the end of the .map file (#781)
Fixes #777
2021-03-05 08:53:27 -05:00
dannye a4049a3f1b rgbasm(5): Clarify charmap behavior (#558) 2021-03-05 13:16:49 +01:00
Rangi 8a75cc5051 Test an indented anonymous label 2021-03-03 12:26:35 -05:00
Rangi b674c5fcaa Comment refers to "built-in" symbols 2021-03-03 10:35:47 -05:00
daid a6d3df7ac9 Put all local symbols in object/sym/map files (#774)
* 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;
2021-03-03 10:59:51 +01:00
Rangi 365484ef18 Factor out handleCRLF()
This logic repeats ten times
2021-03-03 10:03:52 +01:00
Rangi 5e2bd35239 Factor out a 'plain_directive' parser rule similar to the reverted 'last_line'
Also expand on the comment explaining how the EOF-newline hack affects the parser
2021-03-02 20:46:17 -05:00
Rangi 6655e04ef0 Restore the "EOF-newline" lexer hack
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
2021-03-02 16:53:56 -08:00
ISSOtm 40c6b840f8 Add tests for certain directives at EOF without a newline 2021-03-02 16:53:56 -08:00
daid 5d6e0677d9 Fix error-related issues (#773)
* 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
2021-03-02 16:34:19 +01:00
Rangi 56071599e7 Allow trailing commas in bare lists
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
2021-03-02 11:48:20 +01:00
Rangi c637447d5d Make the "db/dw/dl directive without data in ROM" warning more specific
Also use uppercase for DB/DW/DL to be consistent
2021-03-02 11:48:20 +01:00
Rangi ac2cefdd87 Refactor some math functions into a shared file for rgbasm and rgblink
Fixes #769

Fixes #770
2021-03-02 11:40:03 +01:00
Rangi 0774f5eb9d Rename math.c/mymath.h to fixpoint.c/.h
This also changes the functions' prefix
from "math_" to "fix_".
2021-03-02 11:40:03 +01:00
Rangi 76d8862900 Refactor part of getSection into createSection
getSection validates its parameters and calls
either mergeSections or createSection.
2021-02-28 16:12:03 -05:00
Rangi 1dafc1c762 Allow empty macro arguments, with a warning
Fixes #739
2021-02-28 10:38:49 -08:00
Rangi 63d15ac8c9 append_yylval_tzString should always evaluate its argument
Fixes #762
2021-02-28 10:38:49 -08:00
Rangi 1f579deaff Trim right whitespace from macro args before warning about length 2021-02-28 10:38:49 -08:00
Rangi fad48326f8 Support /* block comments */ in macro arguments
Fixes #746
2021-02-28 10:38:49 -08:00
Rangi e7d6ddf593 Fix linking tiny overlay files (#755)
* 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
2021-02-24 23:04:51 -05:00
Rangi 953f79c0d9 Support 'MACRO mac' as well as 'mac: MACRO' for defining macros
The new syntax is used in documentation, but
the old syntax is not yet deprecated.
2021-02-25 04:42:35 +01:00
Rangi 3c5e1caa7c Disallow "." as a local label
Fixes #760
2021-02-25 04:40:42 +01:00
Rangi d4028fff10 Prevent ELIF or ELSE after an ELSE
Fixes #749
2021-02-25 04:39:49 +01:00
Rangi dd892d61d8 Correct rgbasm(5) about whitespace before labels
Also rephrase some more label-related documentation
2021-02-23 15:31:29 -05:00
Rangi a09f2d4115 Test an indented macro label 2021-02-23 14:48:27 -05:00
Eldred Habert dafef5a953 Remove column 1 restriction for labels with colons (#635)
Partial fix for #457
2021-02-23 14:42:24 -05:00
dannye 929e2a4490 rgbasm: Report conflicting file/line number for duplicate sections 2021-02-23 20:08:59 +01:00
dannye cc1129093d Add duplicate-section test 2021-02-23 20:08:59 +01:00
ISSOtm 72911ada2d Prevent non-numeric symbol from overriding refs
Fixes #751
2021-02-22 13:00:25 +01:00
Rangi 037bc7abb3 Add an rgblink test case for an $8000-byte ROM0 section with -t 2021-02-21 16:30:02 -05:00
Rangi 5fd636ac4b Implement floored / and divisor-sign % operators (#745)
Fixes #703
2021-02-21 16:14:44 -05:00
Rangi a6d844a9a5 Add more test cases for IF, REPT, and MACRO (#748) 2021-02-19 19:34:21 -05:00
ISSOtm bee62076c6 Allow ENDC at EOF without a newline 2021-02-20 00:51:33 +01:00
ISSOtm cd072d5e6a Add assertion check for potential UAF trigger
It actually currently triggers if an INCLUDE directive is given at EOF,
but #742 will fix that.
2021-02-19 16:53:30 +01:00
ISSOtm 6ef3ee1391 Give void* ptr to %p formatter
Silences a format type mismatch warning
2021-02-19 16:53:26 +01:00
ISSOtm c29b616f93 Fix forgotten initialization of lexerState->isReferenced 2021-02-18 16:33:06 +01:00
Rangi 39c179aa32 Fix missing newline in a dbgPrint 2021-02-17 13:14:02 -05:00
Rangi 5c1ae4ce22 Shorter quine test cases 2021-02-17 11:51:21 -05:00
Rangi efbfeca292 Avoid two peek(1) calls when lexing """multi-line strings""" 2021-02-17 10:36:36 -05:00
Rangi 7dd34f1572 Format INT32_MIN as '-2147483648', not '--2147483648' 2021-02-17 09:48:40 -05:00
Rangi 748e7dd4c7 Fix calculation of 2**30
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.
2021-02-17 09:25:02 -05:00
Rangi d049ffc0f0 Handle string literals within macro arguments (#685)
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
2021-02-16 22:44:25 -05:00
Rangi 8c0275480c Allow ds to take multiple values to repeat for a count (#725)
Fixes #722
2021-02-16 22:01:23 -05:00
Rangi 76d6ef8695 Implement LOAD UNION and LOAD FRAGMENT
Fix #632
2021-02-17 03:42:06 +01:00
Rangi c67a696a87 Use macros to convert between radians and fixed-point 65536ths 2021-02-16 18:07:05 -05:00
Rangi ee20d9010e Make @ relative to the start of a ds even at link time
Fix #737
2021-02-16 22:47:07 +01:00
Rangi 2bc12447e2 Update rgbds(5) object file format documentation (#740) 2021-02-16 16:36:37 -05:00
Rangi cb61da8842 -Wmacro-shift warns about shifting macro arguments too far (#741)
Fixes #735
2021-02-16 16:31:01 -05:00
ISSOtm 122ba6eba5 Update deprecated feature examples
Those have been removed, lol
2021-02-16 22:09:31 +01:00
Rangi dddff0f450 Cannot start a new section that's already on the stack
This is only relevant for FRAGMENT or UNION sections, since
normal ones would fail with "Section already defined previously".

Fixes #730
2021-02-16 21:51:48 +01:00
Antonio Vivace a919f922a1 Add FUNDING.yml to show the Sponsor button on the repository 2021-02-16 21:23:27 +01:00
Rangi 8f20620c16 Allow shifting macro arguments by a negative amount
Fixes #733
2021-02-14 16:21:00 +01:00
Rangi 96bce05be2 Newlines in multi-line strings update the line number
This affects error and warning messages, and dbgPrint
2021-02-14 16:16:52 +01:00
Rangi fc2bf3d11d Prefer sizeof($$) to MAXSTRLEN + 1
This makes `strsubUTF8` similar to `strrpl` and `strfmt`
2021-02-14 16:16:52 +01:00
Rangi 8415ce3ed0 Correct the keywordDict size
The stale keywords XDEF and GLOBAL were removed,
so there can be fewer keyword nodes.
2021-02-14 16:16:52 +01:00
Rangi ebb5aab6db Correct some comments
nPCOffset no longer exists, and the lexer only
returns T_NEWLINE for EOF in raw mode.
2021-02-14 16:16:52 +01:00
Rangi 464a3a4892 Separate extern getopt implementation from the unistd.h one
Fixes #710
2021-02-12 00:29:21 +01:00
ISSOtm 88e1cc7302 Make EOF token name consistent across Bison versions
The "end of file" name apparently only became a default recently
2021-02-11 13:04:43 +01:00
ISSOtm b3c0db218d Remove "EOF-newline" lexer hack
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.
2021-02-11 12:48:37 +01:00
ISSOtm 76446e6d00 Change behavior of merging FRAGMENTs to constrain each fragment individually
Additionally, remove the deprecated merging of non-fragment SECTIONs
2021-02-10 10:19:16 +01:00
ISSOtm 6623b1dc45 Fix CI on macOS
Apple supplies version 2.3 (from 2006!!), which doesn't support `%empty`.
2021-01-23 13:45:12 +01:00
ISSOtm 70bbb098d3 Remove stale keywords
They were removed from the grammar, but not the lexer
2021-01-23 00:05:56 +01:00
ISSOtm 1926065377 Enable Bison warnings
-Wall should be old enough.
Also use %empty instead of comments
2021-01-23 00:05:56 +01:00
Rangi e3d355d976 Attempt to recover from syntax errors with bison
Fixes #595
2021-01-22 15:54:24 +01:00
ISSOtm a679e02246 Get rid of asm.h and localasm.h
No need to make them global
2021-01-22 13:34:16 +01:00
ISSOtm 592e9b3725 Reorganize and comment better main() 2021-01-22 11:09:27 +01:00
ISSOtm effc58241d Rework defining variables on command-line
Avoids allocating memory
Detects CLI errors even when failing to open file
Reports symbols as defined on command-line instead of input line 0 (!?)
2021-01-22 11:03:43 +01:00
ISSOtm 3697065afc Add asm/opt.c to CMakeLists
Fixes compiling with CMake
2021-01-22 11:01:33 +01:00
ISSOtm fa0fa4d5ac Significantly overhaul OPT code
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
2021-01-22 10:41:09 +01:00
ISSOtm 5acc48fa54 Error out when given several input files
Also rename tzMainFile
2021-01-22 09:44:41 +01:00
ISSOtm 1487eebe79 Remove time counter
Nobody uses that, and it requires running extra code for each line
2021-01-22 08:51:57 +01:00
ISSOtm 993c034039 Avoid using EXPAND_AND_STR with external defines
There is no guarantee that they are purely numeric, use the values instead
2021-01-22 08:51:35 +01:00
ISSOtm 09f16bda4a Use putc instead of fputc
Also rename some functions for consistency
2021-01-22 08:32:28 +01:00
ISSOtm 41d544a4eb Rewrite RGBFIX
- 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
2021-01-20 21:22:55 +01:00
Rangi f28b4abafc Fix a potential buffer overflow in strrpl
This caused an error using clang with -O3 -flto
2021-01-20 10:21:53 +01:00
ISSOtm ca1c934629 Have CMake use specified compiler in CI, not system default
Otherwise it's just GCC on Linux and Clang on macOS...
2021-01-19 16:35:06 +01:00
Rangi d5a00cf634 Comment cites the string hash algorithm (djb2)
"If you just want to have a good hash function,
and cannot wait, djb2 is one of the best string
hash functions I know."
2021-01-19 15:03:22 +01:00
Rangi fb39c3a70e Consistently refer to "directives", not "pseudo-ops"
Some docs and warnings already referred to SECTION and
db/dw/dl "directives", but others used "pseudo-ops".
2021-01-19 15:03:22 +01:00
ISSOtm 15ec6efc28 Fix missing newline in charmap override warning 2021-01-17 20:13:51 +01:00
Rangi 93d83e17dc Don't override bison's internal 'yytnamerr' function
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'.
2021-01-15 11:51:31 +01:00
Rangi df16e64fc6 Handle MACRO and REPT/FOR bodies differently
Fixes #697
2021-01-15 02:16:37 +01:00
Rangi a4ebb87858 Add Rangi to contributors 2021-01-14 18:36:10 +01:00
Rangi 5ef8e0a1f6 Use an IELR parser if available 2021-01-14 18:36:10 +01:00
Rangi eb4952c188 Use more verbose syntax error messages
Fixes #385
2021-01-14 18:36:10 +01:00
ISSOtm 57b734a7df Reinstate RL into the _RS family
Removal of colon-less labels lifted the grammar ambiguity that
prevented `RL` from being usable as a variable declarator.
Thus, reinstate its functionality.
2021-01-11 01:38:03 +01:00
ISSOtm 5be1c0da62 Fix intra-section ALIGN not computing offset correctly 2021-01-09 23:29:08 +01:00
ISSOtm b598911e96 Enable LTO in release builds
Fixes #693
2021-01-09 20:31:15 +01:00
Rangi cab9cb06a3 Store IF depth relative to each fstack context
This disallows starting/ending an IF inside an
INCLUDEd file or a macro expansion
2021-01-09 20:12:14 +01:00
Rangi 62bea23c49 Implement BREAK to exit REPT and FOR loops
Fixes #684
2021-01-08 21:13:23 +01:00
Rangi 7ce5cf1595 Convert floating to fixed point by rounding, not truncation
Fixes #678
2021-01-04 21:23:43 +01:00
Rangi 7e3fc1db03 Fix Actions CI for MSVC
Fixes #616
2021-01-04 02:01:25 +01:00
Rangi 77279984a5 Implement STRRPL
Fixes #660

STRRPL(str, "", new) does nothing
(warn about it with -Wempty-strrpl)
2021-01-04 00:20:35 +01:00
Rangi 669a392fcd Revise the rgbasm(5) docs 2021-01-02 08:29:57 +01:00
ISSOtm 51ce0b038a Remove removed features from documentation 2021-01-02 02:47:13 +01:00
ISSOtm bd244e6865 Remove deprecated features
Trimming off the fat!
- GLOBAL and XDEF keywords
- Colon-less global labels
- *-comments
2021-01-02 02:42:44 +01:00
Rangi a70ecba06f Implement PRINT and PRINTLN (#672)
Fixes #669
Closes #368
Closes #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
2021-01-02 02:37:32 +01:00
Rangi 9d2d5cfcfe Implement REDEF to allow redefining EQUS string equates
Fixes #677
2021-01-02 01:49:00 +01:00
ISSOtm 18f3c8ff9a Un-document deprecated _PI 2021-01-02 01:43:49 +01:00
Rangi 895ec5564d Update mathematical functions (#675)
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
2021-01-02 01:39:20 +01:00
Rangi 7bb6f71f0b Change FOREACH to FOR (#680) 2021-01-02 00:46:26 +01:00
Rangi 10e3f1a02b Deprecate built-in _PI
Fixes #670
2021-01-01 19:18:17 +01:00
Rangi 2a9d52871b Make dbgPrint in lexer.c report the correct colNo (#676)
Fixes #656
2021-01-01 18:44:47 +01:00
ISSOtm c4fb5591ee Fix size of unterminated REPT/FOREACH blocks
Do not "uncapture" ENDR if it was not read in the first place
2020-12-30 15:52:24 +01:00
Rangi c0ce1da4c3 Implement STRFMT and more printf-like format specifiers for string interpolation (#646)
Fixes #570
Fixes #178

Use errors for inapplicable format spec flags instead of -Wstring-format
2020-12-29 22:53:15 +01:00
ISSOtm aa27e714d4 Make Bison version detection more portable
- 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.
2020-12-29 22:31:15 +01:00
Rangi 6874f694e5 Implement FOREACH (#658)
This acts like `REPT` with a variable automatically
incremented across a range of values

Fixes #432
2020-12-29 21:30:42 +01:00
Rangi 3690546795 make checkpatch and make checkcodebase check the same files
Only check src and include (not test), and
exclude src/extern and include/extern.
2020-12-29 20:27:00 +01:00
ISSOtm 7bc42d468b Clean up temp test files even if interrupted
Avoids "tmp.*" piling up in /tmp
2020-12-26 14:38:04 +01:00
ISSOtm 097999cad3 Prevent tests from running if RGBDS hasn't been built
Prevents a *lot* of spurious errors due to files not generating
2020-12-26 14:26:50 +01:00
ISSOtm f82edaa7ec Make gbdiff.bash handle CRLF sym files gracefully
Additionally, reduce the amount of lines piped through `cut`,
improving performance
2020-12-26 02:47:04 +01:00
ISSOtm d8e8b796e7 Update tested projects to latest commits
Compatibility fixes, etc.
2020-12-26 02:02:38 +01:00
ISSOtm 900fd8cabc Improve gbdiff script
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
2020-12-26 01:44:45 +01:00
ISSOtm c20ac35074 Refactor readString
Much more readable, and avoids `peek(nz)`
2020-12-19 13:02:05 +01:00
Rangi 255b8bf9ba Implement """triple-quoted""" multi-line strings
Fixes #589
2020-12-19 12:34:32 +01:00
Rangi ad6f17cd93 Support SOURCE_DATE_EPOCH for reproducible builds
See https://reproducible-builds.org/docs/source-date-epoch/

Fixes #286
2020-12-19 01:09:45 +01:00
Rangi 063a22ddf9 LOAD blocks cannot create a ROM section
Fixes #576
2020-12-19 00:58:54 +01:00
Rangi 1d9cc01ae1 Macro arguments within a string literal are read into the string, not expanded
Fixes #643
2020-12-15 21:28:15 +01:00
Rangi f31deb5010 Fix STRUPR and STRLWR after 5aabb915ec
Fixes #647
2020-12-15 20:18:45 +01:00
Rangi 0956d300c4 Document \# 2020-12-14 10:48:03 +01:00
ISSOtm 4ef490f3cb Avoid interpreting Liquid in doc pages
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.
2020-12-14 10:35:30 +01:00
ISSOtm 8f2a894b88 Add anonymous labels
Fix #497
2020-12-14 10:14:40 +01:00
Rangi 0e40543757 Implement \# to expand to all unshifted macro arguments
Fixes #596
2020-12-14 00:12:36 +01:00
Rangi ce58f6d6be Allow {symbol} interpolation outside of strings
Fixes #629

Closes #631
2020-12-13 23:53:16 +01:00
ISSOtm 5aabb915ec Allow STRCAT to take any number of args
Fixes bullet point 1 of #625
2020-12-12 23:46:32 +01:00
ISSOtm 0d9de01f9d Make charmap-converting a non-UTF8 string non-fatal 2020-12-12 14:16:50 +01:00
ISSOtm f5b0eae9cd Remove custom action code when equivalent to default
Enables Bison to better reason about it, and should improve performance
2020-12-12 12:22:36 +01:00
Rangi e6552064bf Specify rgbfix --mbc-type by name
This supports the names listed in Pan Docs:
https://gbdev.io/pandocs/#_0147-cartridge-type
Spaces may be replaced with underscores.

It also supports "ROM" for "ROM ONLY".
2020-12-12 01:53:42 +01:00
Rangi 861cb552c4 discardBlockComment sets lexerState->disableMacroArgs = true, like discardComment 2020-12-12 01:34:01 +01:00
ISSOtm 417cceb0de Document dw and dl with strings 2020-12-11 11:02:20 +01:00
Rangi 165bd8cb71 Allow 'dw' and 'dl' to apply to characters of strings
Fixes #568

The old behavior of `dw "string"` can be replicated with `dw ("string")`; likewise for dl
2020-12-11 11:02:20 +01:00
ISSOtm e54e02dc77 Correct underscore-in-number documentation
No radix actually allows underscores at the beginning of a literal
2020-12-10 16:01:18 +01:00
ISSOtm 2bf3b08d76 Document underscores in numeric literals 2020-12-10 15:40:59 +01:00
ISSOtm 21b58b08b8 Fix not shifting CRLF at end of raw lines
Fixes line reporting errors on Windows
2020-12-10 15:37:50 +01:00
Rangi af530859f0 Allow underscores in numeric literals
Fixes #539

Changes \@'s output to start with "_u", not "_", so it will be valid within labels but not numerics
2020-12-10 15:34:21 +01:00
Rangi 58739b0bf2 Implement STRRIN, like STRIN but searching from the right 2020-12-10 15:32:17 +01:00
ISSOtm 3e4c2fe712 Avoid error with old Bison versions
`api.token.raw` is only defined starting with Bison 3.5
Since it's not essential, define it on the command-line iff the Bison
version is sufficient.
2020-12-10 15:13:45 +01:00
ISSOtm bdfce25db0 Avoid running version test when git describe fails
Can happen when not enough history has been fetched, notably in our CI
2020-12-10 13:43:22 +01:00
ISSOtm 2b6d9cd1e0 Avoid using yytoken_kind_t
Apparently it was added in a fairly recent Bison version...
2020-12-10 13:32:18 +01:00
ISSOtm bf789dd7b3 Add automated test for version consistency
Automatically check that the version number constants
(__RGBDS_MAJOR__ etc.) match `rgbasm -V`
Should avoid the problem with 0.4.2's release...
2020-12-10 12:22:29 +01:00
ISSOtm 9b6f01047c Enable raw token types
Removes one layer of indirection for the parser, and helps remove all literals from the grammar

The latter preparing the next change
2020-12-09 21:22:05 +01:00
ISSOtm 3fe2fa43bb Switch to GNU Bison as a dependency
First step for #595
2020-12-09 20:30:31 +01:00
ISSOtm ede982b50a Bump patch level appropriately
*HEADDESK*
2020-12-09 20:30:31 +01:00
ISSOtm 319d775c13 Add CI script to create docs on new releases 2020-12-09 16:08:43 +01:00
ISSOtm 44124319a6 Work around old Bison versions not forward-declaring yyparse
Notably, macOS still ships 2.3 (from 2008)...
Should fix #214
2020-12-09 16:00:22 +01:00
ISSOtm 462fd7539c Prohibit nested macros
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.
2020-12-09 10:44:39 +01:00
ISSOtm f16e34b804 Fix captures beginning in expansions
Fixes #590
2020-12-09 09:54:55 +01:00
ISSOtm c3ccdc548e Remove unnecessary flex dep from Dockerfile 2020-12-09 09:42:19 +01:00
ISSOtm fd721ca480 Document optional RB/RW/RL argument 2020-12-09 09:39:46 +01:00
ISSOtm eac365aef0 Allow argument to rb, rw and rl to be optional
Fixes #617
2020-12-09 09:31:47 +01:00
ISSOtm 4de6266442 Add explanation of how EXPORT works
Fixes #608
2020-12-08 21:07:24 +01:00
ISSOtm 213d985e17 Fix incorrect "sliced" INCBIN causing memory leaks
Oh, how I miss RAII...
2020-11-29 12:47:53 +01:00
ISSOtm de76dcb8fb Fix possible segfault from -MT and -MQ
Happened only if `malloc` failed, so...
2020-11-29 12:47:53 +01:00
Eldred Habert 30fb6bde5e Merge pull request #615 from ISSOtm/find-sym
Create specialized symbol finder functions
2020-11-25 15:17:34 +01:00
ISSOtm 4f842a1248 Create specialized symbol finder functions
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.
2020-11-21 01:06:17 +01:00
ISSOtm cc4d455b8a Add test for empty local label component 2020-11-21 00:58:40 +01:00
Eldred Habert 0bb5efebfd Merge pull request #610 from daid/stdin
Allow rgbasm and rgblink to use stdout and stdin as input and output
2020-11-08 01:20:44 +01:00
ISSOtm b6bf7ae620 Fix RGBLINK incorrectly reading file stack nodes
This caused node IDs to mismatch, yielding possibly corrupted file stacks
Worst part is, the docs mentioned the reading order had to be reversed...
2020-11-04 02:52:06 +01:00
ISSOtm dc96cc6d1e Add zsh completion scripts
Can't get bash ones to work, but these do.
2020-11-03 23:29:47 +01:00
daid 642daf1a76 Update main.c 2020-11-03 13:33:57 +01:00
daid 84edfb3d88 Update output.c 2020-11-03 13:33:02 +01:00
Daid 7e620bff81 Allow rgbasm and rgblink to use stdout and stdin as input and output 2020-10-26 20:28:15 +01:00
ISSOtm 0c55703438 Improve helpers.h
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
2020-10-26 15:19:31 +01:00
ISSOtm 6c57ad2226 Have make clean delete parser artifacts
Forgot to update the names there
2020-10-25 16:26:58 +01:00
ISSOtm 9028fb5391 Fix mistakes in RGBDS man pages
As reported by `mandoc -Wall`
2020-10-23 01:02:59 +02:00
ISSOtm 12dc49b60a Make page processor print usage only after reporting all bad opts 2020-10-23 00:40:05 +02:00
Eldred Habert 7e1d20acdf Merge pull request #607 from anderoonies/inline-comment-#537
handle inline c-like comments in lexer
2020-10-19 19:36:49 +02:00
anderoonies 5230104852 documentation for block comments 2020-10-19 18:05:37 +02:00
anderoonies 55be77be69 discard block comments delimited with /* */ 2020-10-15 12:42:53 -04:00
Eldred Habert 42b3a17356 Merge pull request #602 from NieDzejkob/shiftstorm
Report only one error when invalid shift has argument
2020-10-13 15:48:16 +02:00
Jakub Kądziołka 4e1d79081c Improve error message for negative shift arguments 2020-10-13 15:42:16 +02:00
ISSOtm 4ce4fdec71 Mention setting CMAKE_BUILD_TYPE to Release when using CMake
Not *necessary*, but if you don't know better, you should probably use it.
Fixes rgbds-www#9
2020-10-13 11:37:25 +02:00
Eldred Habert 05256946ac Merge pull request #604 from NieDzejkob/narg-overwrite
Don't overwrite symbol when it's not allowed
2020-10-13 10:47:57 +02:00
Eldred Habert 73396166aa Merge pull request #605 from NieDzejkob/invalid-labels
Don't consider difference of invalid labels constant
2020-10-13 10:42:05 +02:00
Jakub Kądziołka 4c5d5c7085 Don't consider difference of invalid labels constant
If a label is defined outside of a section, avoid trying to obtain its
value.
2020-10-12 23:03:14 +02:00
Jakub Kądziołka 045a9e8b93 Report only one error when invalid shift has argument
Not to mention that incrementing a variable in a loop is kinda dumb.
2020-10-12 22:54:20 +02:00
Jakub Kądziołka 4419f0d54f remove dead function: sym_GetDefinedValue 2020-10-12 13:31:21 +02:00
Jakub Kądziołka b07aa00d5c Don't overwrite symbol when it's not allowed
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.
2020-10-12 12:35:49 +02:00
Eldred Habert e4f5df1306 Merge pull request #603 from NieDzejkob/rpn-realloc
reserveSpace: don't assume one doubling is enough
2020-10-12 12:26:44 +02:00
Jakub Kądziołka dc62d60e9b reserveSpace: don't assume one doubling is enough 2020-10-12 11:57:03 +02:00
ISSOtm 71d8aeb4c2 Add CMake defines to enable tracing lexer and parser 2020-10-12 09:02:21 +02:00
Eldred Habert 0836f67d42 Merge pull request #601 from NieDzejkob/utf8decoder
utf8decoder: Use byte-sized byte argument
2020-10-12 01:49:57 +02:00
Eldred Habert 176a57a1e9 Merge pull request #600 from NieDzejkob/stray-shift
Report error when shifting outside a macro
2020-10-12 01:44:10 +02:00
Eldred Habert 0d02355dbf Merge pull request #599 from NieDzejkob/stray-align
Report error when aligning outside of a section
2020-10-12 01:43:35 +02:00
Jakub Kądziołka 6767d11c23 utf8decoder: Use byte-sized byte argument
This prevents passing a negative value out of a signed char by accident.
Also renders some casts in the code superfluous.
2020-10-12 01:22:09 +02:00
ISSOtm 2dd9015dc6 Remove two stale variables from parser.y
They were made useless with the lexer rewrite
2020-10-12 00:52:12 +02:00
Jakub Kądziołka 217c10ddac Report error when shifting outside a macro 2020-10-12 00:47:01 +02:00
Jakub Kądziołka 822e4e7c44 Report error when aligning outside of a section 2020-10-12 00:27:54 +02:00
ISSOtm 0b1d01792d Indicate cur offset in linkerscript "backwards org" message 2020-10-12 00:04:08 +02:00
ISSOtm 01637768cf Rename asmy to more explicit parser
This should make the purpose of that file clearer to newcomers
2020-10-11 21:03:41 +02:00
ISSOtm 6a8ae643d5 Mention that SHIFT updates _NARG
Fixes #598
2020-10-11 02:13:30 +02:00
ISSOtm fd83d46ba0 Enable master docs update workflow always
There seems to be no way to make the check work, and Actions are disabled
in forks by default anyways.
2020-10-11 02:04:09 +02:00
ISSOtm 914856342c Fix incorrect documentation of accepted sym names
No, they cannot start with a digit!
2020-10-11 01:57:27 +02:00
Eldred Habert 91889fc14a Merge pull request #593 from Rangi42/issue586
Fix #586: Update the `charmaps` hashmap when an existing charmap is resized
2020-10-10 02:15:04 +02:00
Rangi 7c8ec5a5ed Add a test case for charmaps that segfaults prior to this fix 2020-10-09 20:06:02 -04:00
Rangi effc6788eb Fix #586 segfault: Update the charmaps hashmap when an existing charmap is resized 2020-10-07 13:21:13 -04:00
Eldred Habert f9daf27511 Merge pull request #585 from ISSOtm/msvc-ci
Add MSVC in CI
2020-10-06 17:48:13 +02:00
ISSOtm 06f7387466 Avoid using VLA in EQUS dumping
MSVC does not support those...
Also add a `develop` warning about VLAs, to avoid future incidents
2020-10-06 08:55:45 +02:00
ISSOtm 21e50eeff1 Have lexer not require <unistd.h> on MSVC
Required for `open`, `close`, `read`, and `STDIN_FILENO`,
which are defined elsewhere on MSVC.
2020-10-06 08:55:45 +02:00
ISSOtm fd4cec93cd Compile with MSVC as well in CI 2020-10-06 08:55:41 +02:00
ISSOtm 92f2055a6c Fix implicit cast between enums
This caused `make develop` to fail
2020-10-05 01:53:54 +02:00
Eldred Habert be9b1198e9 Merge pull request #584 from Xeyler/master
Add directory summary to README.rst
2020-10-04 20:20:08 +02:00
Brigham Campbell 56bea083f9 Add directory summary to README.rst 2020-10-04 12:04:59 -06:00
Eldred Habert fdfc02ab96 Merge pull request #583 from JL2210/cmake-build-type
Modularize CMake build configuration
2020-10-04 19:45:20 +02:00
Eldred Habert fc7f042ad6 Merge pull request #551 from NieDzejkob/errors-after-unknown-symbol
link: Suppress cascading errors.
2020-10-04 19:43:38 +02:00
James Larrowe 761c775043 Modularize CMake build configuration
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 :|
2020-10-04 13:28:00 -04:00
Jakub Kądziołka b421c983d6 link: Suppress cascading errors. 2020-10-04 18:14:22 +02:00
Eldred Habert 3036b58598 Merge pull request #557 from ISSOtm/new-lexer-electric-boogaloo
New lexer 2 — Electric Boogaloo
2020-10-04 16:45:47 +02:00
ISSOtm 2eca43cd2d Fix critical oversight in lexer buffer refilling
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.
2020-10-04 16:10:32 +02:00
ISSOtm c24694233f Fix incomplete duplication of REPT nodes
"Initialization, sizeof, and the assignment operator ignore the flexible array member."
Oops!
2020-10-04 04:46:01 +02:00
ISSOtm 423a7c4899 Handle \\r better
Translate it to \\n regardless of the lexer mode
2020-10-04 04:46:01 +02:00
ISSOtm ee9e45b3d4 Change assertion condition in __FILE__ buf dumping
Removes a false positive from Clang static analysis
2020-10-04 04:46:01 +02:00
ISSOtm 5a65188ca9 Implement compact file stacks in object files
Gets rid of `open_memstream`, enabling Windows compatibility again
Also fixes #491 as a nice bonus!
2020-10-04 04:46:01 +02:00
ISSOtm 930080f556 Mark not unmapping macro-containing files as okay
There isn't really a better alternative.
Making several mappings instead requires too much bookkeeping.
2020-10-04 04:46:01 +02:00
ISSOtm 8e7afb0ab3 Move some MSVC-specific defines to platform.h 2020-10-04 04:46:01 +02:00
ISSOtm 138523570e Fix possible uninitialized read on Windows 2020-10-04 04:46:01 +02:00
ISSOtm 82469ac0fd Shim around mmap on Windows 2020-10-04 04:46:01 +02:00
ISSOtm 96cb5e10ed Fix range-dependent dead code in recursion depth check 2020-10-04 04:46:01 +02:00
ISSOtm b224cab3e0 Harmonize printing distance 2020-10-04 04:46:01 +02:00
ISSOtm 7381d7b92f Remove unnecessarily nested symbol data union 2020-10-04 04:46:01 +02:00
ISSOtm dbef51ba05 Move isWhitespace to a place where it makes more sense 2020-10-04 04:46:01 +02:00
ISSOtm c952dd8a6e Fix fixed-point constants not working correctly
And added a test to check their behavior
2020-10-04 04:46:01 +02:00
ISSOtm b65ea64a58 Add newlines to all test output
MacOS treats them differently, for some reason.
2020-10-04 04:46:01 +02:00
ISSOtm 542b5d18f1 Fix possible capture buffer size overflow
Attempt to grow it to the max size first.
Seriously, if this triggers, *how*
2020-10-04 04:46:01 +02:00
ISSOtm 71a0a42cfb Fix C2x use of static_assert 2020-10-04 04:46:01 +02:00
ISSOtm ac011fe69f Use common function to discard comments in macro args 2020-10-04 04:46:01 +02:00
ISSOtm 9e3d7a50e6 Handle comments in line continuations 2020-10-04 04:46:00 +02:00
ISSOtm e33c2ad6a2 Fix INCLUDE ignoring -MG 2020-10-04 04:46:00 +02:00
ISSOtm 615f1072d9 Fix readFractionalPart never shifting characters 2020-10-04 04:46:00 +02:00
ISSOtm f7b7a97407 Prevent expanding macro args in comments
Also use a cleaner way, instead of hardcoding to capture
2020-10-04 04:46:00 +02:00
ISSOtm ece6853e0f Implement opt b and opt g 2020-10-04 04:46:00 +02:00
ISSOtm b7b03ee451 Fix "REPT 0" not being a no-op 2020-10-04 04:45:59 +02:00
ISSOtm f9b48c0cad Fix else working incorrectly from macros
Since the "skip ELSE blocks" variable is global, it used to get carried
over from the macro's `if` to the outer's.
2020-10-04 04:45:59 +02:00
ISSOtm aa76603da9 Add line+col trace info to lexer 2020-10-04 04:45:59 +02:00
ISSOtm b83b9825f8 Fix _NARG crashing outside of macros
And add a test for it
2020-10-04 04:45:59 +02:00
ISSOtm d641972cde Fix macro args not being restored when exiting macros 2020-10-04 04:45:59 +02:00
ISSOtm 4d1333e124 Fix incorrect error reporting of INCLUDEd files 2020-10-04 04:45:59 +02:00
ISSOtm 35396e6410 Fix files being unmapped when still referenced by macros 2020-10-04 04:45:59 +02:00
ISSOtm 8d18b39eee Support missing register tokens
Made possible by #491
2020-10-04 04:45:59 +02:00
ISSOtm ae77893021 Fix file name reporting
As noted in the function's code, this is very error-prone, but
will do the job; this needs rewriting due to #491 anyways, so, temporary.
2020-10-04 04:45:59 +02:00
ISSOtm baeb180acd Apply error reporting changes to tests 2020-10-04 04:45:58 +02:00
ISSOtm fd02ffb7bd Implement __FILE__ symbol
Also clean up built-in symbol creation
This is not great, but currently okay.
Should be fixed later, like the rest...
2020-10-04 04:45:58 +02:00
ISSOtm 62ecdce0b0 Fix line-continuation-macro test 2020-10-04 04:45:58 +02:00
ISSOtm e4f2fad215 Support line continuations in main scope 2020-10-04 04:45:58 +02:00
ISSOtm 3f5f9bcaf0 Fix numeric constant overflow checks 2020-10-04 04:45:58 +02:00
ISSOtm 08867b3cec Enable catching invalid macro arg 0 2020-10-04 04:45:55 +02:00
ISSOtm 9081feab51 Reinstate macro arg scan distance
Used to be broken, so it was removed, but doing so prevents escaping them.
So it was instead put back in, but with corrected behavior
2020-10-04 04:39:27 +02:00
ISSOtm cf992164f7 Fix lexer capture sometimes not being reset 2020-10-04 04:39:27 +02:00
ISSOtm b27b821e7f Fix RAW lexer length underflow
Also added an assertion to check against more such overflows
2020-10-04 04:39:26 +02:00
ISSOtm d9ecaabac1 Add debug tracing code to lexer
Hidden behind a #define, like YYDEBUG
2020-10-04 04:39:26 +02:00
ISSOtm cd747d8175 Fix many lexer bugs
More to come...
2020-10-04 04:39:25 +02:00
ISSOtm df75fd2ec2 Fix expansion reporting being incorrect 2020-10-04 04:38:53 +02:00
ISSOtm adcaf4cd46 Fix crash when no macro args are being used 2020-10-04 04:38:53 +02:00
ISSOtm 81a77a9b88 Re-implement block copy to avoid expanding macro args
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).
2020-10-04 04:38:53 +02:00
ISSOtm 6e805cd318 Implement macro args
This finally allows running 90% of the test suite, debugging time!
2020-10-04 04:38:53 +02:00
ISSOtm e11f25024e Add test for built-in file symbol
It's currently defined in fstack.c, making it more prone to accidental
dropping. Let's not repeat the 0.3.9 scenario...
2020-10-04 04:38:53 +02:00
ISSOtm 7c895f8a1b Fix diagnostic formatting
Missing colon and space after the file stack
2020-10-04 04:38:53 +02:00
ISSOtm 38bda7e1bb Fix string expansion reporting
More expansions were allowed than the limit specified, and reporting code
did not account for the extra one that caused overflow
2020-10-04 04:38:52 +02:00
ISSOtm 149db9a022 Fix incorrect freeing of expansions
Freeing an expansion should free its children, not its siblings...
Fixes a use-after-free reported by scan-build. Nice catch!
2020-10-04 04:38:52 +02:00
ISSOtm fed252bc49 Fix nested expansions being incorrectly handled
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!
2020-10-04 04:38:52 +02:00
ISSOtm 61b2fd9816 Add string expansion reporting
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.
2020-10-04 04:38:52 +02:00
ISSOtm 5ad7a93750 Add EQUS expansion 2020-10-04 04:38:52 +02:00
ISSOtm 2ec10012b6 Fix mmap read offset not being initialized 2020-10-04 04:38:52 +02:00
ISSOtm e56c6cc291 Fix PC's name not being passed to parser 2020-10-04 04:38:52 +02:00
ISSOtm 4c9a929a14 Implement almost all functionality
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
2020-10-04 04:38:50 +02:00
ISSOtm 71f8871702 Implement more functionality
Macro arg detection, first emitted tokens, primitive (bad) column counting
2020-10-04 04:37:58 +02:00
ISSOtm 6dc4ce6599 Implement infrastructure around new lexer
The lexer itself is very much incomplete, but this is intended to be a
safe point to revert to should further implementation go south.
2020-10-04 04:37:58 +02:00
Eldred Habert 3a44cc7722 Merge pull request #582 from ISSOtm/rewrite-charmap
Rewrite charmap system
2020-10-04 04:37:06 +02:00
ISSOtm 4cfed3c98f Rewrite charmap system
Avoid allocating a *ton* of data per charmap
Stop relying on uninitialized data in charmap nodes
Only initialize charmap nodes lazily
2020-10-04 04:31:10 +02:00
Eldred Habert 6af57ff026 Merge pull request #581 from JL2210/cmake-docs
Install manpages with CMake
2020-10-03 22:15:17 +02:00
ISSOtm 2e3db9d56a Clean up label generation
Only check for localness when we already know we have a local
2020-10-03 21:33:30 +02:00
James Larrowe f8d9fa87ed Install manpages with CMake 2020-10-03 12:37:56 -04:00
ISSOtm f53ad359a6 Remove whoami step from Windows CI
A carry-over from testing
2020-10-03 02:17:18 +02:00
ISSOtm 84de86beb5 Enable make develop on Ubuntu 20.04 CI as well 2020-10-03 01:05:09 +02:00
Eldred Habert 04e7af2675 Merge pull request #579 from ISSOtm/cmake-ci
Enable CMake in CI
2020-10-02 23:30:26 +02:00
Eldred Habert 4f13a336b9 Merge pull request #578 from JL2210/cmake-pkgconfig
Use pkg-config to detect libpng
2020-10-02 22:30:30 +02:00
ISSOtm 03508119e5 Use CMake in CI as well 2020-10-02 22:24:02 +02:00
James Larrowe 03e20138d3 Use pkg-config to detect libpng
Only fall back to findpng
2020-10-01 18:58:36 -04:00
Antonio Niño Díaz dfcba36448 test: Update commit of uCity used for testing
This one updates the code to fix all warnings introduced in the last few
months because of updates to RGBDS.
2020-09-27 22:47:56 +01:00
ISSOtm 8e4a9a5c21 Remove assertions from release builds
I believe the CMakeLists already did that, but the Makefile did not.
2020-09-27 17:05:52 +02:00
ISSOtm a1286e6f0e Make newlines explicit in error messages
In preparation for a change a PR is about to make
2020-09-27 10:54:06 +02:00
ISSOtm c0808246e5 Silence the mingw test
Use "quiet" instead of "count"...
2020-09-27 10:51:52 +02:00
ISSOtm ba051e10fb Factor printing assert failures into functions
Saves some code duplication
2020-09-27 09:24:24 +02:00
ISSOtm 9fee0603b1 Fix typo in object file format doc
Thanks @ax6!
2020-09-24 16:43:13 +02:00
ISSOtm be8ebe6db9 Fix master docs update CI script
GitHub documentation about the syntax is unclear, this should be right
according to the examples I saw.
2020-09-24 16:41:23 +02:00
ISSOtm 548e3dc31c Correct previously-introduced test being a no-op
Forgot to invoke the macro due to a copy-paste error
2020-09-24 16:35:45 +02:00
ISSOtm 9440086d77 Add a test for purging a macro while running
This could cause a crash if the macro name is then used for error reporting
2020-09-24 16:14:18 +02:00
ISSOtm ec5a1bc71f Fix incorrect obj file documentation
Bit 7 of section types was actually documented in the symbol type
Bit 6 of section types was not documented at all
2020-09-24 10:26:02 +02:00
ISSOtm 9742fa731c Run the quote in file name except on Windows
This should make the CI function again
2020-09-22 18:13:26 +02:00
ISSOtm 91a3c538d9 Enable running regression tests on PRs as well 2020-09-22 17:27:29 +02:00
ISSOtm e98485da3f Make code style errors fail their CI job
Mimics the behavior of the old Travis script
2020-09-22 02:59:38 +02:00
ISSOtm 6528a955fe Fix checkpatch in CI 2020-09-22 02:44:24 +02:00
ISSOtm 431f77127e Also update master docs when updating script 2020-09-22 01:05:49 +02:00
ISSOtm 2cc58723cb Do not try updating docs if no key is set
This will avoid this randomly failing in forks, unless we want to run it
2020-09-22 00:56:14 +02:00
ISSOtm 268219d74e Avoid warning about /* fallthrough */ comments
We do not have `fallthrough;`, so...
2020-09-21 17:46:44 +02:00
ISSOtm d09ed3e52e Get rid of flex as a dependency in CMakeLists
It will actually not be needed for new lexer
2020-09-20 03:39:53 +02:00
ISSOtm 421d1f5490 Add regression test for #546
Check for quotes in `__FILE__`
2020-09-20 00:44:29 +02:00
ISSOtm 66784b7122 Fix documentation not mentioning SECTION FRAGMENTsyntax 2020-09-20 00:06:51 +02:00
ISSOtm 54f2d99ce7 Apply two minor fixes to rgbasm(5)
Mustn't → must not
Add a comma to INCBIN sentence to mirror INCLUDE's
2020-09-17 20:45:58 +02:00
ISSOtm 557c799ec9 Update README to point to online install instructions 2020-09-17 03:47:55 +02:00
ISSOtm d22a667095 Update help text to redirect to new online docs 2020-09-17 03:10:02 +02:00
ISSOtm 30085a5342 Update documentation link in README 2020-09-16 15:52:36 +02:00
ISSOtm 304e6c4279 Sync redirect page generation with site 2020-09-16 06:25:46 +02:00
ISSOtm 12458aae6f Fix permalinks of index pages 2020-09-16 06:04:38 +02:00
ISSOtm 7e5d9683b1 Use mandoc 1.14.5 in CI
This is the version that added -Otoc
2020-09-15 19:24:25 +02:00
ISSOtm 210a4a957a Get rid of in-repo HTML documentation
The online documentation is now managed by a CI hook
2020-09-15 18:39:22 +02:00
ISSOtm 131ad9b315 Fix GitHub link in BUGS sections 2020-09-15 18:35:04 +02:00
ISSOtm 06b4cf57ab Fix example arguments to -MT appearing as options 2020-09-15 18:32:13 +02:00
ISSOtm dbefdc923a Clean up doc post-processor
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
2020-09-15 18:30:40 +02:00
ISSOtm 37e45de9c1 Improve rendering of pages
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
2020-09-15 18:27:55 +02:00
ISSOtm 5e63527190 Update repo link at bottom of all man pages 2020-09-15 16:00:17 +02:00
ISSOtm 0cc9026978 Fix docs update action
Make script executable (facepalm)
Fix `run**s**-on` typo
Add key using ssh-agent
Force using SSH for pushing back
2020-09-15 15:57:20 +02:00
ISSOtm bb6a5441ed Update RGBDS history to mention org move 2020-09-15 15:02:26 +02:00
ISSOtm 0ffda1bf29 Add CI Action to update man pages from master 2020-09-15 15:00:07 +02:00
Antonio Vivace 56b5f77dc8 Mention the new website, add notice about the movement to the gbdev org 2020-09-15 14:01:38 +02:00
Antonio Vivace 6eb284f99e Update README.rst 2020-09-15 13:53:22 +02:00
Marco Spataro 34c2288fd0 Fix __FILE__ when filename contains quotes 2020-09-10 12:49:04 +02:00
ISSOtm 304bb9f902 Remove most Hungarian notation in section module
Seriously, it sucks.
2020-09-06 20:43:13 +02:00
ISSOtm 14be01880d Move UNION code inside section.c
Improves organization and locality
2020-09-06 19:18:10 +02:00
ISSOtm 12b7cf3cd4 Move curOffset into section code
Improves organization
2020-09-06 18:50:19 +02:00
ISSOtm 0d7914bff7 Fix asm/charmap.h not including required header 2020-09-06 17:16:49 +02:00
ISSOtm d2285953d7 Fix test missed by last PR
We need to fix CI
2020-09-03 14:28:28 +02:00
Eldred Habert d2801505c3 Merge pull request #562 from Rangi42/strsub-0
Resolve #554: STRSUB("<N-char string>", N, 0) will not warn "Position N is past the end of the string"
2020-09-03 12:12:03 +02:00
ISSOtm 9d62b4b9bb Fix bugs with LOAD section size
LOAD blocks did not properly update their parent's size until after closed
Additionally, section size wasn't correctly sanitized inside LOAD blocks
2020-09-03 12:07:12 +02:00
Rangi b65b723fa6 Resolve #554: STRSUB("<N-char string>", N, 0) will not warn "Position N is past the end of the string" 2020-08-31 15:40:25 -04:00
ISSOtm e05321356b Fix truncation warning when adding charmap mapping
It used to warn when mapping negative values
2020-08-31 21:33:53 +02:00
ISSOtm 0778959e98 Remove arbitrary limits on charmap
They were made irrelevant when switching to a trie
2020-08-31 21:26:21 +02:00
Eldred Habert 76331d1c4a Merge pull request #552 from mattcurrie/incbin-length-optional
Make INCBIN's length argument optional
2020-08-23 00:11:54 +02:00
Eldred Habert 9e378ec5cf Bump license year
I feel like there's a 20xx joke to be made here...
2020-08-20 23:02:25 +02:00
ISSOtm f57d33b17a Update subprojects in test suite
Especially necessary for the "new lexer" branch
2020-08-18 16:40:41 +02:00
Matt Currie c389e8dccb Fix typo
'arugment' => 'argument'
2020-08-17 13:57:58 +12:00
Matt Currie 90c64a94d1 Revert change to rgbasm.5.html
Will be rebuilt upon release
2020-08-17 13:56:29 +12:00
Eldred Habert df27af6d1c Merge pull request #553 from JL2210/cmake-develop
Add DEVELOP option to CMake
2020-08-16 22:12:47 +02:00
James Larrowe c85b48f23e Default to debug when building in develop mode 2020-08-16 13:58:02 -04:00
James Larrowe 5a9f2b7750 Add DEVELOP option to CMake
This requires CMake 3.0 so -Werror won't conflict with link tests.
Remove all version checks to improve simplicity.
2020-08-16 13:23:29 -04:00
ISSOtm fcfecc6e82 Improve description of @ symbol
As requested by someone on GBDev
2020-08-15 15:23:11 +02:00
Matt Currie f863a927c1 Make INCBIN's length argument optional
INCBIN can now be used with just a start position to include everything
from the start position until the end of the file.
2020-08-15 17:24:11 +12:00
Eldred Habert cb4fbdfcd5 Merge pull request #550 from rednex/an/array
Refactor warning array for clarity
2020-08-05 10:53:21 +02:00
Eldred Habert c6eacde55e Merge pull request #544 from ISSOtm/atomic_ind
Split register-indirect tokens
2020-08-05 10:52:18 +02:00
Antonio Niño Díaz daf780c7e6 Refactor warning array for clarity 2020-08-04 22:28:56 +01:00
Eldred Habert 613305d234 Add checkpatch link in README 2020-07-31 16:07:00 +02:00
ISSOtm 656432301d Run as many CI jobs as possible when one fails
The other matrixes should not have this problem, so only touch unix testing
2020-07-27 18:34:32 +02:00
ISSOtm 38a80f2816 Fix test failing on OS-dependent trailing newline 2020-07-27 18:30:12 +02:00
ISSOtm 6563133426 Avoid using echo -e in tests 2020-07-27 18:26:05 +02:00
ISSOtm 762474d3ac Let RGBASM write JR offsets in floating sections
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.
2020-07-27 18:17:29 +02:00
ISSOtm b1adbcc77c Output a non-empty RPN buffer from known expressions
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!
2020-07-27 17:43:31 +02:00
Eldred Habert dda052da20 Merge pull request #545 from JL2210/consistent-versions
Use versioning consistent with the Makefile in CMake
2020-07-26 19:16:27 +02:00
James Larrowe 2d6bdbc1b1 Use versioning consistent with the Makefile in CMake
This uses git to determine the dirty version and uses a fallback
if that's not available.
2020-07-23 10:47:01 -04:00
ISSOtm 0600856167 Move incbin slice sign check
The grammar's message is pretty generic, so this one is more useful.
2020-07-23 01:06:28 +02:00
ISSOtm ce47b57b03 Document version string fallback in Makefile
For a packager just looking at the Makefile, it's not obvious that there
is one...
2020-07-22 16:21:58 +02:00
ISSOtm f3c916ab96 Allow env vars to override default CFLAGS etc.
Should make the work easier for downstream packagers
2020-07-22 16:21:21 +02:00
ISSOtm ca6fa6d1d7 Split register-indirect tokens
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.
2020-07-22 15:00:39 +02:00
ISSOtm fcd37b52b6 Update pret projects to latest commits
Behind pokecrystal by 123, behind pokered by 172
2020-07-22 00:29:38 +02:00
ISSOtm 8c0adb63a1 Sync release version in CMakeLists 2020-07-21 23:54:36 +02:00
ISSOtm f5b0c701a6 Add install hint to CMakeLists 2020-07-21 23:41:56 +02:00
ISSOtm 874bd92604 Only require libpng 1.2 in CMakeLists
This version is sufficient for rgbgfx to function properly, according to testing.
The security problems are not ours to decide, however!
2020-07-21 23:23:52 +02:00
ISSOtm 69a8c62863 Add install directives to CMakeLists
Otherwise `make install` or `cmake --install` does not work
2020-07-21 23:17:33 +02:00
ISSOtm 5481af5093 Release 0.4.1 2020-07-21 23:11:06 +02:00
ISSOtm 6355d0598b Regenerate docs for 0.4.1 2020-07-21 23:10:14 +02:00
Eldred Habert 1145d10996 Merge pull request #543 from ISSOtm/ubuntu20
Add Ubuntu 20.04 to CI
2020-07-21 22:24:28 +02:00
ISSOtm 32231e3f7e Add Ubuntu 20.04 to CI 2020-07-21 22:15:56 +02:00
Eldred Habert 29314f76f7 Merge pull request #533 from JL2210/platform-fixes
Add platform-specific fixes file (only for MSVC, currently)
2020-07-21 22:11:25 +02:00
ISSOtm 8e92383fa3 Enable -Wobsolete by default
The fact that deprecations were common and quickly acted upon was raised by
some users
2020-07-21 21:06:48 +02:00
James Larrowe e51701acaa Add platform-specific fixes file
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
2020-07-21 14:24:22 -04:00
ISSOtm 0793e9effe Fix develop compilation error
This bug slipped by because my pre-commit hook for testing was broken...
2020-07-21 20:10:28 +02:00
ISSOtm c25b0be085 Document that -t and -w convert section types
This is also a fairly overdue doc update
2020-07-21 20:05:26 +02:00
ISSOtm 1f2f797cb9 Add section fragments
Fixes #517, and hopefully enables RGBDS as a SDCC back-end
2020-07-21 19:56:46 +02:00
ISSOtm aca00e4fce Document MP etc. in rgbasm(1)
This is actually kind of overdue...
2020-07-21 15:55:56 +02:00
Eldred Habert cf80293d9b Merge pull request #540 from daid/patch-1
Make the local variables of getopt static.
2020-07-21 13:11:30 +02:00
daid 6d53753c66 Make the local variables of getopt static.
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.
2020-07-21 10:21:33 +02:00
Eldred Habert 79f293c3d7 Merge pull request #529 from JL2210/cmake
Add CMake build system
2020-07-20 16:02:47 +02:00
Eldred Habert 8c765883fb Merge pull request #536 from braydenm303/patch-1
Fix error in documentation about unary not
2020-07-20 15:11:29 +02:00
Brayden Morris 83aa456d05 Fix error in documentation about unary not 2020-07-13 09:32:43 -06:00
James R Larrowe 819c36943e Add CMake build system
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.
2020-07-03 15:10:18 -04:00
Eldred Habert 8b60efa149 Merge pull request #530 from JL2210/fix-clang
Fix Clang warning in linkdefs
2020-06-27 22:07:19 +02:00
James Larrowe 240fca0861 Fix Clang warning in linkdefs
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
2020-06-23 23:29:49 -04:00
Eldred Habert f996186fae Merge pull request #526 from JL2210/fix-bank-index
Fix indexing of banks array, fixes #525
2020-06-21 12:44:17 +02:00
James Larrowe 69a41d8ef9 Fix indexing of banks array
When ROMX bank 1 is given, the banks array is indexed with an index
of 1 rather than an index of zero.
2020-06-17 13:33:48 -04:00
Eldred Habert b958820bce Merge pull request #523 from RandomBananazz/patch-1
Fixed error in POP AF instruction reference
2020-05-27 12:45:44 +02:00
Jason Yuan 7624bd524c Fixed error in POP AF instruction reference
The "imaginary" equivalent instructions put the instructions in the wrong order (inc sp first).
2020-05-26 23:29:06 -04:00
Eldred Habert 663f0ca3b0 Merge pull request #522 from JL2210/djgpp
Fix DJGPP build
2020-05-21 22:37:24 +02:00
James Larrowe f88d9e728d Fix DJGPP build
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.
2020-05-19 19:21:16 -04:00
ISSOtm 71fa62c9d1 Fix incorrectly spaced unary ! in RPN documentation 2020-05-13 01:20:34 +02:00
ISSOtm 5c6069dbe9 Add NULL and overflow checks to macro args 2020-05-13 01:17:58 +02:00
ISSOtm d517d2d6b4 Change macro arg allocation to geometric growth array 2020-05-13 00:22:56 +02:00
ISSOtm 80218fa109 Fix array overflow on invalid macro arg evaluation
`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.
2020-05-12 16:44:23 +02:00
Eldred Habert fee8a58b77 Merge pull request #521 from aaaaaa123456789/master
Support over 256 macro arguments
2020-05-12 15:46:42 +02:00
aaaaaa123456789 fd52a6f046 Add a test for >256 macro arguments 2020-05-12 07:22:42 -03:00
aaaaaa123456789 89fb372326 Set max macro arguments to 99,999 2020-05-12 06:46:17 -03:00
aaaaaa123456789 a828f82414 Remove fixed-size array for macro arguments 2020-05-12 06:46:07 -03:00
Eldred Habert 4d0d6664d7 Merge pull request #520 from JL2210/inttypes-stdint
Use inttypes for stdint types
2020-05-07 17:31:06 +02:00
James Larrowe 5c24de3dc4 Use inttypes for stdint types
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.
2020-05-07 11:10:20 -04:00
ISSOtm 363458c3bc Fix semi-unused variable in lexer.c 2020-05-06 19:55:37 +02:00
ISSOtm b299f6fb3b Fix uninitialized memory use with -MT and -MQ
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?
2020-05-06 19:19:10 +02:00
Eldred Habert 645473e336 Merge pull request #518 from JL2210/warn-parameterless-dx
Add empty data directive warning
2020-05-06 16:25:03 +02:00
James Larrowe bdf397bba7 Add empty data directive warning
Fixes #516
2020-05-06 09:50:28 -04:00
ISSOtm 781a65ee49 Fix hashmap collisions sometimes hanging deletion 2020-05-03 19:13:12 +02:00
ISSOtm c135e2c6a0 Fix local sym names not being expanded by PURGE
And an additional bug that broke the attached test
2020-05-03 19:06:48 +02:00
ISSOtm 12693081c9 Use colons for hour symbols 2020-04-28 13:05:06 +02:00
Eldred Habert 7c22954fd5 Merge pull request #513 from JL2210/disable-padding-option
Add option to disable padding in rgblink
2020-04-27 11:05:55 +02:00
ISSOtm 8958e352df Update documentation for new -x option 2020-04-27 11:04:29 +02:00
ISSOtm 573003113b Fix 0-byte sections incorrectly printed in map files
Fixes #515
2020-04-17 11:38:28 +02:00
JL2210 8b1351fc3e Add option to disable padding in rgblink
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]>
2020-04-15 09:34:51 -04:00
Eldred Habert 106ef895ee Merge pull request #514 from JL2210/fix-gfx-gb-leak
Add error checking and fix memory leak in gfx/gb.c
2020-04-14 21:31:12 +02:00
JL2210 7f9bd12f76 Add error checking and fix memory leak in gfx/gb.c
It's possible that tile could be leaked, so free it.

Fix sizeof convention and check the result of malloc.

Signed-off-by: JL2210 <[email protected]>
2020-04-13 22:02:24 -04:00
ISSOtm 5fe3a0adb6 Remove non-OPT options from Options struct 2020-04-13 17:15:00 +02:00
Eldred Habert cdb4c5f553 Merge pull request #509 from JL2210/zero-alloc-use-fix-3
Fix use of zero-allocated memory
2020-04-13 02:50:58 +02:00
ISSOtm 57639f3765 Change comment style and use errx instead of err 2020-04-13 02:50:11 +02:00
Eldred Habert 9bec983923 Merge pull request #511 from JL2210/memory-errors
Fix memory errors in makepng
2020-04-13 02:39:17 +02:00
ISSOtm 2220f19fa7 Fix use-after-free with include in linker scripts
Fixes #510, and further proves that you *really* should not entrust memory
ownership management to humans :P
2020-04-13 02:36:19 +02:00
JL2210 2a734ecba2 Fix memory errors
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]>
2020-04-12 19:45:37 -04:00
JL2210 d21015e34a Fix use of zero-allocated memory
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]>
2020-04-12 19:36:47 -04:00
ISSOtm 023a3c037f Properly handle missing symbols
Fixes #512
2020-04-12 22:52:32 +02:00
ISSOtm 828edb7403 Remove spurious error from div by zero test 2020-04-12 01:05:06 +02:00
ISSOtm a034ce0478 Deprecate '*' for comments 2020-04-09 17:57:15 +02:00
Eldred Habert d6cd5823e3 Merge pull request #508 from JL2210/mod-by-zero-fix-2
Fix modulo by zero
2020-04-09 14:52:12 +02:00
JL2210 5dd941b311 Fix modulo by zero
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]>
2020-04-09 08:50:23 -04:00
ISSOtm f9f27d6f5a Clean up symbol system
Get rid of Hungarian notation
Improve encapsulation (the rest of the world should not touch PC directly)
2020-04-09 10:42:37 +02:00
Eldred Habert 5ea8490e2b Merge pull request #507 from JL2210/null-pointer-fix-1
Fix possible null pointer dereference
2020-04-08 23:35:21 +02:00
JL2210 5863cd10b8 Fix possible null pointer dereference
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]>
2020-04-08 17:30:43 -04:00
ISSOtm 40f8e33e6c Fix periods not being accepted as second char of label names 2020-04-08 15:14:07 +02:00
ISSOtm 0157ba63d3 Document whitespace before local labels 2020-04-08 15:08:29 +02:00
ISSOtm 9e3d8b22cb Document new intra-section align
Also sneak in two code style fixes forgotten in last commit
2020-04-08 15:01:36 +02:00
ISSOtm 665412c073 Implement mid-section alignment directive
Fixes #254.
2020-04-08 12:29:00 +02:00
ISSOtm 2b0c34ecb5 Fix a few code style errors 2020-04-08 00:44:41 +02:00
ISSOtm b0ec8468e6 Allow specifying offset in addition to alignment 2020-04-08 00:40:41 +02:00
ISSOtm e82ad21704 Use a single byte for alignment 2020-04-07 21:19:09 +02:00
ISSOtm e098bf47ba Allow references to be overridden by constant symbols
RGBLINK is capable of handling it now.
Though it'd be ideal for RGBASM to directly catch it.

Fixes #496.
2020-04-07 20:57:20 +02:00
ISSOtm 190678107b Prevent RGBLINK from crashing when getting the bank of a constant 2020-04-07 20:41:29 +02:00
ISSOtm 9f82fa4cf7 Fix BANK(@) outside sections causing crashes 2020-04-07 15:51:17 +02:00
Eldred Habert 562835308b Merge pull request #504 from runlevel5/gcc10-fix
Fix multiple definitions for GCC10
2020-04-07 15:18:23 +02:00
ISSOtm 927c65e863 Fix incorrect PC in LOAD blocks at link time 2020-04-07 14:44:51 +02:00
ISSOtm 5b6c1569a4 Make failure to open file a fatal error 2020-04-07 11:36:44 +02:00
Trung Lê 65121e6d5d Fix multiple definitions for GCC10 2020-04-07 14:48:30 +10:00
ISSOtm 82e0e4ffaf Make some RGBLINK errors non-fatal 2020-04-06 00:48:10 +02:00
ISSOtm ffb199a26a Avoid Useless Use of backticks in rgblink testing 2020-04-06 00:44:59 +02:00
ISSOtm 175933d2b1 Remove old scripts for updating references for tests
I much rather prefer correcting everything by hand, and gauging
whether the change is good on a case by case basis
2020-04-06 00:41:37 +02:00
Eldred Habert c86e6fef0a Merge pull request #502 from JL2210/more-conventional-permissions
Use more conventional permissions and man-page directory
2020-04-06 00:25:33 +02:00
JL2210 1e3ce2a36f Use more conventional permissions and man-page directory
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]>
2020-04-05 17:02:12 -04:00
ISSOtm 153915dc2f Improve portability of new make dist 2020-04-04 14:48:15 +02:00
ISSOtm ced38bc6ee Add new Makefile target for release tarballs 2020-04-04 14:23:28 +02:00
840 changed files with 17089 additions and 13942 deletions
+3
View File
@@ -83,3 +83,6 @@
# Parentheses can make the code clearer
--ignore UNNECESSARY_PARENTHESES
# We don't have `fallthrough;` */
--ignore PREFER_FALLTHROUGH
+3
View File
@@ -0,0 +1,3 @@
github: avivace
patreon: gbdev01
open_collective: gbdev
@@ -7,6 +7,14 @@
sub(/b><\/td/, "th");
}
# The whole page is being generated, so it's not meant to contain any Liquid
BEGIN {
print "{% raw %}"
}
END {
print "{% endraw %}"
}
BEGIN {
in_synopsis = 0
}
@@ -38,48 +46,11 @@ BEGIN {
}
}
/<div class="Nd">/ {
# Make the description blurb inline, as with terminal output
gsub(/div/, "span")
}
BEGIN {
pages["gbz80", 7] = 1
pages["rgbds", 5] = 1
pages["rgbds", 7] = 1
pages["rgbasm", 1] = 1
pages["rgbasm", 5] = 1
pages["rgblink",1] = 1
pages["rgblink",5] = 1
pages["rgbfix", 1] = 1
pages["rgbgfx", 1] = 1
}
/<a class="Xr">/ {
# Link to other pages in the doc
for (i in pages) {
split(i, page, SUBSEP)
name = page[1]
section = page[2]
gsub(sprintf("<a class=\"Xr\">%s\\(%d\\)", name, section),
sprintf("<a class=\"Xr\" href=\"%s.%d.html\">%s(%d)", name, section, name, section))
}
}
{
# Make long opts (defined using `Fl Fl`) into a single tag
gsub(/<code class="Fl">-<\/code><code class="Fl">/, "<code class=\"Fl\">-")
gsub(/<code class="Fl">-<\/code>\s*<code class="Fl">/, "<code class=\"Fl\">-")
}
{
print
}
/<head>/ {
# Add viewport size <meta> tag for mobile users
print " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
}
/<link/ {
# Inject our own style overrides
print(" <link rel=\"stylesheet\" href=\"rgbds.css\" type=\"text/css\" media=\"all\"/>")
}
+113
View File
@@ -0,0 +1,113 @@
#!/bin/bash
usage() {
cat <<EOF
Usage: $0 [-h] [-r] <rgbds-www> <version>
Copy renders from RGBDS repository to rgbds-www documentation
Execute from the root folder of the RGBDS repo, checked out at the desired tag
<rgbds-www> : Path to the rgbds-www repository
<version> : Version to be copied, such as 'v0.4.1' or 'master'
-h Display this help message
-r Update "latest stable" redirection pages and add a new entry to the index
(use for releases, not master)
EOF
}
is_release=0
bad_usage=0
while getopts ":hr" opt; do
case $opt in
r)
is_release=1
;;
h)
usage
exit 0
;;
\?)
echo "Unknown option '$OPTARG'"
bad_usage=1
;;
esac
done
if [ $bad_usage -ne 0 ]; then
usage
exit 1
fi
shift $(($OPTIND - 1))
declare -A PAGES
PAGES=(
[rgbasm.1.html]=src/asm/rgbasm.1
[rgbasm.5.html]=src/asm/rgbasm.5
[rgblink.1.html]=src/link/rgblink.1
[rgblink.5.html]=src/link/rgblink.5
[rgbfix.1.html]=src/fix/rgbfix.1
[rgbgfx.1.html]=src/gfx/rgbgfx.1
[rgbds.5.html]=src/rgbds.5
[rgbds.7.html]=src/rgbds.7
[gbz80.7.html]=src/gbz80.7
)
WWWPATH="/docs"
mkdir -p "$1/_documentation/$2"
# `mandoc` uses a different format for referring to man pages present in the **current** directory.
# We want that format for RGBDS man pages, and the other one for the rest;
# we thus need to copy all pages to a temporary directory, and process them there.
# Copy all pages to current dir
cp "${PAGES[@]}" .
for page in "${!PAGES[@]}"; do
stem="${page%.html}"
manpage="${stem%.?}(${stem#*.})"
descr="$(awk -v 'FS=.Nd ' '/.Nd/ { print $2; }' "${PAGES[$page]}")"
cat >"$1/_documentation/$2/$page" <<EOF
---
layout: doc
title: $manpage [$2]
description: RGBDS $2 — $descr
---
EOF
options=fragment,man='%N.%S;https://linux.die.net/man/%S/%N'
if [ $stem = rgbasm.5 ]; then
options+=,toc
fi
mandoc -Thtml -I os=Linux -O$options "${PAGES[$page]##*/}" | .github/actions/doc_postproc.awk >> "$1/_documentation/$2/$page"
groff -Tpdf -mdoc -wall "${PAGES[$page]##*/}" >"$1/_documentation/$2/$stem.pdf"
if [ $is_release -ne 0 ]; then
cat - >"$1/_documentation/$page" <<EOF
---
redirect_to: $WWWPATH/$2/${page%.html}
permalink: $WWWPATH/${page%.html}/
title: $manpage [latest stable]
description: RGBDS latest stable — $descr
---
EOF
fi
done
cat - >"$1/_documentation/$2/index.html" <<EOF
---
layout: doc_index
permalink: /docs/$2/
title: RGBDS online manual [$2]
description: RGBDS $2 - Online manual
---
EOF
# If making a release, add a new entry right after `master`
if [ $is_release -ne 0 ]; then
awk '{ print }
/"name": "master"/ { print "\t\t{\"name\": \"'$2'\", \"text\": \"'$2'\" }," }
' "$1/_data/doc.json" >"$1/_data/doc.json.tmp"
mv "$1/_data/doc.json"{.tmp,}
fi
# Clean up
rm "${PAGES[@]##*/}"
+18
View File
@@ -0,0 +1,18 @@
case `echo $1 | cut -d '-' -f 1` in
ubuntu)
sudo apt-get -qq update
sudo apt-get install -yq bison libpng-dev pkg-config
;;
macos)
brew install bison libpng pkg-config md5sha1sum
# For the version check below exclusively, re-do this before building
export PATH="/usr/local/opt/bison/bin:$PATH"
;;
*)
echo "WARNING: Cannot install deps for OS '$1'"
;;
esac
bison --version
make --version
cmake --version
+25
View File
@@ -0,0 +1,25 @@
name: "Code style checking"
on: pull_request
jobs:
checkpatch:
runs-on: ubuntu-latest
steps:
- name: Set up repo
run: |
git clone -b "${{ github.event.pull_request.head.ref }}" "${{ github.event.pull_request.head.repo.clone_url }}" rgbds
cd rgbds
git remote add upstream "${{ github.event.pull_request.base.repo.clone_url }}"
git fetch upstream
- name: Set up checkpatch
working-directory: rgbds
run: |
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl'
chmod +x checkpatch.pl
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/const_structs.checkpatch'
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/spelling.txt'
- name: Checkpatch
working-directory: rgbds
run: |
make checkpatch CHECKPATCH=./checkpatch.pl "BASE_REF=${{ github.event.pull_request.base.sha }}" Q= | tee log
if grep -q ERROR: log; then exit 1; else exit 0; fi
@@ -0,0 +1,52 @@
name: "Create release docs"
on:
release:
types:
- released # This avoids triggering on pre-releases
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Checkout rgbds@release
uses: actions/checkout@v2
with:
path: rgbds
- name: Checkout rgbds-www@master
uses: actions/checkout@v2
with:
repository: ${{ github.repository_owner }}/rgbds-www
path: rgbds-www
# `-O toc` was added in 1.14.5, but the repos only have 1.14.4
- name: Build and install mandoc + install groff
run: |
sudo apt-get -qq update
sudo apt-get install -yq groff zlib1g-dev
wget 'http://mandoc.bsd.lv/snapshots/mandoc-1.14.5.tar.gz'
tar xf mandoc-1.14.5.tar.gz
cd mandoc-1.14.5
./configure
make
sudo make install
- name: Update pages
working-directory: rgbds
run: | # The ref appears to be in the format "refs/tags/<version>", so strip that
./.github/actions/get-pages.sh -r ../rgbds-www ${GITHUB_REF##*/}
- name: Push new pages
working-directory: rgbds-www
run: |
mkdir -p -m 700 ~/.ssh
cat > ~/.ssh/id_ed25519 <<<"${{ secrets.SSH_KEY_SECRET }}"
chmod 0600 ~/.ssh/id_ed25519
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519
git config --global user.name "GitHub Action"
git config --global user.email "[email protected]"
git add -A
git commit -m "Create RGBDS ${GITHUB_REF##*/} documentation"
if git remote | grep -q origin; then
git remote set-url origin [email protected]:${{ github.repository_owner }}/rgbds-www.git
else
git remote add origin [email protected]:${{ github.repository_owner }}/rgbds-www.git
fi
git push origin master
+200
View File
@@ -0,0 +1,200 @@
name: "Regression testing"
on:
- push
- pull_request
jobs:
unix-testing:
strategy:
matrix:
os: [ubuntu-20.04, ubuntu-18.04, ubuntu-16.04, macos-10.15]
cc: [gcc, clang]
buildsys: [make, cmake]
include:
- os: ubuntu-18.04
cc: gcc
target: develop
cmakevars: -DSANITIZERS=ON -DMORE_WARNINGS=ON -DCMAKE_BUILD_TYPE=Debug
- os: ubuntu-20.04
cc: gcc
target: develop
cmakevars: -DSANITIZERS=ON -DMORE_WARNINGS=ON -DCMAKE_BUILD_TYPE=Debug
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Install deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
# The `export` lines are to allow working on macOS...
# Apple's base version is severely outdated, not even supporting -Wall,
# but it overrides Homebrew's version nonetheless...
- name: Build & install using Make
run: |
export PATH="/usr/local/opt/bison/bin:$PATH"
make ${{ matrix.target }} -j Q= CC=${{ matrix.cc }}
sudo make install -j Q=
if: matrix.buildsys == 'make'
- name: Build & install using CMake
run: |
export PATH="/usr/local/opt/bison/bin:$PATH"
cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=${{ matrix.cc }} ${{ matrix.cmakevars }}
cmake --build build
cp build/src/rgb{asm,link,fix,gfx} .
sudo cmake --install build
if: matrix.buildsys == 'cmake'
- name: Package binaries
run: |
mkdir bins
cp rgb{asm,link,fix,gfx} bins
- name: Upload binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.buildsys }}
path: bins
- name: Test
shell: bash
run: |
test/run-tests.sh
windows-testing:
strategy:
matrix:
bits: [32, 64]
include:
- bits: 32
arch: x86
platform: Win32
- bits: 64
arch: x86_x64
platform: x64
fail-fast: false
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Get zlib, libpng and bison
run: | # TODO: use an array
$wc = New-Object System.Net.WebClient
$wc.DownloadFile('https://www.zlib.net/zlib1211.zip', 'zlib.zip')
$hash = (Get-FileHash "zlib.zip" -Algorithm SHA256).Hash
if ($hash -ne 'd7510a8ee1918b7d0cad197a089c0a2cd4d6df05fee22389f67f115e738b178d') {
Write-Host "zlib SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://download.sourceforge.net/libpng/lpng1637.zip', 'libpng.zip')
$hash = (Get-FileHash "libpng.zip" -Algorithm SHA256).Hash
if ($hash -ne '3b4b1cbd0bae6822f749d39b1ccadd6297f05e2b85a83dd2ce6ecd7d09eabdf2') {
Write-Host "libpng SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://github.com/lexxmark/winflexbison/releases/download/v2.5.23/win_flex_bison-2.5.23.zip', 'winflexbison.zip')
$hash = (Get-FileHash "winflexbison.zip" -Algorithm SHA256).Hash
if ($hash -ne '6AA5C8EA662DA1550020A5804C28BE63FFAA53486DA9F6842E24C379EC422DFC') {
Write-Host "bison SHA256 mismatch! ($hash)"
}
Expand-Archive -DestinationPath . "zlib.zip"
Expand-Archive -DestinationPath . "libpng.zip"
Expand-Archive -DestinationPath install_dir "winflexbison.zip"
Move-Item zlib-1.2.11 zlib
Move-Item lpng1637 libpng
- name: Build zlib
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
cmake -S zlib -B zbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
cmake --build zbuild --config Release
cmake --install zbuild
- name: Build libpng
run: |
cmake -S libpng -B pngbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
cmake --build pngbuild --config Release
cmake --install pngbuild
- name: Build Windows binaries
run: |
cmake -S . -B build -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release
cmake --install build
- name: Package binaries
shell: bash
run: |
mkdir bins
cp install_dir/bin/{rgbasm.exe,rgblink.exe,rgbfix.exe,rgbgfx.exe,zlib1.dll,libpng16.dll} bins
- name: Upload Windows binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-win${{ matrix.bits }}
path: bins
- name: Test
shell: bash
run: |
cp bins/* .
test/run-tests.sh
windows-xbuild:
strategy:
matrix:
bits: [32, 64]
os: [ubuntu-18.04]
include:
- bits: 32
arch: i686
triplet: i686-w64-mingw32
- bits: 64
arch: x86-64
triplet: x86_64-w64-mingw32
fail-fast: false
runs-on: ${{ matrix.os }}
env:
DIST_DIR: win${{ matrix.bits }}
steps:
- uses: actions/checkout@v2
- name: Install deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
- name: Install MinGW
run: |
sudo apt-get install gcc-mingw-w64-${{ matrix.arch }} mingw-w64-tools libz-mingw-w64-dev
- name: Install libpng dev headers for MinGW
run: |
sudo ./.github/actions/mingw-w64-libpng-dev.sh ${{ matrix.triplet }}
- name: Cross-build Windows binaries
run: |
make mingw${{ matrix.bits }} -j Q=
- name: Package binaries
run: |
mkdir bins
mv rgbasm bins/rgbasm.exe
mv rgblink bins/rgblink.exe
mv rgbfix bins/rgbfix.exe
mv rgbgfx bins/rgbgfx.exe
cp /usr/${{ matrix.triplet }}/lib/zlib1.dll bins
cp /usr/${{ matrix.triplet }}/bin/libpng16-16.dll bins
if [ ${{ matrix.bits }} -eq 32 ]; then cp /usr/lib/gcc/${{ matrix.triplet }}/7.3-win32/libgcc_s_sjlj-1.dll bins; fi
- name: Upload Windows binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-mingw-win${{ matrix.bits }}
path: bins
windows-xtesting:
needs: windows-xbuild
strategy:
matrix:
bits: [32, 64]
fail-fast: false
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Retrieve binaries
uses: actions/download-artifact@v1
with:
name: rgbds-canary-mingw-win${{ matrix.bits }}
path: bins
- name: Extract binaries
shell: bash
run: |
cp bins/* .
- name: Run tests
shell: bash
run: |
test/run-tests.sh
@@ -0,0 +1,65 @@
name: "Update master docs"
on:
push:
branches:
- master
paths:
- .github/actions/get-pages.sh
- src/gbz80.7
- src/rgbds.5
- src/rgbds.7
- src/asm/rgbasm.1
- src/asm/rgbasm.5
- src/link/rgblink.1
- src/link/rgblink.5
- src/fix/rgbfix.1
- src/gfx/rgbgfx.1
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Checkout rgbds@master
uses: actions/checkout@v2
with:
repository: gbdev/rgbds
ref: master
path: rgbds
- name: Checkout rgbds-www@master
uses: actions/checkout@v2
with:
repository: gbdev/rgbds-www
ref: master
path: rgbds-www
- name: Build and install mandoc + install groff
run: |
sudo apt-get -qq update
sudo apt-get install -yq groff zlib1g-dev
wget 'http://mandoc.bsd.lv/snapshots/mandoc-1.14.5.tar.gz'
tar xf mandoc-1.14.5.tar.gz
cd mandoc-1.14.5
./configure
make
sudo make install
- name: Update pages
working-directory: rgbds
run: |
./.github/actions/get-pages.sh ../rgbds-www master
- name: Push new pages
working-directory: rgbds-www
run: |
mkdir -p -m 700 ~/.ssh
echo "${{ secrets.SSH_KEY_SECRET }}" > ~/.ssh/id_ed25519
chmod 0600 ~/.ssh/id_ed25519
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519
git config --global user.name "GitHub Action"
git config --global user.email "[email protected]"
git add .
git commit -m "Update RGBDS master documentation"
if git remote | grep -q origin; then
git remote set-url origin [email protected]:gbdev/rgbds-www.git
else
git remote add origin [email protected]:gbdev/rgbds-www.git
fi
git push origin master
-14
View File
@@ -1,14 +0,0 @@
case `echo $1 | cut -d '-' -f 1` in
ubuntu)
sudo apt-get -qq update
sudo apt-get install -yq bison libpng-dev pkg-config
;;
macos)
brew install libpng pkg-config md5sha1sum
;;
*)
echo "WARNING: Cannot install deps for OS '$1'"
;;
esac
yacc --version
-17
View File
@@ -1,17 +0,0 @@
name: "Code style checking"
on: pull_request
jobs:
checkpatch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up checkpatch
run: |
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl'
chmod +x checkpatch.pl
touch const_structs.checkpatch
touch spelling.txt
- name: Checkpatch
run: |
make checkpatch CHECKPATCH=./checkpatch.pl BASE_REF=${{ github.base_ref }} Q=
@@ -0,0 +1,96 @@
name: "Create release artifacts"
on:
push:
tags:
- v[0-9]*
jobs:
windows:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Get version from tag
shell: bash
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
VERSION="${{ github.ref }}"
echo "version=${VERSION##*/v}" >> $GITHUB_ENV
- name: Get zlib, libpng and bison
run: | # TODO: use an array
$wc = New-Object System.Net.WebClient
$wc.DownloadFile('https://www.zlib.net/zlib1211.zip', 'zlib.zip')
$hash = (Get-FileHash "zlib.zip" -Algorithm SHA256).Hash
if ($hash -ne 'd7510a8ee1918b7d0cad197a089c0a2cd4d6df05fee22389f67f115e738b178d') {
Write-Host "zlib SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://download.sourceforge.net/libpng/lpng1637.zip', 'libpng.zip')
$hash = (Get-FileHash "libpng.zip" -Algorithm SHA256).Hash
if ($hash -ne '3b4b1cbd0bae6822f749d39b1ccadd6297f05e2b85a83dd2ce6ecd7d09eabdf2') {
Write-Host "libpng SHA256 mismatch! ($hash)"
exit 1
}
$wc.DownloadFile('https://github.com/lexxmark/winflexbison/releases/download/v2.5.23/win_flex_bison-2.5.23.zip', 'winflexbison.zip')
$hash = (Get-FileHash "winflexbison.zip" -Algorithm SHA256).Hash
if ($hash -ne '6AA5C8EA662DA1550020A5804C28BE63FFAA53486DA9F6842E24C379EC422DFC') {
Write-Host "bison SHA256 mismatch! ($hash)"
}
Expand-Archive -DestinationPath . "zlib.zip"
Expand-Archive -DestinationPath . "libpng.zip"
Expand-Archive -DestinationPath install_dir "winflexbison.zip"
Move-Item zlib-1.2.11 zlib
Move-Item lpng1637 libpng
- name: Build 32-bit zlib
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
cmake -S zlib -B zbuild32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
cmake --build zbuild32 --config Release
cmake --install zbuild32
- name: Build 32-bit libpng
run: |
cmake -S libpng -B pngbuild32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
cmake --build pngbuild32 --config Release
cmake --install pngbuild32
- name: Build 32-bit Windows binaries
run: |
cmake -S . -B build32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
cmake --build build32 --config Release
cmake --install build32
- name: Package 32-bit binaries
run: |
Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/zlib1.dll", "install_dir/bin/libpng16.dll") "rgbds-${{ env.version }}-win32.zip"
- name: Build 64-bit zlib
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
cmake -S zlib -B zbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
cmake --build zbuild64 --config Release
cmake --install zbuild64
- name: Build 64-bit libpng
run: |
cmake -S libpng -B pngbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
cmake --build pngbuild64 --config Release
cmake --install pngbuild64
- name: Build 64-bit Windows binaries
run: |
cmake -S . -B build64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
cmake --build build64 --config Release
cmake --install build64
- name: Package 64-bit binaries
run: |
Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/zlib1.dll", "install_dir/bin/libpng16.dll") "rgbds-${{ env.version }}-win64.zip"
- name: Package sources
run: |
make dist
- name: Release
uses: softprops/action-gh-release@v1
with:
body: |
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...
prerelease: ${{ contains(github.ref, '-rc') }}
files: |
rgbds-${{ env.version }}-win32.zip
rgbds-${{ env.version }}-win64.zip
rgbds-${{ env.version }}.tar.gz
fail_on_unmatched_files: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-107
View File
@@ -1,107 +0,0 @@
name: "Regression testing"
on: push
jobs:
unix-testing:
strategy:
matrix:
os: [ubuntu-18.04, ubuntu-16.04, macos-10.15]
cc: [gcc, clang]
include:
- os: ubuntu-18.04
cc: gcc
target: develop
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Install deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
- name: Build
run: |
make ${{ matrix.target }} -j Q= CC=${{ matrix.cc }}
- name: Install
run: |
sudo make install -j Q=
- name: Package binaries
run: |
mkdir bins
cp rgb{asm,link,fix,gfx} bins
- name: Upload binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-${{ matrix.os }}-${{ matrix.cc }}
path: bins
- name: Test
shell: bash
run: |
test/run-tests.sh
windows-build:
strategy:
matrix:
bits: [32, 64]
os: [ubuntu-latest]
include:
- bits: 32
arch: i686
triplet: i686-w64-mingw32
- bits: 64
arch: x86-64
triplet: x86_64-w64-mingw32
runs-on: ${{ matrix.os }}
env:
DIST_DIR: win${{ matrix.bits }}
steps:
- uses: actions/checkout@v2
- name: Install deps
shell: bash
run: |
./.github/actions/install_deps.sh ${{ matrix.os }}
- name: Install MinGW
run: |
sudo apt-get install gcc-mingw-w64-${{ matrix.arch }} mingw-w64-tools libz-mingw-w64-dev
- name: Install libpng dev headers for MinGW
run: |
sudo ./.github/actions/mingw-w64-libpng-dev.sh ${{ matrix.triplet }}
- name: Build Windows binaries
run: |
make mingw${{ matrix.bits }} -j Q=
- name: Package binaries
run: |
mkdir bins
mv rgbasm bins/rgbasm.exe
mv rgblink bins/rgblink.exe
mv rgbfix bins/rgbfix.exe
mv rgbgfx bins/rgbgfx.exe
cp /usr/${{ matrix.triplet }}/lib/zlib1.dll bins
cp /usr/${{ matrix.triplet }}/bin/libpng16-16.dll bins
if [ ${{ matrix.bits }} -eq 32 ]; then cp /usr/lib/gcc/${{ matrix.triplet }}/7.3-win32/libgcc_s_sjlj-1.dll bins; fi
- name: Upload Windows binaries
uses: actions/upload-artifact@v1
with:
name: rgbds-canary-win${{ matrix.bits }}
path: bins
windows-testing:
needs: windows-build
strategy:
matrix:
bits: [32, 64]
runs-on: windows-2019
steps:
- uses: actions/checkout@v2
- name: Retrieve binaries
uses: actions/download-artifact@v1
with:
name: rgbds-canary-win${{ matrix.bits }}
path: bins
- name: Extract binaries
shell: bash
run: |
cp bins/* .
- name: Run tests
shell: bash
run: |
test/run-tests.sh
+4
View File
@@ -5,7 +5,11 @@ rgbgfx
rgbshim.sh
*.o
*.exe
*.dll
.checkpatch-camelcase.*
CMakeCache.txt
CMakeFiles
cmake_install.cmake
test/pokecrystal
test/pokered
+97
View File
@@ -0,0 +1,97 @@
#
# This file is part of RGBDS.
#
# Copyright (c) 2020 RGBDS contributors.
#
# SPDX-License-Identifier: MIT
#
# 3.9 required for LTO checks
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
project(rgbds
LANGUAGES C)
# get real path of source and binary directories
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
get_filename_component(bindir "${CMAKE_BINARY_DIR}" REALPATH)
# reject in-source builds, may conflict with Makefile
if(srcdir STREQUAL bindir)
message("RGBDS should not be built in the source directory.")
message("Instead, create a separate build directory and specify to CMake the path to the source directory.")
message(FATAL_ERROR "Terminating configuration")
endif()
option(SANITIZERS "Build with sanitizers enabled" OFF) # Ignored on MSVC
option(MORE_WARNINGS "Turn on more warnings" OFF) # Ignored on MSVC
option(TRACE_PARSER "Trace parser execution" OFF)
option(TRACE_LEXER "Trace lexer execution" OFF)
if(MSVC)
# MSVC's standard library triggers warning C5105,
# "macro expansion producing 'defined' has undefined behavior"
add_compile_options(/std:c11 /W1 /MP /wd5105)
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
else()
add_compile_options(-Wall -pedantic)
if(SANITIZERS)
set(SAN_FLAGS -fsanitize=shift -fsanitize=integer-divide-by-zero
-fsanitize=unreachable -fsanitize=vla-bound
-fsanitize=signed-integer-overflow -fsanitize=bounds
-fsanitize=object-size -fsanitize=bool -fsanitize=enum
-fsanitize=alignment -fsanitize=null)
add_compile_options(${SAN_FLAGS})
link_libraries(${SAN_FLAGS})
endif()
if(MORE_WARNINGS)
add_compile_options(-Werror -Wextra -Wno-type-limits
-Wno-sign-compare -Wvla -Wformat -Wformat-security -Wformat-overflow=2
-Wformat-truncation=1 -Wformat-y2k -Wswitch-enum -Wunused
-Wuninitialized -Wunknown-pragmas -Wstrict-overflow=5
-Wstringop-overflow=4 -Walloc-zero -Wduplicated-cond
-Wfloat-equal -Wshadow -Wcast-qual -Wcast-align -Wlogical-op
-Wnested-externs -Wno-aggressive-loop-optimizations -Winline
-Wundef -Wstrict-prototypes -Wold-style-definition)
endif()
endif()
# Use versioning consistent with Makefile
# the git revision is used but uses the fallback in an archive
execute_process(COMMAND git describe --tags --dirty --always
OUTPUT_VARIABLE GIT_REV
ERROR_QUIET)
string(STRIP "${GIT_REV}" GIT_REV)
include_directories("${PROJECT_SOURCE_DIR}/include")
add_definitions(-DBUILD_VERSION_STRING="${GIT_REV}")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
add_subdirectory(src)
# By default, build in Release mode; Debug mode must be explicitly requested
# (You may want to augment it with the options above)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
message(CHECK_START "Checking if LTO is supported")
include(CheckIPOSupported)
check_ipo_supported(RESULT enable_lto)
if(enable_lto)
message(CHECK_PASS "yes")
set_property(TARGET rgbasm rgblink rgbfix rgbgfx PROPERTY INTERPROCEDURAL_OPTIMIZATION ON)
else()
message(CHECK_FAIL "no")
endif()
endif()
if(TRACE_PARSER)
target_compile_definitions(rgbasm PRIVATE -DYYDEBUG)
endif()
if(TRACE_LEXER)
target_compile_definitions(rgbasm PRIVATE -DLEXER_DEBUG)
endif()
+2
View File
@@ -40,6 +40,8 @@ Other contributors
- Quint Guvernator <[email protected]>
- Rangi <http://github.com/Rangi42>
- Sanqui <[email protected]>
- YamaArashi <[email protected]>
+1 -2
View File
@@ -7,8 +7,7 @@
FROM alpine:latest
RUN apk add --update \
build-base \
byacc \
flex \
bison \
libpng-dev
COPY . /rgbds
WORKDIR /rgbds
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
Copyright (c) 1997-2020, Carsten Sorensen and RGBDS contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
+52 -54
View File
@@ -14,10 +14,10 @@
Q := @
PREFIX := /usr/local
bindir := ${PREFIX}/bin
mandir := ${PREFIX}/man
mandir := ${PREFIX}/share/man
STRIP := -s
BINMODE := 555
MANMODE := 444
BINMODE := 755
MANMODE := 644
CHECKPATCH := ../linux/scripts/checkpatch.pl
# Other variables
@@ -27,24 +27,25 @@ PNGCFLAGS := `${PKG_CONFIG} --cflags libpng`
PNGLDFLAGS := `${PKG_CONFIG} --libs-only-L libpng`
PNGLDLIBS := `${PKG_CONFIG} --libs-only-l libpng`
# Note: if this comes up empty, `version.c` will automatically fall back to last release number
VERSION_STRING := `git describe --tags --dirty --always 2>/dev/null`
WARNFLAGS := -Wall
# Overridable CFLAGS
CFLAGS := -O3
CFLAGS ?= -O3 -flto -DNDEBUG
# Non-overridable CFLAGS
REALCFLAGS := ${CFLAGS} ${WARNFLAGS} -std=c11 -D_POSIX_C_SOURCE=200809L \
-D_DEFAULT_SOURCE -Iinclude
REALCFLAGS := ${CFLAGS} ${WARNFLAGS} -std=gnu11 -D_POSIX_C_SOURCE=200809L \
-Iinclude
# Overridable LDFLAGS
LDFLAGS :=
LDFLAGS ?=
# Non-overridable LDFLAGS
REALLDFLAGS := ${LDFLAGS} ${WARNFLAGS} \
-DBUILD_VERSION_STRING=\"${VERSION_STRING}\"
YFLAGS :=
YFLAGS ?= -Wall
YACC := yacc
BISON := bison
RM := rm -rf
# Rules to build the RGBDS binaries
@@ -52,14 +53,15 @@ RM := rm -rf
all: rgbasm rgblink rgbfix rgbgfx
rgbasm_obj := \
src/asm/asmy.o \
src/asm/charmap.o \
src/asm/fixpoint.o \
src/asm/format.o \
src/asm/fstack.o \
src/asm/globlex.o \
src/asm/lexer.o \
src/asm/macro.o \
src/asm/main.o \
src/asm/math.o \
src/asm/parser.o \
src/asm/opt.o \
src/asm/output.o \
src/asm/rpn.o \
src/asm/section.o \
@@ -70,9 +72,10 @@ rgbasm_obj := \
src/extern/getopt.o \
src/extern/utf8decoder.o \
src/hashmap.o \
src/linkdefs.o
src/linkdefs.o \
src/opmath.o
src/asm/globlex.o src/asm/lexer.o src/asm/constexpr.o: src/asm/asmy.h
src/asm/lexer.o src/asm/main.o: src/asm/parser.h
rgblink_obj := \
src/link/assign.o \
@@ -86,7 +89,8 @@ rgblink_obj := \
src/extern/err.o \
src/extern/getopt.o \
src/hashmap.o \
src/linkdefs.o
src/linkdefs.o \
src/opmath.o
rgbfix_obj := \
src/fix/main.o \
@@ -114,21 +118,32 @@ rgbgfx: ${rgbgfx_obj}
# Rules to process files
# We want the yacc invocations to pass through our rules, not default ones
# We want the Bison invocation to pass through our rules, not default ones
.y.o:
# yacc-generated C files have an accompanying header
.c.h:
# Bison-generated C files have an accompanying header
src/asm/parser.h: src/asm/parser.c
$Qtouch $@
.y.c:
$Q${YACC} -d ${YFLAGS} -o $@ $<
src/asm/parser.c: src/asm/parser.y
$QDEFS=; \
add_flag(){ \
if src/check_bison_ver.sh $$1 $$2; then \
DEFS="-D$$3 $$DEFS"; \
fi \
}; \
add_flag 3 5 api.token.raw=true; \
add_flag 3 6 parse.error=detailed; \
add_flag 3 0 parse.error=verbose; \
add_flag 3 0 parse.lac=full; \
add_flag 3 0 lr.type=ielr; \
echo "DEFS=$$DEFS"; \
${BISON} $$DEFS -d ${YFLAGS} -o $@ $<
.c.o:
$Q${CC} ${REALCFLAGS} ${PNGCFLAGS} -c -o $@ $<
# Target used to remove all files generated by other Makefile targets, except
# for the html documentation.
# Target used to remove all files generated by other Makefile targets
clean:
$Q${RM} rgbasm rgbasm.exe
@@ -137,16 +152,7 @@ clean:
$Q${RM} rgbgfx rgbgfx.exe
$Qfind src/ -name "*.o" -exec rm {} \;
$Q${RM} rgbshim.sh
$Q${RM} src/asm/asmy.c src/asm/asmy.h
# Target used to remove all html files generated by the wwwman target
cleanwwwman:
$Q${RM} docs/rgbds.7.html docs/gbz80.7.html docs/rgbds.5.html
$Q${RM} docs/rgbasm.1.html docs/rgbasm.5.html
$Q${RM} docs/rgblink.1.html docs/rgblink.5.html
$Q${RM} docs/rgbfix.1.html
$Q${RM} docs/rgbgfx.1.html
$Q${RM} src/asm/parser.c src/asm/parser.h
# Target used to install the binaries and man pages.
@@ -188,34 +194,19 @@ checkpatch:
for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \
echo "[*] Analyzing commit '$$commit'"; \
git format-patch --stdout "$$commit~..$$commit" \
-- src include '!src/extern' '!include/extern' \
| ${CHECKPATCH} - || true; \
done
# Target for the project maintainer to easily create web manuals.
# It relies on mandoc: http://mdocml.bsd.lv
MANDOC := -Thtml -Ios=General -Oman=%N.%S.html -Ostyle=mandoc.css
wwwman:
$Qmandoc ${MANDOC} src/rgbds.7 | src/doc_postproc.awk > docs/rgbds.7.html
$Qmandoc ${MANDOC} src/gbz80.7 | src/doc_postproc.awk > docs/gbz80.7.html
$Qmandoc ${MANDOC} src/rgbds.5 | src/doc_postproc.awk > docs/rgbds.5.html
$Qmandoc ${MANDOC} src/asm/rgbasm.1 | src/doc_postproc.awk > docs/rgbasm.1.html
$Qmandoc ${MANDOC} src/asm/rgbasm.5 | src/doc_postproc.awk > docs/rgbasm.5.html
$Qmandoc ${MANDOC} src/fix/rgbfix.1 | src/doc_postproc.awk > docs/rgbfix.1.html
$Qmandoc ${MANDOC} src/link/rgblink.1 | src/doc_postproc.awk > docs/rgblink.1.html
$Qmandoc ${MANDOC} src/link/rgblink.5 | src/doc_postproc.awk > docs/rgblink.5.html
$Qmandoc ${MANDOC} src/gfx/rgbgfx.1 | src/doc_postproc.awk > docs/rgbgfx.1.html
# This target is used during development in order to prevent adding new issues
# to the source code. All warnings are treated as errors in order to block the
# compilation and make the continous integration infrastructure return failure.
develop:
$Qenv $(MAKE) -j WARNFLAGS="-Werror -Wall -Wextra -Wpedantic \
-Wno-sign-compare -Wformat -Wformat-security -Wformat-overflow=2 \
$Qenv $(MAKE) -j WARNFLAGS="-Werror -Wall -Wextra -Wpedantic -Wno-type-limits \
-Wno-sign-compare -Wvla -Wformat -Wformat-security -Wformat-overflow=2 \
-Wformat-truncation=1 -Wformat-y2k -Wswitch-enum -Wunused \
-Wuninitialized -Wunknown-pragmas -Wstrict-overflow=5 \
-Wuninitialized -Wunknown-pragmas -Wstrict-overflow=4 \
-Wstringop-overflow=4 -Walloc-zero -Wduplicated-cond \
-Wfloat-equal -Wshadow -Wcast-qual -Wcast-align -Wlogical-op \
-Wnested-externs -Wno-aggressive-loop-optimizations -Winline \
@@ -224,7 +215,7 @@ develop:
-fsanitize=unreachable -fsanitize=vla-bound \
-fsanitize=signed-integer-overflow -fsanitize=bounds \
-fsanitize=object-size -fsanitize=bool -fsanitize=enum \
-fsanitize=alignment -fsanitize=null -DDEVELOP" CFLAGS="-g -O0"
-fsanitize=alignment -fsanitize=null" CFLAGS="-ggdb3 -O0"
# Targets for the project maintainer to easily create Windows exes.
# This is not for Windows users!
@@ -232,11 +223,11 @@ develop:
# install instructions instead.
mingw32:
$Qmake CC=i686-w64-mingw32-gcc YACC=bison \
$Qmake CC=i686-w64-mingw32-gcc BISON=bison \
PKG_CONFIG=i686-w64-mingw32-pkg-config -j
mingw64:
$Qmake CC=x86_64-w64-mingw32-gcc YACC=bison \
$Qmake CC=x86_64-w64-mingw32-gcc BISON=bison \
PKG_CONFIG=x86_64-w64-mingw32-pkg-config -j
wine-shim:
@@ -247,3 +238,10 @@ wine-shim:
$Qln -s rgbshim.sh rgblink
$Qln -s rgbshim.sh rgbfix
$Qln -s rgbshim.sh rgbgfx
# Target for the project maintainer to produce distributable release tarballs
# of the source code.
dist:
$Qgit ls-files | sed s~^~$${PWD##*/}/~ \
| tar -czf rgbds-`git describe --tags | cut -c 2-`.tar.gz -C .. -T -
+58 -129
View File
@@ -15,160 +15,87 @@ 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://rednex.github.io/rgbds/>`__, it is generated from the man pages
`here <https://rgbds.gbdev.io/docs/>`__, it is generated from the man pages
found in this repository.
1. Installing RGBDS
-------------------
1.1 Windows
~~~~~~~~~~~
Windows builds are available in the releases page on GitHub
`here <https://github.com/rednex/rgbds/releases>`__.
Extract the zip and then add the executable directory to the path. For example:
::
path %PATH%;C:\Programs\rgbds-0.3.8-win64\win64
Alternatively, the RGBDS executables can be simply dropped in the folder of the project they're used in.
If you require the latest version in development, it should be possible to
compile RGBDS with MinGW or Cygwin by following the instructions to build it on
UNIX systems.
1.2 macOS
~~~~~~~~~
You can build RGBDS by following the instructions below. However, if you would
prefer not to build RGBDS yourself, you may also install it using
`Homebrew <http://brew.sh/>`__.
To install the latest release, use:
.. code:: sh
brew install rgbds
To install RGBDS with all of the current changes in development (as seen on the
``master`` branch on GitHub), use:
.. code:: sh
brew install rgbds --HEAD
1.3 Arch Linux
~~~~~~~~~~~~~~
To install RGBDS through the AUR run
.. code:: sh
yaourt -S rgbds
1.4 Other UNIX-like systems
~~~~~~~~~~~~~~~~~~~~~~~~~~~
No official binaries of RGBDS are distributed for these systems, you must follow
the simple instructions below to compile and install it.
2. Building RGBDS from source
-----------------------------
RGBDS can be built in UNIX-like systems by following the instructions below.
2.1 Dependencies
~~~~~~~~~~~~~~~~
RGBDS requires yacc, libpng and pkg-config to be installed.
On macOS, install the latter two with `Homebrew <http://brew.sh/>`__:
.. code:: sh
brew install libpng pkg-config
On other Unixes, use the built-in package manager. For example, on Debian or
Ubuntu:
.. code:: sh
sudo apt-get install byacc flex pkg-config libpng-dev
You can test if libpng and pkg-config are installed by running ``pkg-config
--cflags libpng``: if the output is a path, then you're good, and if it outputs
an error then you need to install them via a package manager.
2.2 Build process
~~~~~~~~~~~~~~~~~
To build the programs, run in your terminal:
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
Then, to install the compiled programs and manual pages, run (with appropriate
privileges, e.g, with ``sudo``):
sudo make install
.. code:: sh
make install
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
cmake --install build
After installation, you can read the manuals with the ``man`` command. E.g.,
2. RGBDS Folder Organization
----------------------------
.. code:: sh
The RGBDS source code file structure somewhat resembles the following:
man 7 rgbds
::
There are some variables in the Makefile that can be redefined by the user. The
variables described below can affect installation behavior when given on the
make command line. For example, to install RGBDS in your home directory instead
of systemwide, run the following:
.
├── .github/
│   ├── actions/
│   │   └── ...
│   └── workflows/
│      └── ...
├── contrib/
│   ├── zsh_compl/
│   │   └── ...
│   └── ...
├── include/
│   └── ...
├── src/
│   ├── asm/
│   │   └── ...
│   ├── extern/
│   │   └── ...
│   ├── fix/
│   │   └── ...
│   ├── gfx/
│   │   └── ...
│   ├── link/
│   │   └── ...
│   ├── CMakeLists.txt
│   └── ...
├── test/
│   ├── ...
│ └── run-tests.sh
├── CMakeLists.txt
├── Makefile
└── README.rst
.. code:: sh
- ``.github/`` - files and scripts related to the integration of the RGBDS codebase with
GitHub.
make install PREFIX=$HOME
- ``contrib/`` - scripts and other resources which may be useful to users and developers of
RGBDS.
To do a verbose build, run:
* ``zsh_compl`` contains tab completion scripts for use with zsh. Put them somewhere in your ``fpath``, and they should auto-load.
.. code:: sh
- ``include/`` - header files for each respective C files in `src`.
make Q=
- ``src/`` - source code and manual pages for RGBDS.
This is the complete list of user-defined variables:
* 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.
- ``PREFIX``: Location where RGBDS will be installed. Defaults to
``/usr/local``.
- ``test/`` - testing framework used to verify that changes to the code don't break or modify the behavior of RGBDS.
- ``bindir``: Location where the binaries will be installed. Defaults to
``${PREFIX}/bin``.
3. History
----------
- ``mandir``: Location where the manpages will be installed. Defaults to
``${PREFIX}/man``.
- ``DESTDIR``: This is prepended to all paths during the installation. It is
mainly used for packaging.
- ``Q``: Whether to quiet the build or not. To make the build more verbose,
clear this variable. Defaults to ``@``.
- ``STRIP``: Whether to strip the installed binaries of debug symbols or not.
Defaults to ``-s``.
- ``BINMODE``: Permissions of the installed binaries. Defaults to ``555``.
- ``MANMODE``: Permissions of the installed manpages. Defaults to ``444``.
- ``CHECKPATCH``: Path of the script ``checkpatch.pl`` of the Linux kernel.
Defaults to ``../linux/scripts/checkpatch.pl``.
3 History
---------
- Around 1997, Carsten Sorensen (AKA SurfSmurf) writes ASMotor as a
- 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
@@ -184,3 +111,5 @@ This is the complete list of user-defined variables:
- 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.
+12 -10
View File
@@ -31,31 +31,33 @@ diff <(xxd $1) <(xxd $2) | while read -r LINE; do
# Separator between files switches states
echo $LINE
STATE=3
elif echo $LINE | grep -Eq '^[0-9]+(,[0-9]+)?c[0-9]+(,[0-9]+)?'; then
elif grep -Eq '^[0-9]+(,[0-9]+)?[cd][0-9]+(,[0-9]+)?' <<< "$LINE"; then
# Line info resets the whole thing
STATE=1
elif [ $STATE -eq 1 -o $STATE -eq 3 ]; then
# Compute the GB address from the ROM offset
OFS=$(echo $LINE | cut -d ' ' -f 2 | tr -d ':')
OFS=$(cut -d ' ' -f 2 <<< "$LINE" | tr -d ':')
BANK=$((0x$OFS / 0x4000))
ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000))
# Try finding the preceding symbol closest to the diff
if [ $STATE -eq 1 ]; then
STATE=2
SYMFILE=$(echo $1 | cut -d '.' -f 1).sym
SYMFILE=${1%.*}.sym
else
STATE=4
SYMFILE=$(echo $2 | cut -d '.' -f 1).sym
SYMFILE=${2%.*}.sym
fi
EXTRA=$(if [ -f "$SYMFILE" ]; then
# Read the sym file for such a symbol
# Ignore comment lines, only pick matching bank
grep -Fv ';' "$SYMFILE" |
grep -Ei $(printf "^%02x:" $BANK) |
# (The bank regex ignores comments already, make `cut` and `tr` process less lines)
grep -Ei $(printf "^%02x:" $BANK) "$SYMFILE" |
cut -d ';' -f 1 |
tr -d "\r" |
while read -r SYMADDR SYM; do
SYMADDR=$((0x$(echo $SYMADDR | cut -d ':' -f 2)))
SYMADDR=$((0x${SYMADDR#*:}))
if [ $SYMADDR -le $ADDR ]; then
printf " (%s+%#x)\n" $SYM $(($ADDR - $SYMADDR))
printf " (%s+%#x)\n" "$SYM" $(($ADDR - $SYMADDR))
fi
# TODO: assumes sorted sym files
done | tail -n 1
@@ -63,9 +65,9 @@ diff <(xxd $1) <(xxd $2) | while read -r LINE; do
printf "%02x:%04x %s\n" $BANK $ADDR $EXTRA
fi
if [ $STATE -eq 2 -o $STATE -eq 4 ]; then
OFS=$(echo $LINE | cut -d ' ' -f 2 | tr -d ':')
OFS=$(cut -d ' ' -f 2 <<< "$LINE" | tr -d ':')
BANK=$((0x$OFS / 0x4000))
ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000))
printf "%s %02x:%04x: %s\n" "$(echo $LINE | cut -d ' ' -f 1)" $BANK $ADDR "$(echo $LINE | cut -d ' ' -f 3-)"
printf "%s %02x:%04x: %s\n" "${LINE:0:1}" $BANK $ADDR "${LINE#*: }"
fi
done
+49
View File
@@ -0,0 +1,49 @@
#compdef rgbasm
_rgbasm_warnings() {
local warnings=(
'error:Turn all warnings into errors'
'all:Enable most warning messages'
'extra:Enable extra, possibly unwanted, messages'
'everything:Enable literally everything'
'assert:Warn when WARN-type asserts fail'
'builtin-args:Report incorrect args to built-in funcs'
'div:Warn when dividing the smallest int by -1'
'empty-entry:Warn on empty entries in db, dw, dl args'
'large-constant:Warn on constants too large for a signed 32-bit int'
'long-string:Warn on strings too long'
'obsolete:Warn when using deprecated features'
'shift:Warn when shifting negative values'
'shift-amount:Warn when a shift'\''s operand it negative or \> 32'
'truncation:Warn when implicit truncations lose bits'
'user:Warn when executing the WARN built-in'
)
# TODO: handle `no-` and `error=` somehow?
_describe warning warnings
}
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-E --export-all)'{-E,--export-all}'[Export all symbols]'
'(-h --halt-without-nop)'{-h,--halt-without-nop}'[Avoid outputting a `nop` after `halt`]'
'(-L ---preserve-ld)'{-L,--preserve-ld}'[Prevent auto-optimizing `ld` into `ldh`]'
'(-v --verbose)'{-v,--verbose}'[Print additional messages regarding progression]'
-w'[Disable all warnings]'
'(-b --binary-digits)'{-b,--binary-digits}'+[Change chars for binary constants]:digit spec:'
'(-D --define)'{-D,--define}'+[Define a string symbol]:name + value (default 1):'
'(-g --gfx-chars)'{-g,--gfx-chars}'+[Change chars for gfx constants]:chars spec:'
'(-i --include)'{-i,--include}'+[Add an include directory]:include path:_files -/'
'(-M --dependfile)'{-M,--dependfile}"+[List deps in make format]:output file:_files -g '*.{d,mk}"
'(-o --output)'{-o,--output}'+[Output file]:output file:_files'
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
'(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:'
'(-W --warning)'{-W,--warning}'+[Toggle warning flags]:warning flag:_rgbasm_warnings'
'*'":assembly sources:_files -g '*.asm'"
)
_arguments -s -S : $args
+25
View File
@@ -0,0 +1,25 @@
#compdef rgbfix
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-C --color-only)'{-C,--color-only}'[Mark ROM as GBC-only]'
'(-c --color-compatible)'{-c,--color-compatible}'[Mark ROM as GBC-compatible]'
'(-j --non-japanese)'{-j,--non-japanese}'[Set the non-Japanese region flag]'
'(-s --sgb-compatible)'{-s,--sgb-compatible}'[Set the SGB flag]'
'(-f --fix-spec -v --validate)'{-v,--validate}'[Shorthand for -f lhg]'
'(-f --fix-spec -v --validate)'{-f,--fix-spec}'+[Fix or trash some header values]:fix spec:'
'(-i --game-id)'{-i,--game-id}'+[Set game ID string]:4-char game ID:'
'(-k --new-licensee)'{-k,--new-licensee}'+[Set new licensee string]:2-char licensee ID:'
'(-l --old-licensee)'{-l,--old-licensee}'+[Set old licensee ID]:licensee number:'
'(-m --mbc-type)'{-m,--mbc-type}'+[Set MBC flags]:mbc flags byte:'
'(-n --rom-version)'{-n,--rom-version}'+[Set ROM version]:rom version byte:'
'(-p --pad-value)'{-p,--pad-value}'+[Pad to next valid size using this byte as padding]:padding byte:'
'(-r --ram-size)'{-r,--ram-size}'+[Set RAM size]:ram size byte:'
'(-t --title)'{-t,--title}'+[Set title string]:11-char title string:'
'*'":ROM files:_files -g '*.{gb,sgb,gbc}'"
)
_arguments -s -S : $args
+37
View File
@@ -0,0 +1,37 @@
#compdef rgbgfx
_depths() {
local depths=(
'1:1bpp'
'2:2bpp (native)'
)
_describe 'bit depth' depths
}
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-a --attr-map -A --output-attr-map)'{-A,--output-attr-map}'[Shortcut for -a <file>.attrmap]'
'(-C --color-curve)'{-C,--color-curve}'[Generate palettes using GBC color curve]'
'(-D --debug)'{-D,--debug}'[Enable debug features]'
'(-f --fix -F --fix-and-save)'{-f,--fix}'[Fix input PNG into an indexed image]'
'(-f --fix -F --fix-and-save)'{-F,--fix-and-save}'[Like -f but also save CLI params within the PNG]'
'(-h --horizontal)'{-h,--horizontal}'[Lay out tiles horizontally instead of vertically]'
'(-m --mirror-tiles)'{-m,--mirror-tiles}'[Eliminate mirrored tiles from output]'
'(-p --palette -P --output-palette)'{-P,--output-palette}'[Shortcut for -p <file>.pal]'
'(-t --tilemap -T --output-tilemap)'{-T,--output-tilemap}'[Shortcut for -t <file>.tilemap]'
'(-u --unique-tiles)'{-u,--unique-tiles}'[Eliminate redundant tiles]'
'(-v --verbose)'{-v,--verbose}'[Enable verbose output]'
'(-a --attr-map -A --output-attr-map)'{-a,--attr-map}'+[Generate a map of tile attributes (mirroring)]:attrmap file:_files'
'(-d --depth)'{-d,--depth}'+[Set bit depth]:bit depth:_depths'
'(-o --output)'{-o,--output}'+[Set output file]:output file:_files'
'(-p --palette -P --output-palette)'{-p,--palette}"+[Output the image's palette in little-endian native RGB555 format]:palette file:_files"
'(-t --tilemap -T --output-tilemap)'{-t,--tilemap}'+[Generate a map of tile indices]:tilemap file:_files'
'(-x --trim-end)'{-x,--trim-end}'+[Trim end of output by this many tiles]:tile count:'
'*'":input png files:_files -g '*.png'"
)
_arguments -s -S : $args
+22
View File
@@ -0,0 +1,22 @@
#compdef rgblink
local args=(
# Arguments are listed here in the same order as in the manual, except for the version
'(- : * options)'{-V,--version}'[Print version number]'
'(-d --dmg)'{-d,--dmg}'[Enable DMG mode (-w + no VRAM banking)]'
'(-t --tiny)'{-t,--tiny}'[Enable tiny mode, disabling ROM banking]'
'(-v --verbose)'{-v,--verbose}'[Enable verbose output]'
'(-w --wramx)'{-w,--wramx}'[Disable WRAM banking]'
'(-l --linkerscript)'{-l,--linkerscript}"+[Use a linker script]:linker script:_files -g '*.link'"
'(-m --map)'{-m,--map}"+[Produce a map file]:map file:_files -g '*.map'"
'(-n --sym)'(-n,--sym)"+[Produce a symbol file]:sym file:_files -g '*.sym'"
'(-O --overlay)'{-O,--overlay}'+[Overlay sections over on top of bin file]:base overlay:_files'
'(-o --output)'{-o,--output}"+[Write ROM image to this file]:rom file:_files -g '*.{gb,sgb,gbc}'"
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
'(-s --smart)'{-s,--smart}'+[!BROKEN! Perform smart linking from this symbol]:symbol name:'
'*'":object files:_files -g '*.o'"
)
_arguments -s -S : $args
-1670
View File
File diff suppressed because it is too large Load Diff
-36
View File
@@ -1,36 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>General Information</title>
<link rel="stylesheet" type="text/css" href="mandoc.css">
</head>
<body>
<h1>RGBDS — Rednex Game Boy Development System</h1>
<h2>Table of Contents</h2>
<ol>
<li>General information
<ul>
<li><a href="rgbds.7.html">RGBDS general information</a></li>
<li><a href="rgbds.5.html">RGBDS object file format</a></li>
</ul>
<li>Language description
<ul>
<li><a href="rgbasm.5.html">RGBASM language description</a></li>
<li><a href="rgblink.5.html">RGBLINK linkerscript language description</a></li>
<li><a href="gbz80.7.html">GBZ80 CPU instruction set description</a></li>
</ul>
<li>Command line usage
<ul>
<li><a href="rgbasm.1.html">RGBASM command-line usage</a></li>
<li><a href="rgblink.1.html">RGBLINK command-line usage</a></li>
<li><a href="rgbfix.1.html">RGBFIX command-line usage</a></li>
<li><a href="rgbgfx.1.html">RGBGFX command-line usage</a></li>
</ul>
</ol>
<h2 id="GitHub Repository">GitHub Repository:</h2>
<ul>
<li><a href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a></li>
</ul>
</body>
-347
View File
@@ -1,347 +0,0 @@
/* $Id: mandoc.css,v 1.45 2019/03/01 10:57:18 schwarze Exp $ */
/*
* Standard style sheet for mandoc(1) -Thtml and man.cgi(8).
*
* Written by Ingo Schwarze <[email protected]>.
* I place this file into the public domain.
* Permission to use, copy, modify, and distribute it for any purpose
* with or without fee is hereby granted, without any conditions.
*/
/* Global defaults. */
html { max-width: 65em; }
body { font-family: Helvetica,Arial,sans-serif; }
table { margin-top: 0em;
margin-bottom: 0em;
border-collapse: collapse; }
/* Some browsers set border-color in a browser style for tbody,
* but not for table, resulting in inconsistent border styling. */
tbody { border-color: inherit; }
tr { border-color: inherit; }
td { vertical-align: top;
padding-left: 0.2em;
padding-right: 0.2em;
border-color: inherit; }
ul, ol, dl { margin-top: 0em;
margin-bottom: 0em; }
li, dt { margin-top: 1em; }
.permalink { border-bottom: thin dotted;
color: inherit;
font: inherit;
text-decoration: inherit; }
* { clear: both }
/* Search form and search results. */
fieldset { border: thin solid silver;
border-radius: 1em;
text-align: center; }
input[name=expr] {
width: 25%; }
table.results { margin-top: 1em;
margin-left: 2em;
font-size: smaller; }
/* Header and footer lines. */
table.head { width: 100%;
border-bottom: 1px dotted #808080;
margin-bottom: 1em;
font-size: smaller; }
td.head-vol { text-align: center; }
td.head-rtitle {
text-align: right; }
table.foot { width: 100%;
border-top: 1px dotted #808080;
margin-top: 1em;
font-size: smaller; }
td.foot-os { text-align: right; }
/* Sections and paragraphs. */
.manual-text {
margin-left: 3.8em; }
.Nd { }
section.Sh { }
h1.Sh { margin-top: 1.2em;
margin-bottom: 0.6em;
margin-left: -3.2em;
font-size: 110%; }
section.Ss { }
h2.Ss { margin-top: 1.2em;
margin-bottom: 0.6em;
margin-left: -1.2em;
font-size: 105%; }
.Pp { margin: 0.6em 0em; }
.Sx { }
.Xr { }
/* Displays and lists. */
.Bd { }
.Bd-indent { margin-left: 3.8em; }
.Bl-bullet { list-style-type: disc;
padding-left: 1em; }
.Bl-bullet > li { }
.Bl-dash { list-style-type: none;
padding-left: 0em; }
.Bl-dash > li:before {
content: "\2014 "; }
.Bl-item { list-style-type: none;
padding-left: 0em; }
.Bl-item > li { }
.Bl-compact > li {
margin-top: 0em; }
.Bl-enum { padding-left: 2em; }
.Bl-enum > li { }
.Bl-compact > li {
margin-top: 0em; }
.Bl-diag { }
.Bl-diag > dt {
font-style: normal;
font-weight: bold; }
.Bl-diag > dd {
margin-left: 0em; }
.Bl-hang { }
.Bl-hang > dt { }
.Bl-hang > dd {
margin-left: 5.5em; }
.Bl-inset { }
.Bl-inset > dt { }
.Bl-inset > dd {
margin-left: 0em; }
.Bl-ohang { }
.Bl-ohang > dt { }
.Bl-ohang > dd {
margin-left: 0em; }
.Bl-tag { margin-top: 0.6em;
margin-left: 5.5em; }
.Bl-tag > dt {
float: left;
margin-top: 0em;
margin-left: -5.5em;
padding-right: 0.5em;
vertical-align: top; }
.Bl-tag > dd {
clear: right;
width: 100%;
margin-top: 0em;
margin-left: 0em;
margin-bottom: 0.6em;
vertical-align: top;
overflow: auto; }
.Bl-compact { margin-top: 0em; }
.Bl-compact > dd {
margin-bottom: 0em; }
.Bl-compact > dt {
margin-top: 0em; }
.Bl-column { }
.Bl-column > tbody > tr { }
.Bl-column > tbody > tr > td {
margin-top: 1em; }
.Bl-compact > tbody > tr > td {
margin-top: 0em; }
.Rs { font-style: normal;
font-weight: normal; }
.RsA { }
.RsB { font-style: italic;
font-weight: normal; }
.RsC { }
.RsD { }
.RsI { font-style: italic;
font-weight: normal; }
.RsJ { font-style: italic;
font-weight: normal; }
.RsN { }
.RsO { }
.RsP { }
.RsQ { }
.RsR { }
.RsT { text-decoration: underline; }
.RsU { }
.RsV { }
.eqn { }
.tbl td { vertical-align: middle; }
.HP { margin-left: 3.8em;
text-indent: -3.8em; }
/* Semantic markup for command line utilities. */
table.Nm { }
code.Nm { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Fl { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Cm { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ar { font-style: italic;
font-weight: normal; }
.Op { display: inline; }
.Ic { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ev { font-style: normal;
font-weight: normal;
font-family: monospace; }
.Pa { font-style: italic;
font-weight: normal; }
/* Semantic markup for function libraries. */
.Lb { }
code.In { font-style: normal;
font-weight: bold;
font-family: inherit; }
a.In { }
.Fd { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ft { font-style: italic;
font-weight: normal; }
.Fn { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Fa { font-style: italic;
font-weight: normal; }
.Vt { font-style: italic;
font-weight: normal; }
.Va { font-style: italic;
font-weight: normal; }
.Dv { font-style: normal;
font-weight: normal;
font-family: monospace; }
.Er { font-style: normal;
font-weight: normal;
font-family: monospace; }
/* Various semantic markup. */
.An { }
.Lk { }
.Mt { }
.Cd { font-style: normal;
font-weight: bold;
font-family: inherit; }
.Ad { font-style: italic;
font-weight: normal; }
.Ms { font-style: normal;
font-weight: bold; }
.St { }
.Ux { }
/* Physical markup. */
.Bf { display: inline; }
.No { font-style: normal;
font-weight: normal; }
.Em { font-style: italic;
font-weight: normal; }
.Sy { font-style: normal;
font-weight: bold; }
.Li { font-style: normal;
font-weight: normal;
font-family: monospace; }
/* Tooltip support. */
h1.Sh, h2.Ss { position: relative; }
.An, .Ar, .Cd, .Cm, .Dv, .Em, .Er, .Ev, .Fa, .Fd, .Fl, .Fn, .Ft,
.Ic, code.In, .Lb, .Lk, .Ms, .Mt, .Nd, code.Nm, .Pa, .Rs,
.St, .Sx, .Sy, .Va, .Vt, .Xr {
display: inline-block;
position: relative; }
.An::before { content: "An"; }
.Ar::before { content: "Ar"; }
.Cd::before { content: "Cd"; }
.Cm::before { content: "Cm"; }
.Dv::before { content: "Dv"; }
.Em::before { content: "Em"; }
.Er::before { content: "Er"; }
.Ev::before { content: "Ev"; }
.Fa::before { content: "Fa"; }
.Fd::before { content: "Fd"; }
.Fl::before { content: "Fl"; }
.Fn::before { content: "Fn"; }
.Ft::before { content: "Ft"; }
.Ic::before { content: "Ic"; }
code.In::before { content: "In"; }
.Lb::before { content: "Lb"; }
.Lk::before { content: "Lk"; }
.Ms::before { content: "Ms"; }
.Mt::before { content: "Mt"; }
.Nd::before { content: "Nd"; }
code.Nm::before { content: "Nm"; }
.Pa::before { content: "Pa"; }
.Rs::before { content: "Rs"; }
h1.Sh::before { content: "Sh"; }
h2.Ss::before { content: "Ss"; }
.St::before { content: "St"; }
.Sx::before { content: "Sx"; }
.Sy::before { content: "Sy"; }
.Va::before { content: "Va"; }
.Vt::before { content: "Vt"; }
.Xr::before { content: "Xr"; }
.An::before, .Ar::before, .Cd::before, .Cm::before,
.Dv::before, .Em::before, .Er::before, .Ev::before,
.Fa::before, .Fd::before, .Fl::before, .Fn::before, .Ft::before,
.Ic::before, code.In::before, .Lb::before, .Lk::before,
.Ms::before, .Mt::before, .Nd::before, code.Nm::before,
.Pa::before, .Rs::before,
h1.Sh::before, h2.Ss::before, .St::before, .Sx::before, .Sy::before,
.Va::before, .Vt::before, .Xr::before {
opacity: 0;
transition: .15s ease opacity;
pointer-events: none;
position: absolute;
bottom: 100%;
box-shadow: 0 0 .35em #000;
padding: .15em .25em;
white-space: nowrap;
font-family: Helvetica,Arial,sans-serif;
font-style: normal;
font-weight: bold;
color: black;
background: #fff; }
.An:hover::before, .Ar:hover::before, .Cd:hover::before, .Cm:hover::before,
.Dv:hover::before, .Em:hover::before, .Er:hover::before, .Ev:hover::before,
.Fa:hover::before, .Fd:hover::before, .Fl:hover::before, .Fn:hover::before,
.Ft:hover::before, .Ic:hover::before, code.In:hover::before,
.Lb:hover::before, .Lk:hover::before, .Ms:hover::before, .Mt:hover::before,
.Nd:hover::before, code.Nm:hover::before, .Pa:hover::before,
.Rs:hover::before, h1.Sh:hover::before, h2.Ss:hover::before, .St:hover::before,
.Sx:hover::before, .Sy:hover::before, .Va:hover::before, .Vt:hover::before,
.Xr:hover::before {
opacity: 1;
pointer-events: inherit; }
/* Overrides to avoid excessive margins on small devices. */
@media (max-width: 37.5em) {
.manual-text {
margin-left: 0.5em; }
h1.Sh, h2.Ss { margin-left: 0em; }
.Bd-indent { margin-left: 2em; }
.Bl-hang > dd {
margin-left: 2em; }
.Bl-tag { margin-left: 2em; }
.Bl-tag > dt {
margin-left: -2em; }
.HP { margin-left: 2em;
text-indent: -2em; }
}
-263
View File
@@ -1,263 +0,0 @@
<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
This file is part of RGBDS.
Copyright (c) 2010-2019, Anthony J. Bentley and RGBDS contributors.
SPDX-License-Identifier: MIT
-->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<link rel="stylesheet" href="mandoc.css" type="text/css" media="all"/>
<link rel="stylesheet" href="rgbds.css" type="text/css" media="all"/>
<title>RGBASM(1)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">RGBASM(1)</td>
<td class="head-vol">General Commands Manual</td>
<td class="head-rtitle">RGBASM(1)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">rgbasm</code> &#x2014;
<span class="Nd">Game Boy assembler</span>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<table class="Nm">
<tr>
<td><code class="Nm">rgbasm</code></td>
<td>[<code class="Fl"><a href="#E">-E</a><a href="#h">h</a><a href="#L">L</a><a href="#V">V</a><a href="#v">v</a><a href="#w">w</a></code>] [<code class="Fl"><a href="#b">-b</a></code>
<var class="Ar">chars</var>] [<code class="Fl"><a href="#D">-D</a></code>
<var class="Ar">name</var>[=<var class="Ar">value</var>]]
[<code class="Fl"><a href="#g">-g</a></code> <var class="Ar">chars</var>]
[<code class="Fl"><a href="#i">-i</a></code> <var class="Ar">path</var>]
[<code class="Fl"><a href="#M">-M</a></code> <var class="Ar">depend_file</var>]
[<code class="Fl"><a href="#o">-o</a></code> <var class="Ar">out_file</var>]
[<code class="Fl"><a href="#p">-p</a></code> <var class="Ar">pad_value</var>]
[<code class="Fl"><a href="#r">-r</a></code> <var class="Ar">recursion_depth</var>]
[<code class="Fl"><a href="#W">-W</a></code> <var class="Ar">warning</var>]
<var class="Ar">file ...</var></td>
</tr>
</table>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
The <code class="Nm">rgbasm</code> program creates an RGB object file from an
assembly source file. The input <var class="Ar">file</var> can be a file path,
or <code class="Cm">-</code> denoting <code class="Cm">stdin</code>.
<p class="Pp">Note that options can be abbreviated as long as the abbreviation
is unambiguous: <code class="Fl">--verb</code> is
<code class="Fl">--verbose</code>, but
<code class="Fl">--ver</code> is invalid because it
could also be <code class="Fl">--version</code>. The
arguments are as follows:</p>
<dl class="Bl-tag">
<dt><a class="permalink" href="#b"><code class="Fl" id="b">-b</code></a>
<var class="Ar">chars</var>,
<code class="Fl">--binary-digits</code>
<var class="Ar">chars</var></dt>
<dd>Change the two characters used for binary constants. The defaults are
01.</dd>
<dt><a class="permalink" href="#D"><code class="Fl" id="D">-D</code></a>
<var class="Ar">name</var>[=<var class="Ar">value</var>],
<code class="Fl">-</code> <code class="Fl">-define</code>
<var class="Ar">name</var>[=<var class="Ar">value</var>]</dt>
<dd>Add a string symbol to the compiled source code. This is equivalent to
&#x2018;<code class="Li"><var class="Ar">name</var> <code class="Ic">EQUS
&quot;</code><var class="Ar">value</var>&quot;</code>&#x2019; in code, or
&#x2018;<code class="Li"><var class="Ar">name</var> <code class="Ic">EQUS
&quot;1&quot;</code></code>&#x2019; if <var class="Ar">value</var> is not
specified.</dd>
<dt><a class="permalink" href="#E"><code class="Fl" id="E">-E</code></a>,
<code class="Fl">--export-all</code></dt>
<dd>Export all labels, including unreferenced and local labels.</dd>
<dt><a class="permalink" href="#g"><code class="Fl" id="g">-g</code></a>
<var class="Ar">chars</var>,
<code class="Fl">--gfx-chars</code>
<var class="Ar">chars</var></dt>
<dd>Change the four characters used for gfx constants. The defaults are
0123.</dd>
<dt><a class="permalink" href="#h"><code class="Fl" id="h">-h</code></a>,
<code class="Fl">--halt-without-nop</code></dt>
<dd>By default, <code class="Nm">rgbasm</code> inserts a
<code class="Ic">nop</code> instruction immediately after any
<code class="Ic">halt</code> instruction. The <code class="Fl">-h</code>
option disables this behavior.</dd>
<dt><a class="permalink" href="#i"><code class="Fl" id="i">-i</code></a>
<var class="Ar">path</var>,
<code class="Fl">--include</code>
<var class="Ar">path</var></dt>
<dd>Add an include path.</dd>
<dt><a class="permalink" href="#L"><code class="Fl" id="L">-L</code></a>,
<code class="Fl">--preserve-ld</code></dt>
<dd>Disable the optimization that turns loads of the form <code class="Ic">LD
[$FF00+n8],A</code> into the opcode <code class="Ic">LDH
[$FF00+n8],A</code> in order to have full control of the result in the
final ROM.</dd>
<dt><a class="permalink" href="#M"><code class="Fl" id="M">-M</code></a>
<var class="Ar">depend_file</var>,
<code class="Fl">--dependfile</code>
<var class="Ar">depend_file</var></dt>
<dd>Print <a class="Xr">make(1)</a> dependencies to
<var class="Ar">depend_file</var>.</dd>
<dt><a class="permalink" href="#o"><code class="Fl" id="o">-o</code></a>
<var class="Ar">out_file</var>,
<code class="Fl">--output</code>
<var class="Ar">out_file</var></dt>
<dd>Write an object file to the given filename.</dd>
<dt><a class="permalink" href="#p"><code class="Fl" id="p">-p</code></a>
<var class="Ar">pad_value</var>,
<code class="Fl">--pad-value</code>
<var class="Ar">pad_value</var></dt>
<dd>When padding an image, pad with this value. The default is 0x00.</dd>
<dt><a class="permalink" href="#r"><code class="Fl" id="r">-r</code></a>
<var class="Ar">recursion_depth</var>,
<code class="Fl">--recursion-depth</code>
<var class="Ar">recursion_depth</var></dt>
<dd>Specifies the recursion depth at which RGBASM will assume being in an
infinite loop.</dd>
<dt><a class="permalink" href="#V"><code class="Fl" id="V">-V</code></a>,
<code class="Fl">--version</code></dt>
<dd>Print the version of the program and exit.</dd>
<dt><a class="permalink" href="#v"><code class="Fl" id="v">-v</code></a>,
<code class="Fl">--verbose</code></dt>
<dd>Be verbose.</dd>
<dt><a class="permalink" href="#W"><code class="Fl" id="W">-W</code></a>
<var class="Ar">warning</var>,
<code class="Fl">--warning</code>
<var class="Ar">warning</var></dt>
<dd>Set warning flag <var class="Ar">warning</var>. A warning message will be
printed if <var class="Ar">warning</var> is an unknown warning flag. See
the <a class="Sx" href="#DIAGNOSTICS">DIAGNOSTICS</a> section for a list
of warnings.</dd>
<dt><a class="permalink" href="#w"><code class="Fl" id="w">-w</code></a></dt>
<dd>Disable all warning output, even when turned into errors.</dd>
</dl>
</section>
<section class="Sh">
<h1 class="Sh" id="DIAGNOSTICS"><a class="permalink" href="#DIAGNOSTICS">DIAGNOSTICS</a></h1>
Warnings are diagnostic messages that indicate possibly erroneous behavior that
does not necessarily compromise the assembling process. The following options
alter the way warnings are processed.
<dl class="Bl-tag">
<dt><a class="permalink" href="#Werror"><code class="Fl" id="Werror">-Werror</code></a></dt>
<dd>Make all warnings into errors.</dd>
<dt><a class="permalink" href="#Werror="><code class="Fl" id="Werror=">-Werror=</code></a></dt>
<dd>Make the specified warning into an error. A warning's name is appended
(example: <code class="Fl">-Werror=obsolete</code>), and this warning is
implicitly enabled and turned into an error. This is an error if used with
a meta warning, such as <code class="Fl">-Werror=all</code>.</dd>
</dl>
<p class="Pp">The following warnings are &#x201C;meta&#x201D; warnings, that
enable a collection of other warnings. If a specific warning is toggled via
a meta flag and a specific one, the more specific one takes priority. The
position on the command-line acts as a tie breaker, the last one taking
effect.</p>
<dl class="Bl-tag">
<dt><a class="permalink" href="#Wall"><code class="Fl" id="Wall">-Wall</code></a></dt>
<dd>This enables warnings that are likely to indicate an error or undesired
behavior, and that can easily be fixed.</dd>
<dt><a class="permalink" href="#Wextra"><code class="Fl" id="Wextra">-Wextra</code></a></dt>
<dd>This enables extra warnings that are less likely to pose a problem, but
that may still be wanted.</dd>
<dt><a class="permalink" href="#Weverything"><code class="Fl" id="Weverything">-Weverything</code></a></dt>
<dd>Enables literally every warning.</dd>
</dl>
<p class="Pp">The following warnings are actual warning flags; with each
description, the corresponding warning flag is included. Note that each of
these flag also has a negation (for example,
<code class="Fl">-Wempty-entry</code> enables the warning that
<code class="Fl">-Wno-empty-entry</code> disables). Only the non-default
flag is listed here. Ignoring the &#x201C;no-&#x201D; prefix, entries are
listed alphabetically.</p>
<dl class="Bl-tag">
<dt><a class="permalink" href="#Wno-assert"><code class="Fl" id="Wno-assert">-Wno-assert</code></a></dt>
<dd>Warns when <code class="Ic">WARN</code><span class="No">-type</span>
assertions fail. (See &#x201C;Aborting the assembly process&#x201D; in
<a class="Xr" href="rgbasm.5.html">rgbasm(5)</a> for <code class="Ic">ASSERT</code>).</dd>
<dt><a class="permalink" href="#Wbuiltin-args"><code class="Fl" id="Wbuiltin-args">-Wbuiltin-args</code></a></dt>
<dd>Warn about incorrect arguments to built-in functions, such as
<code class="Fn">STRSUB</code>() with indexes outside of the string's
bounds. This warning is enabled by <code class="Fl">-Wall</code>.</dd>
<dt><a class="permalink" href="#Wdiv"><code class="Fl" id="Wdiv">-Wdiv</code></a></dt>
<dd>Warn when dividing the smallest negative integer by -1, which yields
itself due to integer overflow.</dd>
<dt><a class="permalink" href="#Wempty-entry"><code class="Fl" id="Wempty-entry">-Wempty-entry</code></a></dt>
<dd>Warn when an empty entry is encountered in a <code class="Ic">db</code>,
<code class="Ic">dw</code>, <code class="Ic">dl</code> list. This warning
is enabled by <code class="Fl">-Wextra</code>.</dd>
<dt><a class="permalink" href="#Wlarge-constant"><code class="Fl" id="Wlarge-constant">-Wlarge-constant</code></a></dt>
<dd>Warn when a constant too large to fit in a signed 32-bit integer is
encountered. This warning is enabled by
<code class="Fl">-Wall</code>.</dd>
<dt><a class="permalink" href="#Wlong-string"><code class="Fl" id="Wlong-string">-Wlong-string</code></a></dt>
<dd>Warn when a string too long to fit in internal buffers is encountered.
This warning is enabled by <code class="Fl">-Wall</code>.</dd>
<dt><a class="permalink" href="#Wobsolete"><code class="Fl" id="Wobsolete">-Wobsolete</code></a></dt>
<dd>Warn when obsolete constructs such as the <code class="Ic">jp [hl]</code>
instruction or <code class="Ic">HOME</code> section type are encountered.
This warning is enabled by <code class="Fl">-Wextra</code>.</dd>
<dt><a class="permalink" href="#Wshift"><code class="Fl" id="Wshift">-Wshift</code></a></dt>
<dd>Warn when shifting right a negative value. Use a division by 2^N
instead.</dd>
<dt><a class="permalink" href="#Wshift-amount"><code class="Fl" id="Wshift-amount">-Wshift-amount</code></a></dt>
<dd>Warn when a shift's operand is negative or greater than 32.</dd>
<dt><a class="permalink" href="#Wno-truncation"><code class="Fl" id="Wno-truncation">-Wno-truncation</code></a></dt>
<dd>Warn when an implicit truncation (for example, <code class="Ic">db</code>)
loses some bits.</dd>
<dt><a class="permalink" href="#Wno-user"><code class="Fl" id="Wno-user">-Wno-user</code></a></dt>
<dd>Warn when the <code class="Ic">WARN</code> built-in is executed. (See
&#x201C;Aborting the assembly process&#x201D; in
<a class="Xr" href="rgbasm.5.html">rgbasm(5)</a> for <code class="Ic">WARN</code>).</dd>
</dl>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
You can assemble a source file in two ways.
<p class="Pp">Straightforward way:</p>
<div class="Bd Bd-indent"><code class="Li">$ rgbasm -o bar.o
foo.asm</code></div>
<p class="Pp">Pipes way:</p>
<div class="Bd Bd-indent"><code class="Li">$ cat foo.asm | rgbasm -o bar.o
-</code></div>
<div class="Bd Bd-indent"><code class="Li">$ rgbasm -o bar.o - &lt;
foo.asm</code></div>
<p class="Pp">The resulting object file is not yet a usable ROM image&#x2014;it
must first be run through <a class="Xr" href="rgblink.1.html">rgblink(1)</a> and then
<a class="Xr" href="rgbfix.1.html">rgbfix(1)</a>.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="BUGS"><a class="permalink" href="#BUGS">BUGS</a></h1>
Please report bugs on
<a class="Lk" href="https://github.com/rednex/rgbds/issues">GitHub</a>.
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<a class="Xr" href="rgbasm.5.html">rgbasm(5)</a>, <a class="Xr" href="rgbfix.1.html">rgbfix(1)</a>,
<a class="Xr" href="rgblink.1.html">rgblink(1)</a>, <a class="Xr" href="rgbds.5.html">rgbds(5)</a>,
<a class="Xr" href="rgbds.7.html">rgbds(7)</a>, <a class="Xr" href="gbz80.7.html">gbz80(7)</a>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<code class="Nm">rgbasm</code> was originally written by Carsten S&#x00F8;rensen
as part of the ASMotor package, and was later packaged in RGBDS by Justin
Lloyd. It is now maintained by a number of contributors at
<a class="Lk" href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a>.
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">July 8, 2019</td>
<td class="foot-os">General</td>
</tr>
</table>
</body>
</html>
-1691
View File
File diff suppressed because it is too large Load Diff
-350
View File
@@ -1,350 +0,0 @@
<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
This file is part of RGBDS.
Copyright (c) 2017-2018, Antonio Nino Diaz and RGBDS contributors.
SPDX-License-Identifier: MIT
-->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<link rel="stylesheet" href="mandoc.css" type="text/css" media="all"/>
<link rel="stylesheet" href="rgbds.css" type="text/css" media="all"/>
<title>RGBDS(5)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">RGBDS(5)</td>
<td class="head-vol">File Formats Manual</td>
<td class="head-rtitle">RGBDS(5)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">rgbds</code> &#x2014;
<span class="Nd">object file format documentation</span>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
This is the description of the object files used by <a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>
and <a class="Xr" href="rgblink.1.html">rgblink(1)</a>. <i class="Em">Please note that the
specifications may change.</i> This toolchain is in development and new
features may require adding more information to the current format, or
modifying some fields, which would break compatibility with older versions.
</section>
<section class="Sh">
<h1 class="Sh" id="FILE_STRUCTURE"><a class="permalink" href="#FILE_STRUCTURE">FILE
STRUCTURE</a></h1>
The following types are used:
<p class="Pp"><var class="Ar">LONG</var> is a 32&#x2010;bit integer stored in
little&#x2010;endian format. <var class="Ar">BYTE</var> is an 8&#x2010;bit
integer. <var class="Ar">STRING</var> is a 0&#x2010;terminated string of
<var class="Ar">BYTE</var>.</p>
<div class="Bd Pp">
<pre>
; Header
BYTE ID[4] ; &quot;RGB9&quot;
LONG RevisionNumber ; The format's revision number this file uses
LONG NumberOfSymbols ; The number of symbols used in this file
LONG NumberOfSections ; The number of sections used in this file
; Symbols
REPT NumberOfSymbols ; Number of symbols defined in this object file.
STRING Name ; The name of this symbol. Local symbols are stored
; as &quot;Scope.Symbol&quot;.
BYTE Type ; 0 = LOCAL symbol only used in this file.
; 1 = IMPORT this symbol from elsewhere
; 2 = EXPORT this symbol to other objects.
; Bit 7 is independent from the above value, and
; encodes whether the section is unionized
IF (Type &amp; 0x7F) != 1 ; If symbol is defined in this object file.
STRING FileName ; File where the symbol is defined.
LONG LineNum ; Line number in the file where the symbol is defined.
LONG SectionID ; The section number (of this object file) in which
; this symbol is defined. If it doesn't belong to any
; specific section (like a constant), this field has
; the value -1.
LONG Value ; The symbols value. It's the offset into that
; symbol's section.
ENDC
ENDR
; Sections
REPT NumberOfSections
STRING Name ; Name of the section
LONG Size ; Size in bytes of this section
BYTE Type ; 0 = WRAM0
; 1 = VRAM
; 2 = ROMX
; 3 = ROM0
; 4 = HRAM
; 5 = WRAMX
; 6 = SRAM
; 7 = OAM
LONG Org ; Address to fix this section at. -1 if the linker should
; decide (floating address).
LONG Bank ; Bank to load this section into. -1 if the linker should
; decide (floating bank). This field is only valid for ROMX,
; VRAM, WRAMX and SRAM sections.
LONG Align ; Alignment of this section, expressed as 1 &lt;&lt; align. 1 if
; not specified.
IF (Type == ROMX) || (Type == ROM0) ; Sections that can contain data.
BYTE Data[Size] ; Raw data of the section.
LONG NumberOfPatches ; Number of patches to apply.
; These types of sections may have patches
REPT NumberOfPatches
STRING SourceFile ; Name of the source file (for printing error
; messages).
LONG Offset ; Offset into the section where patch should
; be applied (in bytes).
BYTE Type ; 0 = BYTE patch.
; 1 = little endian WORD patch.
; 2 = little endian LONG patch.
; 3 = JR offset value BYTE patch.
LONG RPNSize ; Size of the buffer with the RPN.
; expression.
BYTE RPN[RPNSize] ; RPN expression. Definition below.
ENDR
ENDC
ENDR
; Assertions
LONG NumberOfAssertions
REPT NumberOfAssertions
STRING SourceFile ; Name of the source file (for printing the failure).
LONG Offset ; Offset into the section where the assertion is located.
BYTE Type ; 0 = Prints the message but allows linking to continue
; 1 = Prints the message and evaluates other assertions,
; but linking fails afterwards
; 2 = Prints the message and immediately fails linking
LONG RPNSize ; Size of the RPN expression's buffer.
BYTE RPN[RPNSize] ; RPN expression, same as patches. Assert fails if == 0.
LONG SectionID ; The section number (of this object file) in which this
; assert is defined. If it doesn't belong to any specific
; section (like a constant), this field has the value -1.
STRING Message ; A message displayed when the assert fails. If set to
; the empty string, a generic message is printed instead.
ENDR
</pre>
</div>
<section class="Ss">
<h2 class="Ss" id="RPN_DATA"><a class="permalink" href="#RPN_DATA">RPN
DATA</a></h2>
Expressions in the object file are stored as RPN. This is an expression of the
form &#x201C;2 5 +&#x201D;. This will first push the value &#x201C;2&#x201D;
to the stack, then &#x201C;5&#x201D;. The &#x201C;+&#x201D; 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 <var class="Ar">BYTE</var>s with some bytes
being special prefixes for integers and symbols.
<table class="Bl-column Bd-indent">
<tr>
<th>Value</th>
<th>Meaning</th>
</tr>
<tr>
<td><a class="permalink" href="#$00"><code class="Li" id="$00">$00</code></a></td>
<td><a class="permalink" href="#+_operator"><code class="Li" id="+_operator">+
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$01"><code class="Li" id="$01">$01</code></a></td>
<td><a class="permalink" href="#-_operator"><code class="Li" id="-_operator">-
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$02"><code class="Li" id="$02">$02</code></a></td>
<td><a class="permalink" href="#*_operator"><code class="Li" id="*_operator">*
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$03"><code class="Li" id="$03">$03</code></a></td>
<td><a class="permalink" href="#/_operator"><code class="Li" id="/_operator">/
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$04"><code class="Li" id="$04">$04</code></a></td>
<td><a class="permalink" href="#__operator"><code class="Li" id="__operator">%
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$05"><code class="Li" id="$05">$05</code></a></td>
<td><a class="permalink" href="#unary_-"><code class="Li" id="unary_-">unary
-</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$10"><code class="Li" id="$10">$10</code></a></td>
<td>|
<a class="permalink" href="#operator"><code class="Li" id="operator">operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$11"><code class="Li" id="$11">$11</code></a></td>
<td><a class="permalink" href="#&amp;_operator"><code class="Li" id="&amp;_operator">&amp;
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$12"><code class="Li" id="$12">$12</code></a></td>
<td><a class="permalink" href="#__operator_2"><code class="Li" id="__operator_2">^
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$13"><code class="Li" id="$13">$13</code></a></td>
<td><a class="permalink" href="#unary_~"><code class="Li" id="unary_~">unary
~</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$21"><code class="Li" id="$21">$21</code></a></td>
<td><a class="permalink" href="#&amp;&amp;_comparison"><code class="Li" id="&amp;&amp;_comparison">&amp;&amp;
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$22"><code class="Li" id="$22">$22</code></a></td>
<td><a class="permalink" href="#___comparison"><code class="Li" id="___comparison">||
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$23"><code class="Li" id="$23">$23</code></a></td>
<td><a class="permalink" href="#unary"><code class="Li" id="unary">unary</code></a>!</td>
</tr>
<tr>
<td><a class="permalink" href="#$30"><code class="Li" id="$30">$30</code></a></td>
<td><a class="permalink" href="#==_comparison"><code class="Li" id="==_comparison">==
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$31"><code class="Li" id="$31">$31</code></a></td>
<td><a class="permalink" href="#!=_comparison"><code class="Li" id="!=_comparison">!=
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$32"><code class="Li" id="$32">$32</code></a></td>
<td><a class="permalink" href="#__comparison"><code class="Li" id="__comparison">&gt;
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$33"><code class="Li" id="$33">$33</code></a></td>
<td><a class="permalink" href="#__comparison_2"><code class="Li" id="__comparison_2">&lt;
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$34"><code class="Li" id="$34">$34</code></a></td>
<td><a class="permalink" href="#_=_comparison"><code class="Li" id="_=_comparison">&gt;=
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$35"><code class="Li" id="$35">$35</code></a></td>
<td><a class="permalink" href="#_=_comparison_2"><code class="Li" id="_=_comparison_2">&lt;=
comparison</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$40"><code class="Li" id="$40">$40</code></a></td>
<td><a class="permalink" href="#___operator"><code class="Li" id="___operator">&lt;&lt;
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$41"><code class="Li" id="$41">$41</code></a></td>
<td><a class="permalink" href="#___operator_2"><code class="Li" id="___operator_2">&gt;&gt;
operator</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$50"><code class="Li" id="$50">$50</code></a></td>
<td><a class="permalink" href="#BANK(symbol)"><code class="Li" id="BANK(symbol)">BANK(symbol)</code></a>,
a <var class="Ar">LONG</var> Symbol ID follows.</td>
</tr>
<tr>
<td><a class="permalink" href="#$51"><code class="Li" id="$51">$51</code></a></td>
<td><a class="permalink" href="#BANK(section_name)"><code class="Li" id="BANK(section_name)">BANK(section_name)</code></a>,
a null-terminated string follows.</td>
</tr>
<tr>
<td><a class="permalink" href="#$52"><code class="Li" id="$52">$52</code></a></td>
<td><a class="permalink" href="#Current_BANK()"><code class="Li" id="Current_BANK()">Current
BANK()</code></a></td>
</tr>
<tr>
<td><a class="permalink" href="#$60"><code class="Li" id="$60">$60</code></a></td>
<td><a class="permalink" href="#HRAMCheck"><code class="Li" id="HRAMCheck">HRAMCheck</code></a>.
Checks if the value is in HRAM, ANDs it with 0xFF.</td>
</tr>
<tr>
<td><a class="permalink" href="#$61"><code class="Li" id="$61">$61</code></a></td>
<td><a class="permalink" href="#RSTCheck"><code class="Li" id="RSTCheck">RSTCheck</code></a>.
Checks if the value is a RST vector, ORs it with 0xC7.</td>
</tr>
<tr>
<td><a class="permalink" href="#$80"><code class="Li" id="$80">$80</code></a></td>
<td><var class="Ar">LONG</var> integer follows.</td>
</tr>
<tr>
<td><a class="permalink" href="#$81"><code class="Li" id="$81">$81</code></a></td>
<td><var class="Ar">LONG</var> symbol ID follows.</td>
</tr>
</table>
</section>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>, <a class="Xr" href="rgblink.1.html">rgblink(1)</a>,
<a class="Xr" href="rgbds.7.html">rgbds(7)</a>, <a class="Xr" href="gbz80.7.html">gbz80(7)</a>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<code class="Nm">rgbds</code> was originally written by Carsten S&#x00F8;rensen
as part of the ASMotor package, and was later packaged in RGBDS by Justin
Lloyd. It is now maintained by a number of contributors at
<a class="Lk" href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a>.
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">January 26, 2018</td>
<td class="foot-os">General</td>
</tr>
</table>
</body>
</html>
-80
View File
@@ -1,80 +0,0 @@
<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
This file is part of RGBDS.
Copyright (c) 2010-2018, Anthony J. Bentley and RGBDS contributors.
SPDX-License-Identifier: MIT
-->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<link rel="stylesheet" href="mandoc.css" type="text/css" media="all"/>
<link rel="stylesheet" href="rgbds.css" type="text/css" media="all"/>
<title>RGBDS(7)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">RGBDS(7)</td>
<td class="head-vol">Miscellaneous Information Manual</td>
<td class="head-rtitle">RGBDS(7)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">rgbds</code> &#x2014;
<span class="Nd">Rednex Game Boy Development System</span>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
To get a working ROM image from a single assembly source file:
<div class="Bd Pp Bd-indent">
<pre>
$ rgbasm -o bar.o foo.asm
$ rgblink -o baz.gb bar.o
$ rgbfix -v -p 0 baz.gb
</pre>
</div>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>, <a class="Xr" href="rgbfix.1.html">rgbfix(1)</a>,
<a class="Xr" href="rgblink.1.html">rgblink(1)</a>, <a class="Xr" href="rgbds.5.html">rgbds(5)</a>,
<a class="Xr" href="gbz80.7.html">gbz80(7)</a>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<dl class="Bl-ohang">
<dt></dt>
<dd>1997, Carsten S&#x00F8;rensen (AKA SurfSmurf) writes ASMotor as a
general-purpose assembler/linker system for DOS/Win32.</dd>
<dt></dt>
<dd>1999, Justin Lloyd (AKA Otaku no Zoku) adapts ASMotor to read and produce
GBZ80 assembly/machine code, and releases this version as RGBDS.</dd>
<dt></dt>
<dd>2009, Vegard Nossum adapts the code to be more UNIX-like and releases this
version as rgbds-linux on GitHub.</dd>
<dt></dt>
<dd>2010, Anthony J. Bentley forks that repository. The fork becomes the
reference implementation of rgbds.</dd>
<dt></dt>
<dd>2017, Bentley's repository is moved to a neutral name. It is now
maintained by a number of contributors at
<a class="Lk" href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a>.</dd>
<dt></dt>
<dd>2018, codebase relicensed under the MIT license.</dd>
</dl>
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">March 7, 2018</td>
<td class="foot-os">General</td>
</tr>
</table>
</body>
</html>
-63
View File
@@ -1,63 +0,0 @@
/* Overrides to default mandoc styling for HTML renders of RGBDS man pages */
html {
/* Reduce contrast */
background-color: #f8f8f8;
color: #222;
/* Override `mandoc.css`'s sowe can put it on <body> instead */
max-width: none;
}
body {
/* Center body horizontally (requires <html> to span full width) */
margin: 0 auto;
/* `mandoc.css`'s default, but it's applied to <html> there */
max-width: 65em;
/* Improve readability */
font-size: 16px;
line-height: 1.4;
text-align: justify;
/* Prevent text from bumping sides on mobile devices */
padding: 10px 20px 10px 10px;
}
@media print {
body {
/* Max width doesn't make sense for print */
max-width: none;
/* Make font slightly smaller for printing */
font-size: 14px;
}
}
code, pre {
font-size: smaller;
}
pre {
/* Avoid horizontal page scrolling on mobile */
overflow: auto;
}
/* Separate lines in tables */
table.Bl-column {
border-collapse: collapse;
}
table.Bl-column tr:not(:first-child) > td,
table.Bl-column tr:not(:first-child) > th {
border-top: 1px solid #aaa;
}
table.Bl-column th {
/* Apply `.Sy` style to table headers */
font-style: normal;
font-weight: bold;
}
table.Bl-column td,
table.Bl-column th {
/* Add horizontal spacing between columns */
padding: 2px 7px 0;
}
-220
View File
@@ -1,220 +0,0 @@
<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
This file is part of RGBDS.
Copyright (c) 2010-2017, Anthony J. Bentley and RGBDS contributors.
SPDX-License-Identifier: MIT
-->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<link rel="stylesheet" href="mandoc.css" type="text/css" media="all"/>
<link rel="stylesheet" href="rgbds.css" type="text/css" media="all"/>
<title>RGBFIX(1)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">RGBFIX(1)</td>
<td class="head-vol">General Commands Manual</td>
<td class="head-rtitle">RGBFIX(1)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">rgbfix</code> &#x2014;
<span class="Nd">Game Boy header utility and checksum fixer</span>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<table class="Nm">
<tr>
<td><code class="Nm">rgbfix</code></td>
<td>[<code class="Fl"><a href="#j">-j</a><a href="#s">s</a><a href="#V">V</a><a href="#v">v</a></code>] [<code class="Fl"><a href="#C">-C</a></code> |
<code class="Fl"><a href="#c">-c</a></code>] [<code class="Fl"><a href="#f">-f</a></code>
<var class="Ar">fix_spec</var>] [<code class="Fl"><a href="#i">-i</a></code>
<var class="Ar">game_id</var>] [<code class="Fl"><a href="#k">-k</a></code>
<var class="Ar">licensee_str</var>] [<code class="Fl"><a href="#l">-l</a></code>
<var class="Ar">licensee_id</var>] [<code class="Fl"><a href="#m">-m</a></code>
<var class="Ar">mbc_type</var>] [<code class="Fl"><a href="#n">-n</a></code>
<var class="Ar">rom_version</var>] [<code class="Fl"><a href="#p">-p</a></code>
<var class="Ar">pad_value</var>] [<code class="Fl"><a href="#r">-r</a></code>
<var class="Ar">ram_size</var>] [<code class="Fl"><a href="#t">-t</a></code>
<var class="Ar">title_str</var>] <var class="Ar">file</var></td>
</tr>
</table>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
The <code class="Nm">rgbfix</code> program changes headers of Game Boy ROM
images. It also performs other correctness operations, such as padding.
<p class="Pp">Note that options can be abbreviated as long as the abbreviation
is unambiguous: <code class="Fl">--verb</code> is
<code class="Fl">--verbose</code>, but
<code class="Fl">--ver</code> is invalid because it
could also be <code class="Fl">--version</code>. The
arguments are as follows:</p>
<dl class="Bl-tag">
<dt><a class="permalink" href="#C"><code class="Fl" id="C">-C</code></a>,
<code class="Fl">--color-only</code></dt>
<dd>Set the Game Boy Color&#x2013;only flag: <span class="Ad">0x143</span> =
0xC0. If both this and the <code class="Fl">-c</code> flag are set, this
takes precedence.</dd>
<dt><a class="permalink" href="#c"><code class="Fl" id="c">-c</code></a>,
<code class="Fl">--color-compatible</code></dt>
<dd>Set the Game Boy Color&#x2013;compatible flag:
<span class="Ad">0x143</span> = 0x80. If both this and the
<code class="Fl">-C</code> flag are set, <code class="Fl">-C</code> takes
precedence.</dd>
<dt><a class="permalink" href="#f"><code class="Fl" id="f">-f</code></a>
<var class="Ar">fix_spec</var>,
<code class="Fl">--fix-spec</code>
<var class="Ar">fix_spec</var></dt>
<dd>Fix certain header values that the Game Boy checks for correctness.
Alternatively, intentionally trash these values by writing their binary
inverse instead. <var class="Ar">fix_spec</var> is a string containing any
combination of the following characters:
<p class="Pp"></p>
<dl class="Bl-tag Bl-compact">
<dt><a class="permalink" href="#l"><code class="Cm" id="l">l</code></a></dt>
<dd>Fix the Nintendo logo
(<span class="Ad">0x104</span>&#x2013;<span class="Ad">0x133</span>).</dd>
<dt><a class="permalink" href="#L"><code class="Cm" id="L">L</code></a></dt>
<dd>Trash the Nintendo logo.</dd>
<dt><a class="permalink" href="#h"><code class="Cm" id="h">h</code></a></dt>
<dd>Fix the header checksum (<span class="Ad">0x14D</span>).</dd>
<dt><a class="permalink" href="#H"><code class="Cm" id="H">H</code></a></dt>
<dd>Trash the header checksum.</dd>
<dt><a class="permalink" href="#g"><code class="Cm" id="g">g</code></a></dt>
<dd>Fix the global checksum
(<span class="Ad">0x14E</span>&#x2013;<span class="Ad">0x14F</span>).</dd>
<dt><a class="permalink" href="#G"><code class="Cm" id="G">G</code></a></dt>
<dd>Trash the global checksum.</dd>
</dl>
</dd>
<dt><a class="permalink" href="#i"><code class="Fl" id="i">-i</code></a>
<var class="Ar">game_id</var>,
<code class="Fl">--game-id</code>
<var class="Ar">game_id</var></dt>
<dd>Set the game ID string
(<span class="Ad">0x13F</span>&#x2013;<span class="Ad">0x142</span>) to a
given string of exactly 4 characters. If both this and the title are set,
the game ID will overwrite the overlapping portion of the title.</dd>
<dt><a class="permalink" href="#j"><code class="Fl" id="j">-j</code></a>,
<code class="Fl">--non-japanese</code></dt>
<dd>Set the non-Japanese region flag: <span class="Ad">0x14A</span> = 1.</dd>
<dt><a class="permalink" href="#k"><code class="Fl" id="k">-k</code></a>
<var class="Ar">licensee_str</var>,
<code class="Fl">--new-licensee</code>
<var class="Ar">licensee_str</var></dt>
<dd>Set the new licensee string
(<span class="Ad">0x144</span>&#x2013;<span class="Ad">0x145</span>) to a
given string, truncated to at most two characters.</dd>
<dt><a class="permalink" href="#l_2"><code class="Fl" id="l_2">-l</code></a>
<var class="Ar">licensee_id</var>,
<code class="Fl">--old-licensee</code>
<var class="Ar">licensee_id</var></dt>
<dd>Set the old licensee code, <span class="Ad">0x14B</span>, to a given value
from 0 to 0xFF. This value is deprecated and should be set to 0x33 in all
new software.</dd>
<dt><a class="permalink" href="#m"><code class="Fl" id="m">-m</code></a>
<var class="Ar">mbc_type</var>,
<code class="Fl">--mbc-type</code>
<var class="Ar">mbc_type</var></dt>
<dd>Set the MBC type, <span class="Ad">0x147</span>, to a given value from 0
to 0xFF.</dd>
<dt><a class="permalink" href="#n"><code class="Fl" id="n">-n</code></a>
<var class="Ar">rom_version</var>,
<code class="Fl">--rom-version</code>
<var class="Ar">rom_version</var></dt>
<dd>Set the ROM version, <span class="Ad">0x14C</span>, to a given value from
0 to 0xFF.</dd>
<dt><a class="permalink" href="#p"><code class="Fl" id="p">-p</code></a>
<var class="Ar">pad_value</var>,
<code class="Fl">--pad-value</code>
<var class="Ar">pad_value</var></dt>
<dd>Pad the image to a valid size with a given pad value from 0 to 0xFF.
<code class="Nm">rgbfix</code> will automatically pick a size from 32 KiB,
64 KiB, 128 KiB, ..., 8192 KiB. The cartridge size byte
(<span class="Ad">0x148</span>) will be changed to reflect this new
size.</dd>
<dt><a class="permalink" href="#r"><code class="Fl" id="r">-r</code></a>
<var class="Ar">ram_size</var>,
<code class="Fl">--ram-size</code>
<var class="Ar">ram_size</var></dt>
<dd>Set the RAM size, <span class="Ad">0x149</span>, to a given value from 0
to 0xFF.</dd>
<dt><a class="permalink" href="#s"><code class="Fl" id="s">-s</code></a>,
<code class="Fl">--sgb-compatible</code></dt>
<dd>Set the SGB flag: <span class="Ad">0x146</span> = 3. This flag will be
ignored by the SGB unless the old licensee code is 0x33!</dd>
<dt><a class="permalink" href="#t"><code class="Fl" id="t">-t</code></a>
<var class="Ar">title</var>,
<code class="Fl">--title</code>
<var class="Ar">title</var></dt>
<dd>Set the title string
(<span class="Ad">0x134</span>&#x2013;<span class="Ad">0x143</span>) to a
given string, truncated to at most 16 characters. It is recommended to use
15 characters instead, to avoid clashing with the CGB flag
(<code class="Fl">-c</code> or <code class="Fl">-C</code>). If both this
and the game ID are set, the game ID will overwrite the overlapping
portion of the title.</dd>
<dt><a class="permalink" href="#V"><code class="Fl" id="V">-V</code></a>,
<code class="Fl">--version</code></dt>
<dd>Print the version of the program and exit.</dd>
<dt><a class="permalink" href="#v"><code class="Fl" id="v">-v</code></a>,
<code class="Fl">--validate</code></dt>
<dd>Equivalent to <code class="Fl">-f</code> <code class="Cm">lhg</code>.</dd>
</dl>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
Most values in the ROM header are only cosmetic. The bare minimum requirements
for a workable program are the header checksum, the Nintendo logo, and (if
needed) the CGB/SGB flags. It is a good idea to pad the image to a valid size
as well (&#x201C;valid&#x201D; meaning a power of 2, times 32 KiB).
<p class="Pp">The following will make a plain, non-color Game Boy game without
checking for a valid size:</p>
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgbfix -v foo.gb</div>
<p class="Pp">The following will make a SGB-enabled, color-enabled game with a
title of &#x201C;foobar&#x201D;, and pad it to a valid size. (The Game Boy
itself does not use the title, but some emulators or ROM managers do.)</p>
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgbfix -vcs -l 0x33 -p 255 -t foobar baz.gb</div>
<p class="Pp">The following will duplicate the header (sans global checksum) of
the game &#x201C;Survival Kids&#x201D;:</p>
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgbfix -cjsv -k A4 -l 0x33 -m 0x1B -p 0xFF -r 3 -t
SURVIVALKIDAVKE SurvivalKids.gbc</div>
</section>
<section class="Sh">
<h1 class="Sh" id="BUGS"><a class="permalink" href="#BUGS">BUGS</a></h1>
Please report bugs on
<a class="Lk" href="https://github.com/rednex/rgbds/issues">GitHub</a>.
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>, <a class="Xr" href="rgblink.1.html">rgblink(1)</a>,
<a class="Xr" href="rgbds.7.html">rgbds(7)</a>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<code class="Nm">rgbfix</code> was originally released by Carsten
S&#x00F8;rensen as a standalone program called gbfix, and was later packaged
in RGBDS by Justin Lloyd. It is now maintained by a number of contributors at
<a class="Lk" href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a>.
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">December 5, 2019</td>
<td class="foot-os">General</td>
</tr>
</table>
</body>
</html>
-220
View File
@@ -1,220 +0,0 @@
<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
This file is part of RGBDS.
Copyright (c) 2013-2018, stag019 and RGBDS contributors.
SPDX-License-Identifier: MIT
-->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<link rel="stylesheet" href="mandoc.css" type="text/css" media="all"/>
<link rel="stylesheet" href="rgbds.css" type="text/css" media="all"/>
<title>RGBGFX(1)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">RGBGFX(1)</td>
<td class="head-vol">General Commands Manual</td>
<td class="head-rtitle">RGBGFX(1)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">rgbgfx</code> &#x2014;
<span class="Nd">Game Boy graphics converter</span>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<table class="Nm">
<tr>
<td><code class="Nm">rgbgfx</code></td>
<td>[<code class="Fl"><a href="#C">-C</a><a href="#D">D</a><a href="#h">h</a><a href="#m">m</a><a href="#u">u</a><a href="#V">V</a><a href="#v">v</a></code>] [<code class="Fl"><a href="#f">-f</a></code> |
<code class="Fl"><a href="#F">-F</a></code>] [<code class="Fl"><a href="#a">-a</a></code>
<var class="Ar">attrmap</var> | <code class="Fl"><a href="#A">-A</a></code>]
[<code class="Fl"><a href="#d">-d</a></code> <var class="Ar">depth</var>]
[<code class="Fl"><a href="#o">-o</a></code> <var class="Ar">out_file</var>]
[<code class="Fl"><a href="#p">-p</a></code> <var class="Ar">pal_file</var> |
<code class="Fl"><a href="#P">-P</a></code>] [<code class="Fl"><a href="#t">-t</a></code>
<var class="Ar">tilemap</var> | <code class="Fl"><a href="#T">-T</a></code>]
[<code class="Fl"><a href="#x">-x</a></code> <var class="Ar">tiles</var>]
<var class="Ar">file</var></td>
</tr>
</table>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
The <code class="Nm">rgbgfx</code> program converts PNG images into the Nintendo
Game Boy's planar tile format.
<p class="Pp">The resulting colors and their palette indices are determined
differently depending on the input PNG file:</p>
<ul class="Bl-dash">
<li>If the file has an embedded palette, that palette's color and order are
used.</li>
<li>If not, and the image only contains shades of gray, rgbgfx maps them to
the indices appropriate for each shade. Any undetermined indices are set
to respective default shades of gray. For example: if the bit depth is 2
and the image contains light gray and black, they become the second and
fourth colors, and the first and third colors get set to default white and
dark gray. If the image has multiple shades that map to the same index,
the palette is instead determined as if the image had color.</li>
<li>If the image has color (or the grayscale method failed), the colors are
sorted from lightest to darkest.</li>
</ul>
<p class="Pp">The input image may not contain more colors than the selected bit
depth allows. Transparent pixels are set to palette index 0.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="ARGUMENTS"><a class="permalink" href="#ARGUMENTS">ARGUMENTS</a></h1>
Note that options can be abbreviated as long as the abbreviation is unambiguous:
<code class="Fl">--verb</code> is
<code class="Fl">-</code> <code class="Fl">-verbose</code>, but
<code class="Fl">--ver</code> is invalid because it
could also be <code class="Fl">--version</code>. The
arguments are as follows:
<dl class="Bl-tag">
<dt><a class="permalink" href="#a"><code class="Fl" id="a">-a</code></a>
<var class="Ar">attrmap,</var>
<code class="Fl">--attr-map</code>
<var class="Ar">attrmap</var></dt>
<dd>Generate a file of tile mirroring attributes for OAM or (CGB-only)
background tiles. For each tile in the input file, a byte is written
representing the dimensions that the associated tile in the output file
should be mirrored. Useful in combination with <code class="Fl">-m</code>
to keep track the mirror direction of mirrored duplicate tiles.</dd>
<dt><a class="permalink" href="#A"><code class="Fl" id="A">-A</code></a>,
<code class="Fl">--output-attr-map</code></dt>
<dd>Same as <code class="Fl">-a</code>, but the attrmap file output name is
made by taking the input filename, removing the file extension, and
appending <span class="Pa">.attrmap</span>.</dd>
<dt><a class="permalink" href="#C"><code class="Fl" id="C">-C</code></a>,
<code class="Fl">--color-curve</code></dt>
<dd>Use the color curve of the Game Boy Color when generating palettes.</dd>
<dt><a class="permalink" href="#D"><code class="Fl" id="D">-D</code></a>,
<code class="Fl">--debug</code></dt>
<dd>Debug features are enabled.</dd>
<dt><a class="permalink" href="#d"><code class="Fl" id="d">-d</code></a>
<var class="Ar">depth</var>,
<code class="Fl">--depth</code>
<var class="Ar">depth</var></dt>
<dd>The bit depth of the output image (either 1 or 2). By default, the bit
depth is 2 (two bits per pixel).</dd>
<dt><a class="permalink" href="#f"><code class="Fl" id="f">-f</code></a>,
<code class="Fl">--fix</code></dt>
<dd>Fix the input PNG file to be a correctly indexed image.</dd>
<dt><a class="permalink" href="#F"><code class="Fl" id="F">-F</code></a>,
<code class="Fl">--fix-and-save</code></dt>
<dd>Same as <code class="Fl">-f</code>, but additionally, the supplied command
line parameters are saved within the PNG and will be loaded and
automatically used next time.</dd>
<dt><a class="permalink" href="#h"><code class="Fl" id="h">-h</code></a>,
<code class="Fl">--horizontal</code></dt>
<dd>Lay out tiles horizontally rather than vertically.</dd>
<dt><a class="permalink" href="#m"><code class="Fl" id="m">-m</code></a>,
<code class="Fl">--mirror-tiles</code></dt>
<dd>Truncate tiles by checking for tiles that are mirrored versions of others
and omitting these from the output file. Useful with tilemaps and attrmaps
together to keep track of the duplicated tiles and the dimension mirrored.
Tiles are checked for horizontal, vertical, and horizontal-vertical
mirroring. Implies <code class="Fl">-u</code>.</dd>
<dt><a class="permalink" href="#o"><code class="Fl" id="o">-o</code></a>
<var class="Ar">out_file</var>,
<code class="Fl">--output</code>
<var class="Ar">out_file</var></dt>
<dd>The name of the output file.</dd>
<dt><a class="permalink" href="#p"><code class="Fl" id="p">-p</code></a>
<var class="Ar">pal_file</var>,
<code class="Fl">--palette</code>
<var class="Ar">pal_file</var></dt>
<dd>Output the image's palette in standard GBC palette format: bytes (8 bytes
for two bits per pixel, 4 bytes for one bit per pixel) containing the
RGB15 values in little-endian byte order. If the palette contains too few
colors, the remaining entries are set to black.</dd>
<dt><a class="permalink" href="#P"><code class="Fl" id="P">-P</code></a>,
<code class="Fl">--output-palette</code></dt>
<dd>Same as <code class="Fl">-p</code>, but the palette file output name is
made by taking the input PNG file's filename, removing the file extension,
and appending <span class="Pa">.pal</span>.</dd>
<dt><a class="permalink" href="#t"><code class="Fl" id="t">-t</code></a>
<var class="Ar">tilemap</var>,
<code class="Fl">--tilemap</code>
<var class="Ar">tilemap</var></dt>
<dd>Generate a file of tile indices. For each tile in the input file, a byte
is written representing the index of the associated tile in the output
file. Useful in combination with <code class="Fl">-u</code> or
<code class="Fl">-m</code> to keep track of duplicate tiles.</dd>
<dt><a class="permalink" href="#T"><code class="Fl" id="T">-T</code></a>,
<code class="Fl">--output-tilemap</code></dt>
<dd>Same as <code class="Fl">-t</code>, but the tilemap file output name is
made by taking the input filename, removing the file extension, and
appending <span class="Pa">.tilemap</span>.</dd>
<dt><a class="permalink" href="#u"><code class="Fl" id="u">-u</code></a>,
<code class="Fl">--unique-tiles</code></dt>
<dd>Truncate tiles by checking for tiles that are exact duplicates of others
and omitting these from the output file. Useful with tilemaps to keep
track of the duplicated tiles.</dd>
<dt><a class="permalink" href="#V"><code class="Fl" id="V">-V</code></a>,
<code class="Fl">--version</code></dt>
<dd>Print the version of the program and exit.</dd>
<dt><a class="permalink" href="#v"><code class="Fl" id="v">-v</code></a>,
<code class="Fl">--verbose</code></dt>
<dd>Verbose. Print errors when the command line parameters and the parameters
in the PNG file don't match.</dd>
<dt><a class="permalink" href="#x"><code class="Fl" id="x">-x</code></a>
<var class="Ar">tiles</var>,
<code class="Fl">--trim-end</code>
<var class="Ar">tiles</var></dt>
<dd>Trim the end of the output file by this many tiles.</dd>
</dl>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
The following will take a PNG file with a bit depth of 1, 2, or 8, and output
planar 2bpp data:
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgbgfx -o out.2bpp in.png</div>
<p class="Pp">The following creates a planar 2bpp file with only unique tiles,
and its tilemap <span class="Pa">out.tilemap</span>:</p>
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgbgfx -T -u -o out.2bpp in.png</div>
<p class="Pp">The following creates a planar 2bpp file with only unique tiles
<span class="Pa">accounting for tile mirroring</span> and its associated
tilemap <span class="Pa">out.tilemap</span> and attrmap
<span class="Pa">out.attrmap</span>:</p>
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgbgfx -A -T -m -o out.2bpp in.png</div>
<p class="Pp">The following will do nothing:</p>
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgbgfx in.png</div>
</section>
<section class="Sh">
<h1 class="Sh" id="BUGS"><a class="permalink" href="#BUGS">BUGS</a></h1>
Please report bugs on
<a class="Lk" href="https://github.com/rednex/rgbds/issues">GitHub</a>.
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<a class="Xr" href="rgbds.7.html">rgbds(7)</a>, <a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>,
<a class="Xr" href="rgblink.1.html">rgblink(1)</a>, <a class="Xr" href="rgbfix.1.html">rgbfix(1)</a>,
<a class="Xr" href="gbz80.7.html">gbz80(7)</a>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<code class="Nm">rgbgfx</code> was created by <span class="An">stag019</span> to
be included in RGBDS. It is now maintained by a number of contributors at
<a class="Lk" href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a>.
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">December 5, 2019</td>
<td class="foot-os">General</td>
</tr>
</table>
</body>
</html>
-183
View File
@@ -1,183 +0,0 @@
<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
This file is part of RGBDS.
Copyright (c) 2010-2019, Anthony J. Bentley and RGBDS contributors.
SPDX-License-Identifier: MIT
-->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<link rel="stylesheet" href="mandoc.css" type="text/css" media="all"/>
<link rel="stylesheet" href="rgbds.css" type="text/css" media="all"/>
<title>RGBLINK(1)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">RGBLINK(1)</td>
<td class="head-vol">General Commands Manual</td>
<td class="head-rtitle">RGBLINK(1)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">rgblink</code> &#x2014;
<span class="Nd">Game Boy linker</span>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<table class="Nm">
<tr>
<td><code class="Nm">rgblink</code></td>
<td>[<code class="Fl"><a href="#d">-d</a><a href="#t">t</a><a href="#V">V</a><a href="#v">v</a><a href="#w">w</a></code>] [<code class="Fl"><a href="#l">-l</a></code>
<var class="Ar">linker_script</var>] [<code class="Fl"><a href="#m">-m</a></code>
<var class="Ar">map_file</var>] [<code class="Fl"><a href="#n">-n</a></code>
<var class="Ar">sym_file</var>] [<code class="Fl"><a href="#O">-O</a></code>
<var class="Ar">overlay_file</var>] [<code class="Fl"><a href="#o">-o</a></code>
<var class="Ar">out_file</var>] [<code class="Fl"><a href="#p">-p</a></code>
<var class="Ar">pad_value</var>] [<code class="Fl"><a href="#s">-s</a></code>
<var class="Ar">symbol</var>] <var class="Ar">file ...</var></td>
</tr>
</table>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
The <code class="Nm">rgblink</code> program links RGB object files, typically
created by <a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>, into a single Game Boy ROM file. The
format is documented in <a class="Xr" href="rgbds.5.html">rgbds(5)</a>.
<p class="Pp">ROM0 sections are placed in the first 16 KiB of the output ROM,
and ROMX sections are placed in any 16 KiB &#x201C;bank&#x201D; except the
first. If your ROM will only be 32 KiB, you can use the
<code class="Fl">-t</code> option to change this.</p>
<p class="Pp">Similarly, WRAM0 sections are placed in the first 4 KiB of WRAM
(&#x201C;bank 0&#x201D;), and WRAMX sections are placed in any bank of the
last 4 KiB. If your ROM doesn't use banked WRAM, you can use the
<code class="Fl">-w</code> option to change this.</p>
<p class="Pp">Also, if your ROM is designed for a monochrome Game Boy, you can
make sure that you don't use any incompatible section by using the
<code class="Fl">-d</code> option, which implies <code class="Fl">-w</code>
but also prohibits the use of banked VRAM.</p>
<p class="Pp">Note that options can be abbreviated as long as the abbreviation
is unambiguous: <code class="Fl">--verb</code> is
<code class="Fl">--verbose</code>, but
<code class="Fl">--ver</code> is invalid because it
could also be <code class="Fl">--version</code>. The
arguments are as follows:</p>
<dl class="Bl-tag">
<dt><a class="permalink" href="#d"><code class="Fl" id="d">-d</code></a>,
<code class="Fl">--dmg</code></dt>
<dd>Enable DMG mode. Prohibit the use of sections that doesn't exist on a DMG,
such as WRAMX and VRAM bank 1. This option automatically enables
<code class="Fl">-w</code>.</dd>
<dt><a class="permalink" href="#l"><code class="Fl" id="l">-l</code></a>
<var class="Ar">linker_script,</var>
<code class="Fl">--linkerscript</code>
<var class="Ar">linker_script</var></dt>
<dd>Specify a linker script file that tells the linker how sections must be
placed in the ROM. The attributes assigned in the linker script must be
consistent with any assigned in the code. See <a class="Xr" href="rgblink.5.html">rgblink(5)</a>
for more information about the linker script format.</dd>
<dt><a class="permalink" href="#m"><code class="Fl" id="m">-m</code></a>
<var class="Ar">map_file</var>,
<code class="Fl">--map</code>
<var class="Ar">map_file</var></dt>
<dd>Write a map file to the given filename, listing how sections and symbols
were assigned.</dd>
<dt><a class="permalink" href="#n"><code class="Fl" id="n">-n</code></a>
<var class="Ar">sym_file</var>,
<code class="Fl">--sym</code>
<var class="Ar">sym_file</var></dt>
<dd>Write a symbol file to the given filename, listing the address of all
exported symbols. Several external programs can use this information, for
example to help debugging ROMs.</dd>
<dt><a class="permalink" href="#O"><code class="Fl" id="O">-O</code></a>
<var class="Ar">overlay_file</var>,
<code class="Fl">--overlay</code>
<var class="Ar">overlay_file</var></dt>
<dd>If specified, sections will be overlaid &quot;on top&quot; of the provided
ROM image. In that case, all sections must be fixed. This may be used to
patch an existing binary.</dd>
<dt><a class="permalink" href="#o"><code class="Fl" id="o">-o</code></a>
<var class="Ar">out_file</var>,
<code class="Fl">--output</code>
<var class="Ar">out_file</var></dt>
<dd>Write the ROM image to the given file.</dd>
<dt><a class="permalink" href="#p"><code class="Fl" id="p">-p</code></a>
<var class="Ar">pad_value</var>,
<code class="Fl">--pad</code>
<var class="Ar">pad_value</var></dt>
<dd>When inserting padding between sections, pad with this value. Has no
effect if <code class="Fl">-O</code> is specified. The default is 0.</dd>
<dt><a class="permalink" href="#s"><code class="Fl" id="s">-s</code></a>
<var class="Ar">symbol</var>,
<code class="Fl">--smart</code>
<var class="Ar">symbol</var></dt>
<dd>This option is ignored. It was supposed to perform smart linking but fell
into disrepair, and so has been removed. It will be reimplemented at some
point.</dd>
<dt><a class="permalink" href="#t"><code class="Fl" id="t">-t</code></a>,
<code class="Fl">--tiny</code></dt>
<dd>Expand the ROM0 section size from 16 KiB to the full 32 KiB assigned to
ROM and prohibit the use of ROMX sections. Useful for ROMs that fit in 32
KiB.</dd>
<dt><a class="permalink" href="#V"><code class="Fl" id="V">-V</code></a>,
<code class="Fl">--version</code></dt>
<dd>Print the version of the program and exit.</dd>
<dt><a class="permalink" href="#v"><code class="Fl" id="v">-v</code></a>,
<code class="Fl">--verbose</code></dt>
<dd>Verbose: enable printing more information to standard error.</dd>
<dt><a class="permalink" href="#w"><code class="Fl" id="w">-w</code></a>,
<code class="Fl">--wramx</code></dt>
<dd>Expand the WRAM0 section size from 4 KiB to the full 8 KiB assigned to
WRAM and prohibit the use of WRAMX sections.</dd>
</dl>
</section>
<section class="Sh">
<h1 class="Sh" id="EXAMPLES"><a class="permalink" href="#EXAMPLES">EXAMPLES</a></h1>
All you need for a basic ROM is an object file, which can be made into a ROM
image like so:
<p class="Pp"></p>
<div class="Bd Bd-indent">$ rgblink -o bar.gb foo.o</div>
<p class="Pp">The resulting <var class="Ar">bar.gb</var> will not have correct
checksums (unless you put them in the assembly source). You should use
<a class="Xr" href="rgbfix.1.html">rgbfix(1)</a> to fix these so that the program will actually
run in a Game Boy:</p>
<p class="Pp"></p>
<div class="Bd Bd-indent"><code class="Li">$ rgbfix -v bar.gb</code></div>
<p class="Pp">Here is a more complete example:</p>
<p class="Pp"></p>
<div class="Bd Bd-indent"><code class="Li">$ rgblink -o bin/game.gb -n
bin/game.sym -p 0xFF obj/title.o obj/engine.o</code></div>
</section>
<section class="Sh">
<h1 class="Sh" id="BUGS"><a class="permalink" href="#BUGS">BUGS</a></h1>
Please report bugs on
<a class="Lk" href="https://github.com/rednex/rgbds/issues">GitHub</a>.
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>, <a class="Xr" href="rgblink.5.html">rgblink(5)</a>,
<a class="Xr" href="rgbfix.1.html">rgbfix(1)</a>, <a class="Xr" href="rgbds.5.html">rgbds(5)</a>,
<a class="Xr" href="rgbds.7.html">rgbds(7)</a>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<code class="Nm">rgblink</code> was originally written by Carsten
S&#x00F8;rensen as part of the ASMotor package, and was later packaged in
RGBDS by Justin Lloyd. It is now maintained by a number of contributors at
<a class="Lk" href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a>.
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">November 26, 2019</td>
<td class="foot-os">General</td>
</tr>
</table>
</body>
</html>
-111
View File
@@ -1,111 +0,0 @@
<!DOCTYPE html>
<html>
<!-- This is an automatically generated file. Do not edit.
This file is part of RGBDS.
Copyright (c) 2017-2018, Antonio Nino Diaz and RGBDS contributors.
SPDX-License-Identifier: MIT
-->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8"/>
<link rel="stylesheet" href="mandoc.css" type="text/css" media="all"/>
<link rel="stylesheet" href="rgbds.css" type="text/css" media="all"/>
<title>RGBLINK(5)</title>
</head>
<body>
<table class="head">
<tr>
<td class="head-ltitle">RGBLINK(5)</td>
<td class="head-vol">File Formats Manual</td>
<td class="head-rtitle">RGBLINK(5)</td>
</tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<code class="Nm">rgblink</code> &#x2014;
<span class="Nd">linker script file format</span>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
The linker script is an external file that allows the user to specify the order
of sections at link time and in a centralized manner.
<p class="Pp">A linker script consists on a series of banks followed by a list
of sections and, optionally, commands. They can be lowercase or uppercase,
it is ignored. Any line can contain a comment starting with
&#x2018;<code class="Li">;</code>&#x2019; that ends at the end of the
line:</p>
<div class="Bd Pp Bd-indent">
<pre>
ROMX $F ; This is a comment
&quot;Functions to read array&quot;
ALIGN 8
&quot;Array aligned to 256 bytes&quot;
WRAMX 2
&quot;Some variables&quot;
</pre>
</div>
<p class="Pp">Numbers can be in decimal or hexadecimal format (the prefix is
&#x2018;<code class="Li">$</code>&#x2019;). It is an error if any section
name or command is found before setting a bank.</p>
<p class="Pp">Files can be included by using the <code class="Ic">INCLUDE</code>
keyword, followed by a string with the path of the file that has to be
included.</p>
<p class="Pp">The possible bank types are: <code class="Cm">ROM0</code>,
<code class="Cm">ROMX</code>, <code class="Cm">VRAM</code>,
<code class="Cm">SRAM</code>, <code class="Cm">WRAM0</code>,
<code class="Cm">WRAMX</code>, <code class="Cm">OAM</code> and
<code class="Cm">HRAM</code>. Unless there is a single bank, which can occur
with types <code class="Cm">ROMX</code>, <code class="Cm">VRAM</code>,
<code class="Cm">SRAM</code> and <code class="Cm">WRAMX</code>, it is needed
to specify a bank number after the type.</p>
<p class="Pp">When a new bank statement is found, sections found after it will
be placed right from the beginning of that bank. If the linker script
switches to a different bank and then comes back to a previous one, it will
continue from the last address that was used.</p>
<p class="Pp">The only two commands are <code class="Ic">ORG</code> and
<code class="Ic">ALIGN</code>:</p>
<ul class="Bl-bullet">
<li><a class="permalink" href="#ORG"><code class="Ic" id="ORG">ORG</code></a>
sets the address in which new sections will be placed. It can not be lower
than the current address.</li>
<li><a class="permalink" href="#ALIGN"><code class="Ic" id="ALIGN">ALIGN</code></a>
will increase the address until it is aligned to the specified boundary
(it tries to set to 0 the number of bits specified after the command:
&#x2018;<code class="Li">ALIGN 8</code>&#x2019; will align to $100).</li>
</ul>
<p class="Pp"><b class="Sy">Note:</b> The bank, alignment, address and type of
sections can be specified both in the source code and in the linker script.
For a section to be able to be placed with the linker script, the bank,
address and alignment must be left unassigned in the source code or be
compatible with what is specified in the linker script. For example,
&#x2018;<code class="Li">ALIGN[8]</code>&#x2019; in the source code is
compatible with &#x2018;<code class="Li">ORG $F00</code>&#x2019; in the
linker script.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
ALSO</a></h1>
<a class="Xr" href="rgbasm.1.html">rgbasm(1)</a>, <a class="Xr" href="rgblink.1.html">rgblink(1)</a>,
<a class="Xr" href="rgbfix.1.html">rgbfix(1)</a>, <a class="Xr" href="rgbds.5.html">rgbds(5)</a>,
<a class="Xr" href="rgbds.7.html">rgbds(7)</a>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<code class="Nm">rgblink</code> was originally written by Carsten
S&#x00F8;rensen as part of the ASMotor package, and was later packaged in
RGBDS by Justin Lloyd. It is now maintained by a number of contributors at
<a class="Lk" href="https://github.com/rednex/rgbds">https://github.com/rednex/rgbds</a>.
</section>
</div>
<table class="foot">
<tr>
<td class="foot-date">November 26, 2019</td>
<td class="foot-os">General</td>
</tr>
</table>
</body>
</html>
-43
View File
@@ -1,43 +0,0 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/*
* Contains some assembler-wide defines and externs
*/
#ifndef RGBDS_ASM_ASM_H
#define RGBDS_ASM_ASM_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "asm/localasm.h"
#include "asm/symbol.h"
#define MAXUNIONS 128
#define MAXMACROARGS 256
#define MAXINCPATHS 128
extern int32_t nLineNo;
extern uint32_t nTotalLines;
extern uint32_t nIFDepth;
extern bool skipElif;
extern uint32_t nUnionDepth;
extern uint32_t unionStart[MAXUNIONS];
extern uint32_t unionSize[MAXUNIONS];
extern char tzCurrentFileName[_MAX_PATH + 1];
extern struct Section *pCurrentSection;
extern struct sSymbol *pPCSymbol;
extern bool oDontExpandStrings;
size_t symvaluetostring(char *dest, size_t maxLength, char *sym,
const char *mode);
#endif /* RGBDS_ASM_ASM_H */
+3 -27
View File
@@ -11,36 +11,12 @@
#include <stdint.h>
#define MAXCHARMAPS 512
#define CHARMAPLENGTH 16
#define MAXCHARNODES (MAXCHARMAPS * CHARMAPLENGTH + 1)
/*
* A node for trie structure.
*/
struct Charnode {
uint8_t code; /* the value in a key-value pair. */
uint8_t isCode; /* has 1 if it's a code node, not just a bridge node. */
struct Charnode *next[256]; /* each index representing the next possible
* character from its current state.
*/
};
struct Charmap {
char name[MAXSYMLEN + 1];
int32_t charCount; /* user-side count. */
int32_t nodeCount; /* node-side count. */
struct Charnode nodes[MAXCHARNODES]; /* first node is reserved for the
* root node in charmap.
*/
};
void charmap_InitMain(void);
struct Charmap *charmap_New(const char *name, const char *baseName);
void charmap_Delete(struct Charmap *charmap);
void charmap_Set(const char *name);
void charmap_Push(void);
void charmap_Pop(void);
int32_t charmap_Add(char *input, uint8_t output);
int32_t charmap_Convert(char **input);
void charmap_Add(char *mapping, uint8_t value);
size_t charmap_Convert(char const *input, uint8_t *output);
#endif /* RGBDS_ASM_CHARMAP_H */
+31
View File
@@ -0,0 +1,31 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_FIXPOINT_H
#define RGBDS_ASM_FIXPOINT_H
#include <stdint.h>
int32_t fix_Callback_PI(void);
void fix_Print(int32_t i);
int32_t fix_Sin(int32_t i);
int32_t fix_Cos(int32_t i);
int32_t fix_Tan(int32_t i);
int32_t fix_ASin(int32_t i);
int32_t fix_ACos(int32_t i);
int32_t fix_ATan(int32_t i);
int32_t fix_ATan2(int32_t i, int32_t j);
int32_t fix_Mul(int32_t i, int32_t j);
int32_t fix_Div(int32_t i, int32_t j);
int32_t fix_Pow(int32_t i, int32_t j);
int32_t fix_Log(int32_t i, int32_t j);
int32_t fix_Round(int32_t i);
int32_t fix_Ceil(int32_t i);
int32_t fix_Floor(int32_t i);
#endif /* RGBDS_ASM_FIXPOINT_H */
+63
View File
@@ -0,0 +1,63 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_FORMAT_SPEC_H
#define RGBDS_FORMAT_SPEC_H
#include <stdint.h>
#include <stdbool.h>
enum FormatState {
FORMAT_SIGN, // expects '+' or ' ' (optional)
FORMAT_PREFIX, // expects '#' (optional)
FORMAT_ALIGN, // expects '-' (optional)
FORMAT_WIDTH, // expects '0'-'9', max 255 (optional) (leading '0' indicates pad)
FORMAT_FRAC, // got '.', expects '0'-'9', max 255 (optional)
FORMAT_DONE, // got [duXxbofs] (required)
FORMAT_INVALID, // got unexpected character
};
struct FormatSpec {
enum FormatState state;
int sign;
bool prefix;
bool alignLeft;
bool padZero;
uint8_t width;
bool hasFrac;
uint8_t fracWidth;
int type;
bool valid;
};
struct StrFmtArg {
union {
uint32_t number;
char *string;
};
bool isNumeric;
};
#define INITIAL_STRFMT_ARG_SIZE 4
struct StrFmtArgList {
char *format;
size_t nbArgs;
size_t capacity;
struct StrFmtArg *args;
};
struct FormatSpec fmt_NewSpec(void);
bool fmt_IsEmpty(struct FormatSpec const *fmt);
bool fmt_IsValid(struct FormatSpec const *fmt);
bool fmt_IsFinished(struct FormatSpec const *fmt);
void fmt_UseCharacter(struct FormatSpec *fmt, int c);
void fmt_FinishCharacters(struct FormatSpec *fmt);
void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, char const *value);
void fmt_PrintNumber(char *buf, size_t bufLen, struct FormatSpec const *fmt, uint32_t value);
#endif /* RGBDS_FORMAT_SPEC_H */
+55 -28
View File
@@ -13,44 +13,71 @@
#ifndef RGBDS_ASM_FSTACK_H
#define RGBDS_ASM_FSTACK_H
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "asm/asm.h"
#include "asm/lexer.h"
#include "types.h"
struct MacroArgs;
struct FileStackNode {
struct FileStackNode *parent; /* Pointer to parent node, for error reporting */
/* Line at which the parent context was exited; meaningless for the root level */
uint32_t lineNo;
struct sContext {
YY_BUFFER_STATE FlexHandle;
struct sSymbol *pMacro;
struct sContext *pNext;
char tzFileName[_MAX_PATH + 1];
struct MacroArgs *macroArgs;
uint32_t uniqueID;
int32_t nLine;
uint32_t nStatus;
FILE *pFile;
char *pREPTBlock;
uint32_t nREPTBlockCount;
uint32_t nREPTBlockSize;
int32_t nREPTBodyFirstLine;
int32_t nREPTBodyLastLine;
struct FileStackNode *next; /* Next node in the output linked list */
bool referenced; /* If referenced, don't free! */
uint32_t ID; /* Set only if referenced: ID within the object file, -1 if not output yet */
enum {
NODE_REPT,
NODE_FILE,
NODE_MACRO,
} type;
};
extern unsigned int nMaxRecursionDepth;
struct FileStackReptNode { /* NODE_REPT */
struct FileStackNode node;
uint32_t reptDepth;
/* WARNING: if changing this type, change overflow check in `fstk_Init` */
uint32_t iters[]; /* REPT iteration counts since last named node, in reverse depth order */
};
void fstk_RunInclude(char *tzFileName);
void fstk_Init(char *s);
void fstk_Dump(void);
void fstk_DumpToStr(char *buf, size_t len);
void fstk_DumpStringExpansions(void);
void fstk_AddIncludePath(char *s);
bool fstk_RunMacro(char *s, struct MacroArgs *args);
void fstk_RunRept(uint32_t count, int32_t nReptLineNo);
FILE *fstk_FindFile(char const *fname, char **incPathUsed);
int32_t fstk_GetLine(void);
struct FileStackNamedNode { /* NODE_FILE, NODE_MACRO */
struct FileStackNode node;
char name[]; /* File name for files, file::macro name for macros */
};
extern size_t nMaxRecursionDepth;
struct MacroArgs;
void fstk_Dump(struct FileStackNode const *node, uint32_t lineNo);
void fstk_DumpCurrent(void);
struct FileStackNode *fstk_GetFileStack(void);
/* The lifetime of the returned chars is until reaching the end of that file */
char const *fstk_GetFileName(void);
void fstk_AddIncludePath(char const *s);
/**
* @param path The user-provided file name
* @param fullPath The address of a pointer, which will be made to point at the full path
* The pointer's value must be a valid argument to `realloc`, including NULL
* @param size Current size of the buffer, or 0 if the pointer is NULL
* @return True if the file was found, false if no path worked
*/
bool fstk_FindFile(char const *path, char **fullPath, size_t *size);
bool yywrap(void);
void fstk_RunInclude(char const *path);
void fstk_RunMacro(char const *macroName, struct MacroArgs *args);
void fstk_RunRept(uint32_t count, int32_t nReptLineNo, char *body, size_t size);
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
int32_t reptLineNo, char *body, size_t size);
void fstk_StopRept(void);
bool fstk_Break(void);
void fstk_Init(char const *mainPath, size_t maxRecursionDepth);
#endif /* RGBDS_ASM_FSTACK_H */
+79 -64
View File
@@ -9,78 +9,93 @@
#ifndef RGBDS_ASM_LEXER_H
#define RGBDS_ASM_LEXER_H
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#define LEXHASHSIZE (1 << 11)
#define MAXSTRLEN 255
struct sLexInitString {
char *tzName;
uint32_t nToken;
struct LexerState;
extern struct LexerState *lexerState;
extern struct LexerState *lexerStateEOL;
static inline struct LexerState *lexer_GetState(void)
{
return lexerState;
}
static inline void lexer_SetState(struct LexerState *state)
{
lexerState = state;
}
static inline void lexer_SetStateAtEOL(struct LexerState *state)
{
lexerStateEOL = state;
}
extern char binDigits[2];
extern char gfxDigits[4];
static inline void lexer_SetBinDigits(char const digits[2])
{
binDigits[0] = digits[0];
binDigits[1] = digits[1];
}
static inline void lexer_SetGfxDigits(char const digits[4])
{
gfxDigits[0] = digits[0];
gfxDigits[1] = digits[1];
gfxDigits[2] = digits[2];
gfxDigits[3] = digits[3];
}
/*
* `path` is referenced, but not held onto..!
*/
struct LexerState *lexer_OpenFile(char const *path);
struct LexerState *lexer_OpenFileView(char *buf, size_t size, uint32_t lineNo);
void lexer_RestartRept(uint32_t lineNo);
void lexer_DeleteState(struct LexerState *state);
void lexer_Init(void);
enum LexerMode {
LEXER_NORMAL,
LEXER_RAW,
LEXER_SKIP_TO_ELIF,
LEXER_SKIP_TO_ENDC,
LEXER_SKIP_TO_ENDR
};
struct sLexFloat {
uint32_t (*Callback)(char *s, uint32_t size);
uint32_t nToken;
void lexer_SetMode(enum LexerMode mode);
void lexer_ToggleStringExpansion(bool enable);
uint32_t lexer_GetIFDepth(void);
void lexer_IncIFDepth(void);
void lexer_DecIFDepth(void);
bool lexer_RanIFBlock(void);
bool lexer_ReachedELSEBlock(void);
void lexer_RunIFBlock(void);
void lexer_ReachELSEBlock(void);
struct CaptureBody {
uint32_t lineNo;
char *body;
size_t size;
};
struct yy_buffer_state {
/* Actual starting address */
char *pBufferRealStart;
/* Address where the data is initially written after a safety margin */
char *pBufferStart;
char *pBuffer;
size_t nBufferSize;
uint32_t oAtLineStart;
};
enum eLexerState {
LEX_STATE_NORMAL,
LEX_STATE_MACROARGS
};
struct sStringExpansionPos {
char *tzName;
char *pBuffer;
char *pBufferPos;
struct sStringExpansionPos *pParent;
};
#define INITIAL 0
#define macroarg 3
typedef struct yy_buffer_state *YY_BUFFER_STATE;
void setup_lexer(void);
void yy_set_state(enum eLexerState i);
YY_BUFFER_STATE yy_create_buffer(FILE *f);
YY_BUFFER_STATE yy_scan_bytes(char *mem, uint32_t size);
void yy_delete_buffer(YY_BUFFER_STATE buf);
void yy_switch_to_buffer(YY_BUFFER_STATE buf);
uint32_t lex_FloatAlloc(const struct sLexFloat *tok);
void lex_FloatAddRange(uint32_t id, uint16_t start, uint16_t end);
void lex_FloatDeleteRange(uint32_t id, uint16_t start, uint16_t end);
void lex_FloatAddFirstRange(uint32_t id, uint16_t start, uint16_t end);
void lex_FloatDeleteFirstRange(uint32_t id, uint16_t start, uint16_t end);
void lex_FloatAddSecondRange(uint32_t id, uint16_t start, uint16_t end);
void lex_FloatDeleteSecondRange(uint32_t id, uint16_t start, uint16_t end);
void lex_Init(void);
void lex_AddStrings(const struct sLexInitString *lex);
void lex_SetBuffer(char *buffer, uint32_t len);
void lex_BeginStringExpansion(const char *tzName);
int yywrap(void);
char const *lexer_GetFileName(void);
uint32_t lexer_GetLineNo(void);
uint32_t lexer_GetColNo(void);
void lexer_DumpStringExpansions(void);
int yylex(void);
void yyunput(char c);
void yyunputstr(const char *s);
void yyskipbytes(uint32_t count);
void yyunputbytes(uint32_t count);
void lexer_CaptureRept(struct CaptureBody *capture);
void lexer_CaptureMacroBody(struct CaptureBody *capture);
extern YY_BUFFER_STATE pCurrentBuffer;
extern struct sStringExpansionPos *pCurrentStringExpansion;
void upperstring(char *s);
void lowerstring(char *s);
#define INITIAL_DS_ARG_SIZE 2
struct DsArgList {
size_t nbArgs;
size_t capacity;
struct Expression *args;
};
#endif /* RGBDS_ASM_LEXER_H */
-131
View File
@@ -1,131 +0,0 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_LOCALASM_H
#define RGBDS_ASM_LOCALASM_H
/*
* GB Z80 instruction groups
*
* n3 = 3-bit
* n = 8-bit
* nn = 16-bit
*
* ADC A,n : 0xCE
* ADC A,r : 0x88|r
* ADD A,n : 0xC6
* ADD A,r : 0x80|r
* ADD HL,ss : 0x09|(ss<<4)
* ADD SP,n : 0xE8
* AND A,n : 0xE6
* AND A,r : 0xA0|r
* BIT n3,r : 0xCB 0x40|(n3<<3)|r
* CALL cc,nn : 0xC4|(cc<<3)
* CALL nn : 0xCD
* CCF : 0x3F
* CP A,n : 0xFE
* CP A,r : 0xB8|r
* CPL : 0x2F
* DAA : 0x27
* DEC r : 0x05|(r<<3)
* DEC ss : 0x0B|(ss<<4)
* DI : 0xF3
* EI : 0xFB
* HALT : 0x76
* INC r : 0x04|(r<<3)
* INC ss : 0x03|(ss<<4)
* JP HL : 0xE9
* JP cc,nn : 0xC2|(cc<<3)
* JP nn : 0xC3|(cc<<3)
* JR n : 0x18
* JR cc,n : 0x20|(cc<<3)
* LD (nn),SP : 0x08
* LD ($FF00+C),A : 0xE2
* LD ($FF00+n),A : 0xE0
* LD (nn),A : 0xEA
* LD (rr),A : 0x02|(rr<<4) // HL+ and HL- included
* LD A,($FF00+C) : 0xF2
* LD A,($FF00+n) : 0xF0
* LD A,(nn) : 0xFA
* LD A,(rr) : 0x0A|(rr<<4) // HL+ and HL- included
* LD HL,SP+n : 0xF8
* LD SP,HL : 0xF9
* LD r,n : 0x06|(r<<3)
* LD r,r' : 0x40|(r<<3)|r' // NOTE: LD (HL),(HL) not allowed
* LD ss,nn : 0x01|(ss<<4)
* NOP : 0x00
* OR A,n : 0xF6
* OR A,r : 0xB0|r
* POP tt : 0xC1|(tt<<4)
* PUSH tt : 0xC5|(tt<<4)
* RES n3,r : 0xCB 0x80|(n3<<3)|r
* RET : 0xC9
* RET cc : 0xC0|(cc<<3)
* RETI : 0xD9
* RL r : 0xCB 0x10|r
* RLA : 0x17
* RLC r : 0xCB 0x00|r
* RLCA : 0x07
* RR r : 0xCB 0x18|r
* RRA : 0x1F
* RRC r : 0xCB 0x08|r
* RRCA : 0x0F
* RST n : 0xC7|n
* SBC A,n : 0xDE
* SBC A,r : 0x98|r
* SCF : 0x37
* SET n3,r : 0xCB 0xC0|(n8<<3)|r
* SLA r : 0xCB 0x20|r
* SRA r : 0xCB 0x28|r
* SRL r : 0xCB 0x38|r
* STOP : 0x10 0x00
* SUB A,n : 0xD6
* SUB A,r : 0x90|r
* SWAP r : 0xCB 0x30|r
* XOR A,n : 0xEE
* XOR A,r : 0xA8|r
*/
/* "r" defs */
enum {
REG_B = 0,
REG_C,
REG_D,
REG_E,
REG_H,
REG_L,
REG_HL_IND,
REG_A
};
/* "rr" defs */
enum {
REG_BC_IND = 0,
REG_DE_IND,
REG_HL_INDINC,
REG_HL_INDDEC,
};
/* "ss" defs (SP) and "tt" defs (AF) */
enum {
REG_BC = 0,
REG_DE = 1,
REG_HL = 2,
REG_SP = 3,
REG_AF = 3
};
/* "cc" defs */
enum {
CC_NZ = 0,
CC_Z,
CC_NC,
CC_C
};
#endif /* RGBDS_ASM_LOCALASM_H */
+5 -2
View File
@@ -10,6 +10,7 @@
#define RGBDS_MACRO_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "asm/warning.h"
@@ -20,15 +21,17 @@ struct MacroArgs;
struct MacroArgs *macro_GetCurrentArgs(void);
struct MacroArgs *macro_NewArgs(void);
void macro_AppendArg(struct MacroArgs *args, char *s);
void macro_AppendArg(struct MacroArgs **args, char *s);
void macro_UseNewArgs(struct MacroArgs *args);
void macro_FreeArgs(struct MacroArgs *args);
char const *macro_GetArg(uint32_t i);
char *macro_GetAllArgs(void);
uint32_t macro_GetUniqueID(void);
char const *macro_GetUniqueIDStr(void);
void macro_SetUniqueID(uint32_t id);
void macro_ShiftCurrentArgs(void);
uint32_t macro_UseNewUniqueID(void);
void macro_ShiftCurrentArgs(int32_t count);
uint32_t macro_NbArgs(void);
#endif
+6 -25
View File
@@ -1,7 +1,7 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
@@ -15,26 +15,10 @@
#include "helpers.h"
struct sOptions {
char binary[2];
char gbgfx[4];
bool exportall;
int32_t fillchar;
bool haltnop;
bool optimizeloads;
bool verbose;
bool warnings; /* True to enable warnings, false to disable them. */
};
extern char *tzNewMacro;
extern uint32_t ulNewMacroSize;
extern int32_t nGBGfxID;
extern int32_t nBinaryID;
extern uint32_t curOffset; /* Offset into the current section */
extern struct sOptions DefaultOptions;
extern struct sOptions CurrentOptions;
extern bool haltnop;
extern bool optimizeloads;
extern bool verbose;
extern bool warnings; /* True to enable warnings, false to disable them. */
extern FILE *dependfile;
extern char *tzTargetFileName;
@@ -42,10 +26,7 @@ extern bool oGeneratedMissingIncludes;
extern bool oFailedOnMissingInclude;
extern bool oGeneratePhonyDeps;
void opt_Push(void);
void opt_Pop(void);
void opt_Parse(char *s);
/* TODO: are these really needed? */
#define YY_FATAL_ERROR fatalerror
#ifdef YYLMAX
-29
View File
@@ -1,29 +0,0 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_ASM_MATH_H
#define RGBDS_ASM_MATH_H
#include <stdint.h>
void math_DefinePI(void);
void math_Print(int32_t i);
int32_t math_Sin(int32_t i);
int32_t math_Cos(int32_t i);
int32_t math_Tan(int32_t i);
int32_t math_ASin(int32_t i);
int32_t math_ACos(int32_t i);
int32_t math_ATan(int32_t i);
int32_t math_ATan2(int32_t i, int32_t j);
int32_t math_Mul(int32_t i, int32_t j);
int32_t math_Div(int32_t i, int32_t j);
int32_t math_Round(int32_t i);
int32_t math_Ceil(int32_t i);
int32_t math_Floor(int32_t i);
#endif /* RGBDS_ASM_MATH_H */
+22
View File
@@ -0,0 +1,22 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2021, Eldred Habert and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_OPT_H
#define RGBDS_OPT_H
void opt_B(char chars[2]);
void opt_G(char chars[4]);
void opt_P(uint8_t fill);
void opt_Parse(char const *option);
void opt_Push(void);
void opt_Pop(void);
#endif
+4 -2
View File
@@ -14,13 +14,15 @@
#include "linkdefs.h"
struct Expression;
struct FileStackNode;
extern char *tzObjectname;
extern struct Section *pSectionList, *pCurrentSection;
void out_RegisterNode(struct FileStackNode *node);
void out_ReplaceNode(struct FileStackNode *node);
void out_SetFileName(char *s);
void out_CreatePatch(uint32_t type, struct Expression const *expr,
uint32_t ofs);
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift);
bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
char const *message, uint32_t ofs);
void out_WriteObject(void);
+3 -4
View File
@@ -27,9 +27,6 @@ struct Expression {
uint32_t nRPNPatchSize; // Size the expression will take in the obj file
};
/* FIXME: Should be defined in `asmy.h`, but impossible with POSIX Yacc */
extern int32_t nPCOffset;
/*
* Determines if an expression is known at assembly time
*/
@@ -46,9 +43,11 @@ static inline bool rpn_isSymbol(const struct Expression *expr)
return expr->isSymbol;
}
void rpn_Symbol(struct Expression *expr, char *tzSym);
void rpn_Symbol(struct Expression *expr, char const *tzSym);
void rpn_Number(struct Expression *expr, uint32_t i);
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym);
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
const struct Expression *src1,
const struct Expression *src2);
+39 -21
View File
@@ -10,49 +10,67 @@
#define RGBDS_SECTION_H
#include <stdint.h>
#include <stdbool.h>
#include "linkdefs.h"
extern uint8_t fillByte;
struct Expression;
struct Section {
char *pzName;
enum SectionType nType;
bool isUnion;
char *name;
enum SectionType type;
enum SectionModifier modifier;
struct FileStackNode *src; /* Where the section was defined */
uint32_t fileLine; /* Line where the section was defined */
uint32_t size;
uint32_t nOrg;
uint32_t nBank;
uint32_t nAlign;
struct Section *pNext;
struct Patch *pPatches;
uint8_t *tData;
uint32_t org;
uint32_t bank;
uint8_t align;
uint16_t alignOfs;
struct Section *next;
struct Patch *patches;
uint8_t *data;
};
struct SectionSpec {
uint32_t bank;
uint32_t alignment;
uint8_t alignment;
uint16_t alignOfs;
};
struct Section *out_FindSectionByName(const char *pzName);
void out_NewSection(char const *pzName, uint32_t secttype, uint32_t org,
struct SectionSpec const *attributes, bool isUnion);
struct Section *out_FindSectionByName(const char *name);
void out_NewSection(char const *name, uint32_t secttype, uint32_t org,
struct SectionSpec const *attributes,
enum SectionModifier mod);
void out_SetLoadSection(char const *name, uint32_t secttype, uint32_t org,
struct SectionSpec const *attributes);
struct SectionSpec const *attributes,
enum SectionModifier mod);
void out_EndLoadSection(void);
struct Section *sect_GetSymbolSection(void);
uint32_t sect_GetSymbolOffset(void);
uint32_t sect_GetOutputOffset(void);
void sect_AlignPC(uint8_t alignment, uint16_t offset);
void sect_StartUnion(void);
void sect_NextUnionMember(void);
void sect_EndUnion(void);
void sect_CheckUnionClosed(void);
void out_AbsByte(uint8_t b);
void out_AbsByteGroup(uint8_t const *s, int32_t length);
void out_Skip(int32_t skip);
void out_AbsWordGroup(uint8_t const *s, int32_t length);
void out_AbsLongGroup(uint8_t const *s, int32_t length);
void out_Skip(int32_t skip, bool ds);
void out_String(char const *s);
void out_RelByte(struct Expression *expr);
void out_RelBytes(struct Expression *expr, uint32_t n);
void out_RelWord(struct Expression *expr);
void out_RelLong(struct Expression *expr);
void out_PCRelByte(struct Expression *expr);
void out_BinaryFile(char const *s);
void out_RelByte(struct Expression *expr, uint32_t pcShift);
void out_RelBytes(uint32_t n, struct Expression *exprs, size_t size);
void out_RelWord(struct Expression *expr, uint32_t pcShift);
void out_RelLong(struct Expression *expr, uint32_t pcShift);
void out_PCRelByte(struct Expression *expr, uint32_t pcShift);
void out_BinaryFile(char const *s, int32_t startPos);
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
void out_PushSection(void);
+78 -41
View File
@@ -12,9 +12,11 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "asm/section.h"
#include "platform.h" // MIN_NB_ELMS
#include "types.h"
#define HASHSIZE (1 << 16)
@@ -29,53 +31,72 @@ enum SymbolType {
SYM_REF // Forward reference to a label
};
struct sSymbol {
char tzName[MAXSYMLEN + 1];
struct Symbol {
char name[MAXSYMLEN + 1];
enum SymbolType type;
bool isExported; /* Whether the symbol is to be exported */
bool isBuiltin; /* Whether the symbol is a built-in */
struct sSymbol *pScope;
struct Section *pSection;
int32_t nValue;
uint32_t ulMacroSize;
char *pMacro;
int32_t (*Callback)(struct sSymbol const *self);
char tzFileName[_MAX_PATH + 1]; /* File where the symbol was defined. */
uint32_t nFileLine; /* Line where the symbol was defined. */
struct Section *section;
struct FileStackNode *src; /* Where the symbol was defined */
uint32_t fileLine; /* Line where the symbol was defined */
bool hasCallback;
union {
/* If sym_IsNumeric */
int32_t value;
int32_t (*numCallback)(void);
/* For SYM_MACRO */
struct {
size_t macroSize;
char *macro;
};
/* For SYM_EQUS, TODO: separate "base" fields from SYM_MACRO */
char const *(*strCallback)(void); /* For SYM_EQUS */
};
uint32_t ID; /* ID of the symbol in the object file (-1 if none) */
struct sSymbol *next; /* Next object to output in the object file */
struct Symbol *next; /* Next object to output in the object file */
};
static inline bool sym_IsDefined(struct sSymbol const *sym)
bool sym_IsPC(struct Symbol const *sym);
static inline bool sym_IsDefined(struct Symbol const *sym)
{
return sym->type != SYM_REF;
}
static inline bool sym_IsConstant(struct sSymbol const *sym)
static inline struct Section *sym_GetSection(struct Symbol const *sym)
{
return sym->type == SYM_EQU || sym->type == SYM_SET
|| (sym->type == SYM_LABEL && sym->pSection
&& sym->pSection->nOrg != -1);
return sym_IsPC(sym) ? sect_GetSymbolSection() : sym->section;
}
static inline bool sym_IsNumeric(struct sSymbol const *sym)
static inline bool sym_IsConstant(struct Symbol const *sym)
{
if (sym->type == SYM_LABEL) {
struct Section const *sect = sym_GetSection(sym);
return sect && sect->org != (uint32_t)-1;
}
return sym->type == SYM_EQU || sym->type == SYM_SET;
}
static inline bool sym_IsNumeric(struct Symbol const *sym)
{
return sym->type == SYM_LABEL || sym->type == SYM_EQU
|| sym->type == SYM_SET;
}
static inline bool sym_IsLabel(struct sSymbol const *sym)
static inline bool sym_IsLabel(struct Symbol const *sym)
{
return sym->type == SYM_LABEL || sym->type == SYM_REF;
}
static inline bool sym_IsLocal(struct sSymbol const *sym)
static inline bool sym_IsLocal(struct Symbol const *sym)
{
return sym_IsLabel(sym) && strchr(sym->tzName, '.');
return sym_IsLabel(sym) && strchr(sym->name, '.');
}
static inline bool sym_IsExported(struct sSymbol const *sym)
static inline bool sym_IsExported(struct Symbol const *sym)
{
return sym->isExported;
}
@@ -83,33 +104,49 @@ static inline bool sym_IsExported(struct sSymbol const *sym)
/*
* Get a string equate's value
*/
static inline char *sym_GetStringValue(struct sSymbol const *sym)
static inline char const *sym_GetStringValue(struct Symbol const *sym)
{
return sym->pMacro;
if (sym->hasCallback)
return sym->strCallback();
return sym->macro;
}
void sym_ForEach(void (*func)(struct sSymbol *, void *), void *arg);
void sym_ForEach(void (*func)(struct Symbol *, void *), void *arg);
int32_t sym_GetValue(struct sSymbol const *sym);
int32_t sym_GetValue(struct Symbol const *sym);
void sym_SetExportAll(bool set);
struct sSymbol *sym_AddLocalReloc(char const *tzSym);
struct sSymbol *sym_AddReloc(char const *tzSym);
void sym_Export(char const *tzSym);
struct sSymbol *sym_FindMacro(char const *s);
struct sSymbol *sym_AddEqu(char const *tzSym, int32_t value);
struct sSymbol *sym_AddSet(char const *tzSym, int32_t value);
void sym_Init(void);
struct Symbol *sym_AddLocalLabel(char const *symName);
struct Symbol *sym_AddLabel(char const *symName);
struct Symbol *sym_AddAnonLabel(void);
void sym_WriteAnonLabelName(char buf[MIN_NB_ELMS(MAXSYMLEN + 1)], uint32_t ofs, bool neg);
void sym_Export(char const *symName);
struct Symbol *sym_AddEqu(char const *symName, int32_t value);
struct Symbol *sym_AddSet(char const *symName, int32_t value);
uint32_t sym_GetPCValue(void);
uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
uint32_t sym_GetConstantValue(char const *s);
struct sSymbol *sym_FindSymbol(char const *tzName);
char *sym_GetStringValue(struct sSymbol const *sym);
struct sSymbol *sym_AddMacro(char const *tzSym, int32_t nDefLineNo);
struct sSymbol *sym_Ref(char const *tzSym);
struct sSymbol *sym_AddString(char const *tzSym, char const *tzValue);
uint32_t sym_GetDefinedValue(char const *s);
void sym_Purge(char const *tzName);
/*
* Find a symbol by exact name, bypassing expansion checks
*/
struct Symbol *sym_FindExactSymbol(char const *name);
/*
* Find a symbol by exact name; may not be scoped, produces an error if it is
*/
struct Symbol *sym_FindUnscopedSymbol(char const *name);
/*
* Find a symbol, possibly scoped, by name
*/
struct Symbol *sym_FindScopedSymbol(char const *name);
struct Symbol const *sym_GetPC(void);
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
struct Symbol *sym_Ref(char const *symName);
struct Symbol *sym_AddString(char const *symName, char const *value);
struct Symbol *sym_RedefString(char const *symName, char const *value);
void sym_Purge(char const *symName);
void sym_Init(time_t now);
/* Functions to save and restore the current symbol scope. */
struct sSymbol *sym_GetCurrentSymbolScope(void);
void sym_SetCurrentSymbolScope(struct sSymbol *pNewScope);
char const *sym_GetCurrentSymbolScope(void);
void sym_SetCurrentSymbolScope(char const *newScope);
#endif /* RGBDS_SYMBOL_H */
+5 -1
View File
@@ -12,6 +12,10 @@
#include <stdint.h>
uint32_t calchash(const char *s);
int32_t readUTF8Char(char *dest, char *src);
char const *print(int c);
/*
* @return The number of bytes read, or 0 if invalid data was found
*/
size_t readUTF8Char(uint8_t *dest, char const *src);
#endif /* RGBDS_UTIL_H */
+19 -14
View File
@@ -14,17 +14,22 @@
extern unsigned int nbErrors;
enum WarningID {
WARNING_ASSERT,
WARNING_BUILTIN_ARG,
WARNING_DIV,
WARNING_EMPTY_ENTRY,
WARNING_LARGE_CONSTANT,
WARNING_LONG_STR,
WARNING_OBSOLETE,
WARNING_SHIFT,
WARNING_SHIFT_AMOUNT,
WARNING_TRUNCATION,
WARNING_USER,
WARNING_ASSERT, /* Assertions */
WARNING_BUILTIN_ARG, /* Invalid args to builtins */
WARNING_CHARMAP_REDEF, /* Charmap entry re-definition */
WARNING_DIV, /* Division undefined behavior */
WARNING_EMPTY_DATA_DIRECTIVE, /* `db`, `dw` or `dl` directive without data in ROM */
WARNING_EMPTY_MACRO_ARG, /* Empty macro argument */
WARNING_EMPTY_STRRPL, /* Empty second argument in `STRRPL` */
WARNING_LARGE_CONSTANT, /* Constants too large */
WARNING_LONG_STR, /* String too long for internal buffers */
WARNING_MACRO_SHIFT, /* Shift past available arguments in macro */
WARNING_NESTED_COMMENT, /* Comment-start delimiter in a block comment */
WARNING_OBSOLETE, /* Obsolete things */
WARNING_SHIFT, /* Shifting undefined behavior */
WARNING_SHIFT_AMOUNT, /* Strange shift amount */
WARNING_TRUNCATION, /* Implicit truncation loses some bits */
WARNING_USER, /* User warnings */
NB_WARNINGS,
@@ -43,7 +48,7 @@ void processWarningFlag(char const *flag);
* Used to warn the user about problems that don't prevent the generation of
* valid code.
*/
void warning(enum WarningID id, const char *fmt, ...);
void warning(enum WarningID id, const char *fmt, ...) format_(printf, 2, 3);
/*
* Used for errors that compromise the whole assembly process by affecting the
@@ -52,7 +57,7 @@ void warning(enum WarningID id, const char *fmt, ...);
* It is also used when the assembler goes into an invalid state (for example,
* when it fails to allocate memory).
*/
noreturn_ void fatalerror(const char *fmt, ...);
_Noreturn void fatalerror(const char *fmt, ...) format_(printf, 1, 2);
/*
* Used for errors that make it impossible to assemble correctly, but don't
@@ -60,6 +65,6 @@ noreturn_ void fatalerror(const char *fmt, ...);
* get a list of all errors at the end, making it easier to fix all of them at
* once.
*/
void yyerror(const char *fmt, ...);
void error(const char *fmt, ...) format_(printf, 1, 2);
#endif
+4 -4
View File
@@ -34,10 +34,10 @@ void vwarn(const char *fmt, va_list ap) format_(printf, 1, 0);
void warnx(const char *fmt, ...) format_(printf, 1, 2);
void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0);
noreturn_ void err(int status, const char *fmt, ...) format_(printf, 2, 3);
noreturn_ void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
noreturn_ void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
noreturn_ void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
_Noreturn void err(int status, const char *fmt, ...) format_(printf, 2, 3);
_Noreturn void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
_Noreturn void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
_Noreturn void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
#endif /* ERR_IN_LIBC */
+5 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2005-2019 Rich Felker, et al.
* Copyright © 2005-2020 Rich Felker, et al.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -23,11 +23,11 @@
/* This implementation was taken from musl and modified for RGBDS */
#ifndef _GETOPT_H
#define _GETOPT_H
#ifndef RGBDS_EXTERN_GETOPT_H
#define RGBDS_EXTERN_GETOPT_H
extern char *optarg;
extern int optind, opterr, optopt, optreset;
extern char *musl_optarg;
extern int musl_optind, musl_opterr, musl_optopt, musl_optreset;
struct option {
const char *name;
+1 -1
View File
@@ -9,6 +9,6 @@
#ifndef EXTERN_UTF8DECODER_H
#define EXTERN_UTF8DECODER_H
uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte);
uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte);
#endif /* EXTERN_UTF8DECODER_H */
+1 -1
View File
@@ -83,7 +83,7 @@ struct Mapfile {
int size;
};
int depth, colors;
extern int depth, colors;
#include "gfx/makepng.h"
#include "gfx/gb.h"
+12 -1
View File
@@ -11,10 +11,11 @@
#define RGBDS_LINK_HASHMAP_H
#include <assert.h>
#include <stdbool.h>
#define HASH_NB_BITS 32
#define HALF_HASH_NB_BITS 16
_Static_assert(HALF_HASH_NB_BITS * 2 == HASH_NB_BITS, "");
static_assert(HALF_HASH_NB_BITS * 2 == HASH_NB_BITS, "");
#define HASHMAP_NB_BUCKETS (1 << HALF_HASH_NB_BITS)
/* HashMapEntry is internal, please do not attempt to use it */
@@ -32,6 +33,16 @@ typedef struct HashMapEntry *HashMap[HASHMAP_NB_BUCKETS];
*/
bool hash_AddElement(HashMap map, char const *key, void *element);
/**
* Replaces an element with an already-present key in a hashmap.
* @warning Inserting a NULL will make `hash_GetElement`'s return ambiguous!
* @param map The HashMap to replace the element in
* @param key The key with which the element will be stored and retrieved
* @param element The element to replace
* @return True if the element was found and replaced
*/
bool hash_ReplaceElement(HashMap const map, char const *key, void *element);
/**
* Removes an element from a hashmap.
* @param map The HashMap to remove the element from
+69 -12
View File
@@ -1,7 +1,7 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2014-2018, RGBDS contributors.
* Copyright (c) 2014-2020, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
@@ -9,25 +9,82 @@
#ifndef HELPERS_H
#define HELPERS_H
#ifdef __GNUC__
/* GCC or compatible */
// Of course, MSVC does not support C11, so no _Noreturn there...
#ifdef _MSC_VER
#define _Noreturn __declspec(noreturn)
#endif
// Ideally, we'd use `__has_attribute` and `__has_builtin`, but these were only introduced in GCC 9
#ifdef __GNUC__ // GCC or compatible
#define format_(archetype, str_index, first_arg) \
__attribute__ ((format (archetype, str_index, first_arg)))
#define noreturn_ __attribute__ ((noreturn))
#define trap_ __builtin_trap()
// In release builds, define "unreachable" as such, but trap in debug builds
#ifdef NDEBUG
#define unreachable_ __builtin_unreachable
#else
#define unreachable_ __builtin_trap
#endif
#else
/* Unsupported, but no need to throw a fit */
// Unsupported, but no need to throw a fit
#define format_(archetype, str_index, first_arg)
#define noreturn_
#define unused_
#define trap_
// This seems to generate similar code to __builtin_unreachable, despite different semantics
// Note that executing this is undefined behavior (declared _Noreturn, but does return)
static inline _Noreturn unreachable_(void) {}
#endif
#ifndef DEVELOP
#define DEVELOP 0
// Use builtins whenever possible, and shim them otherwise
#ifdef __GNUC__ // GCC or compatible
#define ctz __builtin_ctz
#define clz __builtin_clz
#elif defined(_MSC_VER)
#include <assert.h>
#include <intrin.h>
#pragma intrinsic(_BitScanReverse, _BitScanForward)
static inline int ctz(unsigned int x)
{
unsigned long cnt;
assert(x != 0);
_BitScanForward(&cnt, x);
return cnt;
}
static inline int clz(unsigned int x)
{
unsigned long cnt;
assert(x != 0);
_BitScanReverse(&cnt, x);
return 31 - cnt;
}
#else
// FIXME: these are rarely used, and need testing...
#include <limits.h>
static inline int ctz(unsigned int x)
{
int cnt = 0;
while (!(x & 1)) {
x >>= 1;
cnt++;
}
return cnt;
}
static inline int clz(unsigned int x)
{
int cnt = 0;
while (x <= UINT_MAX / 2) {
x <<= 1;
cnt++;
}
return cnt;
}
#endif
/* Macros for stringification */
// Macros for stringification
#define STR(x) #x
#define EXPAND_AND_STR(x) STR(x)
+39 -2
View File
@@ -14,9 +14,11 @@
#include <stdbool.h>
#include <stdio.h>
#include "helpers.h"
/* Variables related to CLI options */
extern bool isDmgMode;
extern char const *linkerScriptName;
extern char *linkerScriptName;
extern char const *mapFileName;
extern char const *symFileName;
extern char const *overlayFileName;
@@ -25,6 +27,26 @@ extern uint8_t padValue;
extern bool is32kMode;
extern bool beVerbose;
extern bool isWRA0Mode;
extern bool disablePadding;
struct FileStackNode {
struct FileStackNode *parent;
/* Line at which the parent context was exited; meaningless for the root level */
uint32_t lineNo;
enum {
NODE_REPT,
NODE_FILE,
NODE_MACRO,
} type;
union {
char *name; /* NODE_FILE, NODE_MACRO */
struct { /* NODE_REPT */
uint32_t reptDepth;
uint32_t *iters;
};
};
};
/* Helper macro for printing verbose-mode messages */
#define verbosePrint(...) do { \
@@ -32,13 +54,28 @@ extern bool isWRA0Mode;
fprintf(stderr, __VA_ARGS__); \
} while (0)
/**
* Dump a file stack to stderr
* @param node The leaf node to dump the context of
*/
char const *dumpFileStack(struct FileStackNode const *node);
void warning(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4);
void error(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4);
_Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo,
char const *fmt, ...) format_(printf, 3, 4);
/**
* Opens a file if specified, and aborts on error.
* @param fileName The name of the file to open; if NULL, no file will be opened
* @param mode The mode to open the file with
* @return A pointer to a valid FILE structure, or NULL if fileName was NULL
*/
FILE * openFile(char const *fileName, char const *mode);
FILE *openFile(char const *fileName, char const *mode);
#define closeFile(file) do { \
FILE *tmp = file; \
+8 -1
View File
@@ -14,8 +14,9 @@
/**
* Read an object (.o) file, and add its info to the data structures.
* @param fileName A path to the object file to be read
* @param i The ID of the file
*/
void obj_ReadFile(char const *fileName);
void obj_ReadFile(char const *fileName, unsigned int i);
/**
* Perform validation on the object files' contents
@@ -27,6 +28,12 @@ void obj_DoSanityChecks(void);
*/
void obj_CheckAssertions(void);
/**
* Sets up object file reading
* @param nbFiles The number of object files that will be read
*/
void obj_Setup(unsigned int nbFiles);
/**
* `free`s all object memory that was allocated.
*/
+1 -2
View File
@@ -20,13 +20,12 @@
struct Assertion {
struct Patch patch;
// enum AssertionType type; The `patch`'s field is instead re-used
struct Section *section;
char *message;
/*
* This would be redundant with `.section->fileSymbols`... but
* `section` is sometimes NULL!
*/
struct Symbol ** fileSymbols;
struct Symbol **fileSymbols;
struct Assertion *next;
};
+14 -4
View File
@@ -19,31 +19,41 @@
#include "linkdefs.h"
struct FileStackNode;
struct Section;
struct AttachedSymbol {
struct Symbol *symbol;
struct AttachedSymbol *next;
};
struct Patch {
char *fileName;
int32_t offset;
struct FileStackNode const *src;
uint32_t lineNo;
uint32_t offset;
uint32_t pcSectionID;
uint32_t pcOffset;
enum PatchType type;
int32_t rpnSize;
uint32_t rpnSize;
uint8_t *rpnExpression;
struct Section const *pcSection;
};
struct Section {
/* Info contained in the object files */
char *name;
uint16_t size;
uint16_t offset;
enum SectionType type;
bool isUnion;
enum SectionModifier modifier;
bool isAddressFixed;
uint16_t org;
bool isBankFixed;
uint32_t bank;
bool isAlignFixed;
uint16_t alignMask;
uint16_t alignOfs;
uint8_t *data; /* Array of size `size`*/
uint32_t nbPatches;
struct Patch *patches;
+3 -1
View File
@@ -16,12 +16,14 @@
#include "linkdefs.h"
struct FileStackNode;
struct Symbol {
/* Info contained in the object files */
char *name;
enum ExportLevel type;
char const *objFileName;
char *fileName;
struct FileStackNode const *src;
int32_t lineNo;
int32_t sectionID;
union {
+12 -3
View File
@@ -12,9 +12,9 @@
#include <stdbool.h>
#include <stdint.h>
#define RGBDS_OBJECT_VERSION_STRING "RGB%1hhu"
#define RGBDS_OBJECT_VERSION_NUMBER (uint8_t)9
#define RGBDS_OBJECT_REV 3
#define RGBDS_OBJECT_VERSION_STRING "RGB%1u"
#define RGBDS_OBJECT_VERSION_NUMBER 9U
#define RGBDS_OBJECT_REV 7U
enum AssertionType {
ASSERT_WARN,
@@ -29,6 +29,7 @@ enum RPNCommand {
RPN_DIV = 0x03,
RPN_MOD = 0x04,
RPN_UNSUB = 0x05,
RPN_EXP = 0x06,
RPN_OR = 0x10,
RPN_AND = 0x11,
@@ -73,6 +74,14 @@ enum SectionType {
SECTTYPE_INVALID
};
enum SectionModifier {
SECTION_NORMAL,
SECTION_UNION,
SECTION_FRAGMENT
};
extern char const * const sectionModNames[];
/**
* Tells whether a section has data in its object file definition,
* depending on type.
+20
View File
@@ -0,0 +1,20 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2021, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#ifndef RGBDS_OP_MATH_H
#define RGBDS_OP_MATH_H
#include <stdint.h>
int32_t op_divide(int32_t dividend, int32_t divisor);
int32_t op_modulo(int32_t dividend, int32_t divisor);
int32_t op_exponent(int32_t base, uint32_t power);
int32_t op_shift_left(int32_t value, int32_t amount);
int32_t op_shift_right(int32_t value, int32_t amount);
#endif /* RGBDS_OP_MATH_H */
+73
View File
@@ -0,0 +1,73 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020 RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/* platform-specific hacks */
#ifndef RGBDS_PLATFORM_H
#define RGBDS_PLATFORM_H
/* MSVC doesn't have strncasecmp, use a suitable replacement */
#ifdef _MSC_VER
# include <string.h>
# define strncasecmp _strnicmp
#else
# include <strings.h>
#endif
/* MSVC has deprecated strdup in favor of _strdup */
#ifdef _MSC_VER
# define strdup _strdup
#endif
/* MSVC prefixes the names of S_* macros with underscores,
and doesn't define any S_IS* macros. Define them ourselves */
#ifdef _MSC_VER
# define S_IFMT _S_IFMT
# define S_IFDIR _S_IFDIR
# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
#endif
/* MSVC doesn't use POSIX types or defines for `read` */
#ifdef _MSC_VER
# include <io.h>
# define STDIN_FILENO 0
# define STDOUT_FILENO 1
# define STDERR_FILENO 2
# define ssize_t int
# define SSIZE_MAX INT_MAX
#else
# include <fcntl.h>
# include <unistd.h>
#endif
/* MSVC doesn't support `[static N]` for array arguments from C99 */
#ifdef _MSC_VER
# define MIN_NB_ELMS(N)
#else
# define MIN_NB_ELMS(N) static (N)
#endif
// MSVC uses a different name for O_RDWR, and needs an additional _O_BINARY flag
#ifdef _MSC_VER
# include <fcntl.h>
# define O_RDWR _O_RDWR
# define S_ISREG(field) ((field) & _S_IFREG)
# define O_BINARY _O_BINARY
#elif !defined(O_BINARY) // Cross-compilers define O_BINARY
# define O_BINARY 0 // POSIX says we shouldn't care!
#endif // _MSC_VER
// Windows has stdin and stdout open as text by default, which we may not want
#if defined(_MSC_VER) || defined(__MINGW32__)
# include <io.h>
# define setmode(fd, mode) _setmode(fd, mode)
#else
# define setmode(fd, mode) ((void)0)
#endif
#endif /* RGBDS_PLATFORM_H */
+5 -4
View File
@@ -1,7 +1,7 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2017-2018, Antonio Nino Diaz and RGBDS contributors.
* Copyright (c) 2017-2021, Antonio Nino Diaz and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
@@ -9,9 +9,10 @@
#ifndef EXTERN_VERSION_H
#define EXTERN_VERSION_H
#define PACKAGE_VERSION_MAJOR (0)
#define PACKAGE_VERSION_MINOR (4)
#define PACKAGE_VERSION_PATCH (0)
#define PACKAGE_VERSION_MAJOR 0
#define PACKAGE_VERSION_MINOR 5
#define PACKAGE_VERSION_PATCH 0
#define PACKAGE_VERSION_RC 2
const char *get_package_version_string(void);
+128
View File
@@ -0,0 +1,128 @@
#
# This file is part of RGBDS.
#
# Copyright (c) 2020 RGBDS contributors.
#
# SPDX-License-Identifier: MIT
#
set(common_src
"extern/err.c"
"extern/getopt.c"
"version.c"
)
find_package(PkgConfig)
if(MSVC OR NOT PKG_CONFIG_FOUND)
# fallback to find_package
find_package(PNG REQUIRED)
else()
pkg_check_modules(LIBPNG REQUIRED libpng)
endif()
find_package(BISON REQUIRED)
set(BISON_FLAGS "-Wall")
# Set sompe optimization flags on versions that support them
if(BISON_VERSION VERSION_GREATER_EQUAL "3.5")
set(BISON_FLAGS "${BISON_FLAGS} -Dapi.token.raw=true")
endif()
if(BISON_VERSION VERSION_GREATER_EQUAL "3.6")
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=detailed")
elseif(BISON_VERSION VERSION_GREATER_EQUAL "3.0")
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=verbose")
endif()
if(BISON_VERSION VERSION_GREATER_EQUAL "3.0")
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.lac=full")
set(BISON_FLAGS "${BISON_FLAGS} -Dlr.type=ielr")
endif()
BISON_TARGET(PARSER "asm/parser.y"
"${PROJECT_SOURCE_DIR}/src/asm/parser.c"
COMPILE_FLAGS "${BISON_FLAGS}"
DEFINES_FILE "${PROJECT_SOURCE_DIR}/src/asm/parser.h"
)
set(rgbasm_src
"${BISON_PARSER_OUTPUT_SOURCE}"
"asm/charmap.c"
"asm/fixpoint.c"
"asm/format.c"
"asm/fstack.c"
"asm/lexer.c"
"asm/macro.c"
"asm/main.c"
"asm/opt.c"
"asm/output.c"
"asm/rpn.c"
"asm/section.c"
"asm/symbol.c"
"asm/util.c"
"asm/warning.c"
"extern/utf8decoder.c"
"hashmap.c"
"linkdefs.c"
"opmath.c"
)
set(rgbfix_src
"fix/main.c"
)
set(rgbgfx_src
"gfx/gb.c"
"gfx/main.c"
"gfx/makepng.c"
)
set(rgblink_src
"link/assign.c"
"link/main.c"
"link/object.c"
"link/output.c"
"link/patch.c"
"link/script.c"
"link/section.c"
"link/symbol.c"
"hashmap.c"
"linkdefs.c"
"opmath.c"
)
foreach(PROG "asm" "fix" "gfx" "link")
add_executable(rgb${PROG}
${rgb${PROG}_src}
${common_src}
)
install(TARGETS rgb${PROG} RUNTIME DESTINATION bin)
endforeach()
set(MANDIR "share/man")
set(man1 "asm/rgbasm.1"
"fix/rgbfix.1"
"gfx/rgbgfx.1"
"link/rgblink.1")
set(man5 "asm/rgbasm.5"
"link/rgblink.5"
"rgbds.5")
set(man7 "gbz80.7"
"rgbds.7")
foreach(SECTION "man1" "man5" "man7")
set(DEST "${MANDIR}/${SECTION}")
install(FILES ${${SECTION}} DESTINATION ${DEST})
endforeach()
if(LIBPNG_FOUND) # pkg-config
target_include_directories(rgbgfx PRIVATE ${LIBPNG_INCLUDE_DIRS})
target_link_directories(rgbgfx PRIVATE ${LIBPNG_LIBRARY_DIRS})
target_link_libraries(rgbgfx PRIVATE ${LIBPNG_LIBRARIES})
else()
target_compile_definitions(rgbgfx PRIVATE ${PNG_DEFINITIONS})
target_include_directories(rgbgfx PRIVATE ${PNG_INCLUDE_DIRS})
target_link_libraries(rgbgfx PRIVATE ${PNG_LIBRARIES})
endif()
include(CheckLibraryExists)
check_library_exists("m" "sin" "" HAS_LIBM)
if(HAS_LIBM)
target_link_libraries(rgbasm PRIVATE "m")
endif()
+2 -2
View File
@@ -1,2 +1,2 @@
asmy.c
asmy.h
/parser.c
/parser.h
-1983
View File
File diff suppressed because it is too large Load Diff
+128 -123
View File
@@ -13,7 +13,6 @@
#include <stdio.h>
#include <string.h>
#include "asm/asm.h"
#include "asm/charmap.h"
#include "asm/main.h"
#include "asm/output.h"
@@ -22,18 +21,36 @@
#include "hashmap.h"
#define CHARMAP_HASH_SIZE (1 << 9)
/*
* Charmaps are stored using a structure known as "trie".
* Essentially a tree, where each nodes stores a single character's worth of info:
* whether there exists a mapping that ends at the current character,
*/
struct Charnode {
bool isTerminal; /* Whether there exists a mapping that ends here */
uint8_t value; /* If the above is true, its corresponding value */
/* This MUST be indexes and not pointers, because pointers get invalidated by `realloc`!! */
size_t next[255]; /* Indexes of where to go next, 0 = nowhere */
};
#define INITIAL_CAPACITY 32
struct Charmap {
char *name;
size_t usedNodes; /* How many nodes are being used */
size_t capacity; /* How many nodes have been allocated */
struct Charnode nodes[]; /* first node is reserved for the root node */
};
static HashMap charmaps;
static struct Charmap *currentCharmap;
struct CharmapStackEntry {
struct Charmap *charmap;
struct CharmapStackEntry *next;
};
static HashMap charmaps;
static struct Charmap *mainCharmap;
static struct Charmap *currentCharmap;
struct CharmapStackEntry *charmapStack;
static inline struct Charmap *charmap_Get(const char *name)
@@ -41,16 +58,21 @@ static inline struct Charmap *charmap_Get(const char *name)
return hash_GetElement(charmaps, name);
}
static void CopyNode(struct Charmap *dest,
const struct Charmap *src,
int nodeIdx)
static inline struct Charmap *resizeCharmap(struct Charmap *map, size_t capacity)
{
dest->nodes[nodeIdx].code = src->nodes[nodeIdx].code;
dest->nodes[nodeIdx].isCode = src->nodes[nodeIdx].isCode;
for (int i = 0; i < 256; i++)
if (src->nodes[nodeIdx].next[i])
dest->nodes[nodeIdx].next[i] = dest->nodes +
(src->nodes[nodeIdx].next[i] - src->nodes);
struct Charmap *new = realloc(map, sizeof(*map) + sizeof(*map->nodes) * capacity);
if (!new)
fatalerror("Failed to %s charmap: %s\n",
map ? "create" : "resize", strerror(errno));
new->capacity = capacity;
return new;
}
static inline void initNode(struct Charnode *node)
{
node->isTerminal = false;
memset(node->next, 0, sizeof(node->next));
}
struct Charmap *charmap_New(const char *name, const char *baseName)
@@ -61,33 +83,28 @@ struct Charmap *charmap_New(const char *name, const char *baseName)
base = charmap_Get(baseName);
if (base == NULL)
yyerror("Base charmap '%s' doesn't exist", baseName);
error("Base charmap '%s' doesn't exist\n", baseName);
}
struct Charmap *charmap = charmap_Get(name);
if (charmap != NULL) {
yyerror("Charmap '%s' already exists", name);
return NULL;
if (charmap) {
error("Charmap '%s' already exists\n", name);
return charmap;
}
charmap = malloc(sizeof(*charmap));
if (charmap == NULL)
fatalerror("Failed to create charmap: %s", strerror(errno));
/* Init the new charmap's fields */
snprintf(charmap->name, sizeof(charmap->name), "%s", name);
if (base != NULL) {
charmap->charCount = base->charCount;
charmap->nodeCount = base->nodeCount;
if (base) {
charmap = resizeCharmap(NULL, base->capacity);
charmap->usedNodes = base->usedNodes;
for (int i = 0; i < MAXCHARNODES; i++)
CopyNode(charmap, base, i);
memcpy(charmap->nodes, base->nodes, sizeof(base->nodes[0]) * charmap->usedNodes);
} else {
charmap->charCount = 0;
charmap->nodeCount = 0;
memset(charmap->nodes, 0, sizeof(charmap->nodes));
charmap = resizeCharmap(NULL, INITIAL_CAPACITY);
charmap->usedNodes = 1;
initNode(&charmap->nodes[0]); /* Init the root node */
}
charmap->name = strdup(name);
hash_AddElement(charmaps, charmap->name, charmap);
currentCharmap = charmap;
@@ -95,12 +112,18 @@ struct Charmap *charmap_New(const char *name, const char *baseName)
return charmap;
}
void charmap_Delete(struct Charmap *charmap)
{
free(charmap->name);
free(charmap);
}
void charmap_Set(const char *name)
{
struct Charmap *charmap = charmap_Get(name);
if (charmap == NULL)
yyerror("Charmap '%s' doesn't exist", name);
error("Charmap '%s' doesn't exist\n", name);
else
currentCharmap = charmap;
}
@@ -109,9 +132,9 @@ void charmap_Push(void)
{
struct CharmapStackEntry *stackEntry;
stackEntry = malloc(sizeof(struct CharmapStackEntry));
stackEntry = malloc(sizeof(*stackEntry));
if (stackEntry == NULL)
fatalerror("No memory for charmap stack");
fatalerror("Failed to alloc charmap stack entry: %s\n", strerror(errno));
stackEntry->charmap = currentCharmap;
stackEntry->next = charmapStack;
@@ -121,8 +144,10 @@ void charmap_Push(void)
void charmap_Pop(void)
{
if (charmapStack == NULL)
fatalerror("No entries in the charmap stack");
if (charmapStack == NULL) {
error("No entries in the charmap stack\n");
return;
}
struct CharmapStackEntry *top = charmapStack;
@@ -131,111 +156,91 @@ void charmap_Pop(void)
free(top);
}
void charmap_InitMain(void)
void charmap_Add(char *mapping, uint8_t value)
{
mainCharmap = charmap_New("main", NULL);
}
struct Charnode *node = &currentCharmap->nodes[0];
int32_t charmap_Add(char *input, uint8_t output)
{
int32_t i;
uint8_t v;
for (uint8_t c; *mapping; mapping++) {
c = *mapping - 1;
struct Charmap *charmap = currentCharmap;
struct Charnode *curr_node, *temp_node;
if (charmap->charCount >= MAXCHARMAPS || strlen(input) > CHARMAPLENGTH)
return -1;
curr_node = &charmap->nodes[0];
for (i = 0; (v = (uint8_t)input[i]); i++) {
if (curr_node->next[v]) {
curr_node = curr_node->next[v];
if (node->next[c]) {
node = &currentCharmap->nodes[node->next[c]];
} else {
temp_node = &charmap->nodes[charmap->nodeCount + 1];
/* Register next available node */
node->next[c] = currentCharmap->usedNodes;
/* If no more nodes are available, get new ones */
if (currentCharmap->usedNodes == currentCharmap->capacity) {
currentCharmap->capacity *= 2;
currentCharmap = resizeCharmap(currentCharmap, currentCharmap->capacity);
hash_ReplaceElement(charmaps, currentCharmap->name, currentCharmap);
}
curr_node->next[v] = temp_node;
curr_node = temp_node;
++charmap->nodeCount;
/* Switch to and init new node */
node = &currentCharmap->nodes[currentCharmap->usedNodes++];
initNode(node);
}
}
/* prevent duplicated keys by accepting only first key-value pair. */
if (curr_node->isCode)
return charmap->charCount;
if (node->isTerminal)
warning(WARNING_CHARMAP_REDEF, "Overriding charmap mapping\n");
curr_node->code = output;
curr_node->isCode = 1;
return ++charmap->charCount;
node->isTerminal = true;
node->value = value;
}
int32_t charmap_Convert(char **input)
size_t charmap_Convert(char const *input, uint8_t *output)
{
struct Charmap *charmap = currentCharmap;
struct Charnode *charnode;
/*
* The goal is to match the longest mapping possible.
* For that, advance through the trie with each character read.
* If that would lead to a dead end, rewind characters until the last match, and output.
* If no match, read a UTF-8 codepoint and output that.
*/
size_t outputLen = 0;
struct Charnode const *node = &currentCharmap->nodes[0];
struct Charnode const *match = NULL;
size_t rewindDistance = 0;
char *output;
char outchar[8];
for (;;) {
/* We still want NULs to reach the `else` path, to give a chance to rewind */
uint8_t c = *input - 1;
int32_t i, match, length;
uint8_t v, foundCode;
if (*input && node->next[c]) {
input++; /* Consume that char */
rewindDistance++;
output = malloc(strlen(*input));
if (output == NULL)
fatalerror("Not enough memory for buffer");
node = &currentCharmap->nodes[node->next[c]];
if (node->isTerminal) {
match = node;
rewindDistance = 0; /* Rewind from after the match */
}
length = 0;
} else {
input -= rewindDistance; /* Rewind */
rewindDistance = 0;
node = &currentCharmap->nodes[0];
while (**input) {
charnode = &charmap->nodes[0];
if (match) { /* Arrived at a dead end with a match found */
*output++ = match->value;
outputLen++;
match = NULL; /* Reset match for next round */
/*
* Find the longest valid match which has been registered in
* charmap, possibly yielding multiple or no matches.
* The longest match is taken, meaning partial matches shorter
* than the longest one are ignored.
*/
for (i = match = 0; (v = (*input)[i]);) {
if (!charnode->next[v])
} else if (*input) { /* No match found */
size_t codepointLen = readUTF8Char(output, input);
if (codepointLen == 0) {
error("Input string is not valid UTF-8!\n");
break;
}
input += codepointLen; /* OK because UTF-8 has no NUL in multi-byte chars */
output += codepointLen;
outputLen += codepointLen;
}
if (!*input)
break;
charnode = charnode->next[v];
i++;
if (charnode->isCode) {
match = i;
foundCode = charnode->code;
}
}
if (match) {
output[length] = foundCode;
length++;
} else {
/*
* put a utf-8 character
* if failed to find a match.
*/
match = readUTF8Char(outchar, *input);
if (match) {
memcpy(output + length, *input, match);
} else {
output[length] = 0;
match = 1;
}
length += match;
}
*input += match;
}
*input = output;
return length;
return outputLen;
}
+170
View File
@@ -0,0 +1,170 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/*
* Fixed-point math routines
*/
#include <inttypes.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include "asm/fixpoint.h"
#include "asm/symbol.h"
#include "asm/warning.h"
#define fix2double(i) ((double)((i) / 65536.0))
#define double2fix(d) ((int32_t)round((d) * 65536.0))
// pi radians == 32768 fixed-point "degrees"
#define fdeg2rad(f) ((f) * (M_PI / 32768.0))
#define rad2fdeg(r) ((r) * (32768.0 / M_PI))
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/*
* Return the _PI symbol value
*/
int32_t fix_Callback_PI(void)
{
warning(WARNING_OBSOLETE, "`_PI` is deprecated; use 3.14159\n");
return double2fix(M_PI);
}
/*
* Print a fixed point value
*/
void fix_Print(int32_t i)
{
uint32_t u = i;
const char *sign = "";
if (i < 0) {
u = -u;
sign = "-";
}
printf("%s%" PRIu32 ".%05" PRIu32, sign, u >> 16,
((uint32_t)(fix2double(u) * 100000 + 0.5)) % 100000);
}
/*
* Calculate sine
*/
int32_t fix_Sin(int32_t i)
{
return double2fix(sin(fdeg2rad(fix2double(i))));
}
/*
* Calculate cosine
*/
int32_t fix_Cos(int32_t i)
{
return double2fix(cos(fdeg2rad(fix2double(i))));
}
/*
* Calculate tangent
*/
int32_t fix_Tan(int32_t i)
{
return double2fix(tan(fdeg2rad(fix2double(i))));
}
/*
* Calculate arcsine
*/
int32_t fix_ASin(int32_t i)
{
return double2fix(rad2fdeg(asin(fix2double(i))));
}
/*
* Calculate arccosine
*/
int32_t fix_ACos(int32_t i)
{
return double2fix(rad2fdeg(acos(fix2double(i))));
}
/*
* Calculate arctangent
*/
int32_t fix_ATan(int32_t i)
{
return double2fix(rad2fdeg(atan(fix2double(i))));
}
/*
* Calculate atan2
*/
int32_t fix_ATan2(int32_t i, int32_t j)
{
return double2fix(rad2fdeg(atan2(fix2double(i), fix2double(j))));
}
/*
* Multiplication
*/
int32_t fix_Mul(int32_t i, int32_t j)
{
return double2fix(fix2double(i) * fix2double(j));
}
/*
* Division
*/
int32_t fix_Div(int32_t i, int32_t j)
{
return double2fix(fix2double(i) / fix2double(j));
}
/*
* Power
*/
int32_t fix_Pow(int32_t i, int32_t j)
{
return double2fix(pow(fix2double(i), fix2double(j)));
}
/*
* Logarithm
*/
int32_t fix_Log(int32_t i, int32_t j)
{
return double2fix(log(fix2double(i)) / log(fix2double(j)));
}
/*
* Round
*/
int32_t fix_Round(int32_t i)
{
return double2fix(round(fix2double(i)));
}
/*
* Ceil
*/
int32_t fix_Ceil(int32_t i)
{
return double2fix(ceil(fix2double(i)));
}
/*
* Floor
*/
int32_t fix_Floor(int32_t i)
{
return double2fix(floor(fix2double(i)));
}
+299
View File
@@ -0,0 +1,299 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 2020, RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#include <inttypes.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/format.h"
#include "asm/warning.h"
struct FormatSpec fmt_NewSpec(void)
{
struct FormatSpec fmt = {0};
return fmt;
}
bool fmt_IsEmpty(struct FormatSpec const *fmt)
{
return !fmt->state;
}
bool fmt_IsValid(struct FormatSpec const *fmt)
{
return fmt->valid || fmt->state == FORMAT_DONE;
}
bool fmt_IsFinished(struct FormatSpec const *fmt)
{
return fmt->state >= FORMAT_DONE;
}
void fmt_UseCharacter(struct FormatSpec *fmt, int c)
{
if (fmt->state == FORMAT_INVALID)
return;
switch (c) {
/* sign */
case ' ':
case '+':
if (fmt->state > FORMAT_SIGN)
goto invalid;
fmt->state = FORMAT_PREFIX;
fmt->sign = c;
break;
/* prefix */
case '#':
if (fmt->state > FORMAT_PREFIX)
goto invalid;
fmt->state = FORMAT_ALIGN;
fmt->prefix = true;
break;
/* align */
case '-':
if (fmt->state > FORMAT_ALIGN)
goto invalid;
fmt->state = FORMAT_WIDTH;
fmt->alignLeft = true;
break;
/* pad and width */
case '0':
if (fmt->state < FORMAT_WIDTH)
fmt->padZero = true;
/* fallthrough */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (fmt->state < FORMAT_WIDTH) {
fmt->state = FORMAT_WIDTH;
fmt->width = c - '0';
} else if (fmt->state == FORMAT_WIDTH) {
fmt->width = fmt->width * 10 + (c - '0');
} else if (fmt->state == FORMAT_FRAC) {
fmt->fracWidth = fmt->fracWidth * 10 + (c - '0');
} else {
goto invalid;
}
break;
case '.':
if (fmt->state > FORMAT_WIDTH)
goto invalid;
fmt->state = FORMAT_FRAC;
fmt->hasFrac = true;
break;
/* type */
case 'd':
case 'u':
case 'X':
case 'x':
case 'b':
case 'o':
case 'f':
case 's':
if (fmt->state >= FORMAT_DONE)
goto invalid;
fmt->state = FORMAT_DONE;
fmt->valid = true;
fmt->type = c;
break;
default:
invalid:
fmt->state = FORMAT_INVALID;
fmt->valid = false;
}
}
void fmt_FinishCharacters(struct FormatSpec *fmt)
{
if (!fmt_IsValid(fmt))
fmt->state = FORMAT_INVALID;
}
void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, char const *value)
{
if (fmt->sign)
error("Formatting string with sign flag '%c'\n", fmt->sign);
if (fmt->prefix)
error("Formatting string with prefix flag '#'\n");
if (fmt->padZero)
error("Formatting string with padding flag '0'\n");
if (fmt->hasFrac)
error("Formatting string with fractional width\n");
if (fmt->type != 's')
error("Formatting string as type '%c'\n", fmt->type);
size_t len = strlen(value);
size_t totalLen = fmt->width > len ? fmt->width : len;
if (totalLen + 1 > bufLen) /* bufLen includes terminator */
error("Formatted string value too long\n");
size_t padLen = fmt->width > len ? fmt->width - len : 0;
if (fmt->alignLeft) {
strncpy(buf, value, len < bufLen ? len : bufLen);
for (size_t i = 0; i < totalLen && len + i < bufLen; i++)
buf[len + i] = ' ';
} else {
for (size_t i = 0; i < padLen && i < bufLen; i++)
buf[i] = ' ';
if (bufLen > padLen)
strncpy(buf + padLen, value, bufLen - padLen - 1);
}
buf[totalLen] = '\0';
}
void fmt_PrintNumber(char *buf, size_t bufLen, struct FormatSpec const *fmt, uint32_t value)
{
if (fmt->type != 'X' && fmt->type != 'x' && fmt->type != 'b' && fmt->type != 'o'
&& fmt->prefix)
error("Formatting type '%c' with prefix flag '#'\n", fmt->type);
if (fmt->type != 'f' && fmt->hasFrac)
error("Formatting type '%c' with fractional width\n", fmt->type);
if (fmt->type == 's')
error("Formatting number as type 's'\n");
char sign = fmt->sign; /* 0 or ' ' or '+' */
if (fmt->type == 'd' || fmt->type == 'f') {
int32_t v = value;
if (v < 0 && v != INT32_MIN) {
sign = '-';
value = -v;
}
}
char prefix = !fmt->prefix ? 0
: fmt->type == 'X' ? '$'
: fmt->type == 'x' ? '$'
: fmt->type == 'b' ? '%'
: fmt->type == 'o' ? '&'
: 0;
char valueBuf[262]; /* Max 5 digits + decimal + 255 fraction digits + terminator */
if (fmt->type == 'b') {
/* Special case for binary */
char *ptr = valueBuf;
do {
*ptr++ = (value & 1) + '0';
value >>= 1;
} while (value);
*ptr = '\0';
/* Reverse the digits */
size_t valueLen = ptr - valueBuf;
for (size_t i = 0, j = valueLen - 1; i < j; i++, j--) {
char c = valueBuf[i];
valueBuf[i] = valueBuf[j];
valueBuf[j] = c;
}
} else if (fmt->type == 'f') {
/* Special case for fixed-point */
/* Default fractional width (C's is 6 for "%f"; here 5 is enough) */
uint8_t fracWidth = fmt->hasFrac ? fmt->fracWidth : 5;
if (fracWidth) {
char spec[16]; /* Max "%" + 5-char PRIu32 + ".%0255.f" + terminator */
snprintf(spec, sizeof(spec), "%%" PRIu32 ".%%0%d.f", fracWidth);
snprintf(valueBuf, sizeof(valueBuf), spec, value >> 16,
(value % 65536) / 65536.0 * pow(10, fracWidth) + 0.5);
} else {
snprintf(valueBuf, sizeof(valueBuf), "%" PRIu32, value >> 16);
}
} else {
char const *spec = fmt->type == 'd' ? "%" PRId32
: fmt->type == 'u' ? "%" PRIu32
: fmt->type == 'X' ? "%" PRIX32
: fmt->type == 'x' ? "%" PRIx32
: fmt->type == 'o' ? "%" PRIo32
: "%" PRId32;
snprintf(valueBuf, sizeof(valueBuf), spec, value);
}
size_t len = strlen(valueBuf);
size_t numLen = len;
if (sign)
numLen++;
if (prefix)
numLen++;
size_t totalLen = fmt->width > numLen ? fmt->width : numLen;
if (totalLen + 1 > bufLen) /* bufLen includes terminator */
error("Formatted numeric value too long\n");
size_t padLen = fmt->width > numLen ? fmt->width - numLen : 0;
if (fmt->alignLeft) {
size_t pos = 0;
if (sign && pos < bufLen)
buf[pos++] = sign;
if (prefix && pos < bufLen)
buf[pos++] = prefix;
strcpy(buf + pos, valueBuf);
pos += len;
for (size_t i = 0; i < totalLen && pos + i < bufLen; i++)
buf[pos + i] = ' ';
} else {
size_t pos = 0;
if (fmt->padZero) {
/* sign, then prefix, then zero padding */
if (sign && pos < bufLen)
buf[pos++] = sign;
if (prefix && pos < bufLen)
buf[pos++] = prefix;
for (size_t i = 0; i < padLen && pos < bufLen; i++)
buf[pos++] = '0';
} else {
/* space padding, then sign, then prefix */
for (size_t i = 0; i < padLen && pos < bufLen; i++)
buf[pos++] = ' ';
if (sign && pos < bufLen)
buf[pos++] = sign;
if (prefix && pos < bufLen)
buf[pos++] = prefix;
}
if (bufLen > pos)
strcpy(buf + pos, valueBuf);
}
buf[totalLen] = '\0';
}
+472 -456
View File
File diff suppressed because it is too large Load Diff
-702
View File
@@ -1,702 +0,0 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/asm.h"
#include "asm/lexer.h"
#include "asm/macro.h"
#include "asm/main.h"
#include "asm/rpn.h"
#include "asm/section.h"
#include "asm/warning.h"
#include "helpers.h"
#include "asmy.h"
bool oDontExpandStrings;
int32_t nGBGfxID = -1;
int32_t nBinaryID = -1;
static int32_t gbgfx2bin(char ch)
{
int32_t i;
for (i = 0; i <= 3; i++) {
if (CurrentOptions.gbgfx[i] == ch)
return i;
}
return 0;
}
static int32_t binary2bin(char ch)
{
int32_t i;
for (i = 0; i <= 1; i++) {
if (CurrentOptions.binary[i] == ch)
return i;
}
return 0;
}
static int32_t char2bin(char ch)
{
if (ch >= 'a' && ch <= 'f')
return (ch - 'a' + 10);
if (ch >= 'A' && ch <= 'F')
return (ch - 'A' + 10);
if (ch >= '0' && ch <= '9')
return (ch - '0');
return 0;
}
typedef int32_t(*x2bin) (char ch);
static int32_t ascii2bin(char *s)
{
char *start = s;
uint32_t radix = 10;
uint32_t result = 0;
x2bin convertfunc = char2bin;
switch (*s) {
case '$':
radix = 16;
s++;
convertfunc = char2bin;
break;
case '&':
radix = 8;
s++;
convertfunc = char2bin;
break;
case '`':
radix = 4;
s++;
convertfunc = gbgfx2bin;
break;
case '%':
radix = 2;
s++;
convertfunc = binary2bin;
break;
default:
/* Handle below */
break;
}
const uint32_t max_q = UINT32_MAX / radix;
const uint32_t max_r = UINT32_MAX % radix;
if (*s == '\0') {
/*
* There are no digits after the radix prefix
* (or the string is empty, which shouldn't happen).
*/
yyerror("Invalid integer constant");
} else if (radix == 4) {
int32_t size = 0;
int32_t c;
while (*s != '\0') {
c = convertfunc(*s++);
result = result * 2 + ((c & 2) << 7) + (c & 1);
size++;
}
/*
* Extending a graphics constant longer than 8 pixels,
* the Game Boy tile width, produces a nonsensical result.
*/
if (size > 8) {
warning(WARNING_LARGE_CONSTANT, "Graphics constant '%s' is too long",
start);
}
} else {
bool overflow = false;
while (*s != '\0') {
int32_t digit = convertfunc(*s++);
if (result > max_q
|| (result == max_q && digit > max_r)) {
overflow = true;
}
result = result * radix + digit;
}
if (overflow)
warning(WARNING_LARGE_CONSTANT, "Integer constant '%s' is too large",
start);
}
return result;
}
uint32_t ParseFixedPoint(char *s, uint32_t size)
{
uint32_t i;
uint32_t dot = 0;
for (i = 0; i < size; i++) {
if (s[i] == '.') {
dot++;
if (dot == 2)
break;
}
}
yyskipbytes(i);
yylval.nConstValue = (int32_t)(atof(s) * 65536);
return 1;
}
uint32_t ParseNumber(char *s, uint32_t size)
{
char dest[256];
if (size > 255)
fatalerror("Number token too long");
strncpy(dest, s, size);
dest[size] = 0;
yylval.nConstValue = ascii2bin(dest);
yyskipbytes(size);
return 1;
}
/*
* If the symbol name ends before the end of the macro arg,
* return a pointer to the rest of the macro arg.
* Otherwise, return NULL.
*/
char const *AppendMacroArg(char whichArg, char *dest, size_t *destIndex)
{
char const *marg;
if (whichArg == '@')
marg = macro_GetUniqueIDStr();
else if (whichArg >= '1' && whichArg <= '9')
marg = macro_GetArg(whichArg - '0');
else
fatalerror("Invalid macro argument '\\%c' in symbol", whichArg);
if (!marg)
fatalerror("Macro argument '\\%c' not defined", whichArg);
char ch;
while ((ch = *marg) != 0) {
if ((ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z')
|| (ch >= '0' && ch <= '9')
|| ch == '_'
|| ch == '@'
|| ch == '#'
|| ch == '.') {
if (*destIndex >= MAXSYMLEN)
fatalerror("Symbol too long");
dest[*destIndex] = ch;
(*destIndex)++;
} else {
return marg;
}
marg++;
}
return NULL;
}
uint32_t ParseSymbol(char *src, uint32_t size)
{
char dest[MAXSYMLEN + 1];
size_t srcIndex = 0;
size_t destIndex = 0;
char const *rest = NULL;
while (srcIndex < size) {
char ch = src[srcIndex++];
if (ch == '\\') {
/*
* We don't check if srcIndex is still less than size,
* but that can only fail to be true when the
* following char is neither '@' nor a digit.
* In that case, AppendMacroArg() will catch the error.
*/
ch = src[srcIndex++];
rest = AppendMacroArg(ch, dest, &destIndex);
/* If the symbol's end was in the middle of the token */
if (rest)
break;
} else {
if (destIndex >= MAXSYMLEN)
fatalerror("Symbol too long");
dest[destIndex++] = ch;
}
}
dest[destIndex] = 0;
/* Tell the lexer we read all bytes that we did */
yyskipbytes(srcIndex);
/*
* If an escape's expansion left some chars after the symbol's end,
* such as the `::` in a `Backup\1` expanded to `BackupCamX::`,
* put those into the buffer.
* Note that this NEEDS to be done after the `yyskipbytes` above.
*/
if (rest)
yyunputstr(rest);
/* If the symbol is an EQUS, expand it */
if (!oDontExpandStrings) {
struct sSymbol const *sym = sym_FindSymbol(dest);
if (sym && sym->type == SYM_EQUS) {
char *s;
lex_BeginStringExpansion(dest);
/* Feed the symbol's contents into the buffer */
yyunputstr(s = sym_GetStringValue(sym));
/* Lines inserted this way shall not increase nLineNo */
while (*s) {
if (*s++ == '\n')
nLineNo--;
}
return 0;
}
}
strcpy(yylval.tzSym, dest);
return 1;
}
uint32_t PutMacroArg(char *src, uint32_t size)
{
char const *s;
yyskipbytes(size);
if ((size == 2 && src[1] >= '1' && src[1] <= '9')) {
s = macro_GetArg(src[1] - '0');
if (s != NULL)
yyunputstr(s);
else
yyerror("Macro argument '\\%c' not defined", src[1]);
} else {
yyerror("Invalid macro argument '\\%c'", src[1]);
}
return 0;
}
uint32_t PutUniqueID(char *src, uint32_t size)
{
(void)src;
char const *s;
yyskipbytes(size);
s = macro_GetUniqueIDStr();
if (s != NULL)
yyunputstr(s);
else
yyerror("Macro unique label string not defined");
return 0;
}
enum {
T_LEX_MACROARG = 3000,
T_LEX_MACROUNIQUE
};
const struct sLexInitString lexer_strings[] = {
{"adc", T_Z80_ADC},
{"add", T_Z80_ADD},
{"and", T_Z80_AND},
{"bit", T_Z80_BIT},
{"call", T_Z80_CALL},
{"ccf", T_Z80_CCF},
{"cpl", T_Z80_CPL},
{"cp", T_Z80_CP},
{"daa", T_Z80_DAA},
{"dec", T_Z80_DEC},
{"di", T_Z80_DI},
{"ei", T_Z80_EI},
{"halt", T_Z80_HALT},
{"inc", T_Z80_INC},
{"jp", T_Z80_JP},
{"jr", T_Z80_JR},
{"ld", T_Z80_LD},
{"ldi", T_Z80_LDI},
{"ldd", T_Z80_LDD},
{"ldio", T_Z80_LDIO},
{"ldh", T_Z80_LDIO},
{"nop", T_Z80_NOP},
{"or", T_Z80_OR},
{"pop", T_Z80_POP},
{"push", T_Z80_PUSH},
{"res", T_Z80_RES},
{"reti", T_Z80_RETI},
{"ret", T_Z80_RET},
{"rlca", T_Z80_RLCA},
{"rlc", T_Z80_RLC},
{"rla", T_Z80_RLA},
{"rl", T_Z80_RL},
{"rrc", T_Z80_RRC},
{"rrca", T_Z80_RRCA},
{"rra", T_Z80_RRA},
{"rr", T_Z80_RR},
{"rst", T_Z80_RST},
{"sbc", T_Z80_SBC},
{"scf", T_Z80_SCF},
{"set", T_POP_SET},
{"sla", T_Z80_SLA},
{"sra", T_Z80_SRA},
{"srl", T_Z80_SRL},
{"stop", T_Z80_STOP},
{"sub", T_Z80_SUB},
{"swap", T_Z80_SWAP},
{"xor", T_Z80_XOR},
{"nz", T_CC_NZ},
{"z", T_CC_Z},
{"nc", T_CC_NC},
/* Handled in list of registers */
/* { "c", T_TOKEN_C }, */
{"[bc]", T_MODE_BC_IND},
{"[de]", T_MODE_DE_IND},
{"[hl]", T_MODE_HL_IND},
{"[hl+]", T_MODE_HL_INDINC},
{"[hl-]", T_MODE_HL_INDDEC},
{"[hli]", T_MODE_HL_INDINC},
{"[hld]", T_MODE_HL_INDDEC},
{"af", T_MODE_AF},
{"bc", T_MODE_BC},
{"de", T_MODE_DE},
{"hl", T_MODE_HL},
{"sp", T_MODE_SP},
{"[c]", T_MODE_C_IND},
{"[$ff00+c]", T_MODE_C_IND},
{"[$ff00 + c]", T_MODE_C_IND},
{"a", T_TOKEN_A},
{"b", T_TOKEN_B},
{"c", T_TOKEN_C},
{"d", T_TOKEN_D},
{"e", T_TOKEN_E},
{"h", T_TOKEN_H},
{"l", T_TOKEN_L},
{"||", T_OP_LOGICOR},
{"&&", T_OP_LOGICAND},
{"==", T_OP_LOGICEQU},
{">", T_OP_LOGICGT},
{"<", T_OP_LOGICLT},
{">=", T_OP_LOGICGE},
{"<=", T_OP_LOGICLE},
{"!=", T_OP_LOGICNE},
{"!", T_OP_LOGICNOT},
{"|", T_OP_OR},
{"^", T_OP_XOR},
{"&", T_OP_AND},
{"<<", T_OP_SHL},
{">>", T_OP_SHR},
{"+", T_OP_ADD},
{"-", T_OP_SUB},
{"*", T_OP_MUL},
{"/", T_OP_DIV},
{"%", T_OP_MOD},
{"~", T_OP_NOT},
{"def", T_OP_DEF},
{"bank", T_OP_BANK},
{"align", T_OP_ALIGN},
{"round", T_OP_ROUND},
{"ceil", T_OP_CEIL},
{"floor", T_OP_FLOOR},
{"div", T_OP_FDIV},
{"mul", T_OP_FMUL},
{"sin", T_OP_SIN},
{"cos", T_OP_COS},
{"tan", T_OP_TAN},
{"asin", T_OP_ASIN},
{"acos", T_OP_ACOS},
{"atan", T_OP_ATAN},
{"atan2", T_OP_ATAN2},
{"high", T_OP_HIGH},
{"low", T_OP_LOW},
{"isconst", T_OP_ISCONST},
{"strcmp", T_OP_STRCMP},
{"strin", T_OP_STRIN},
{"strsub", T_OP_STRSUB},
{"strlen", T_OP_STRLEN},
{"strcat", T_OP_STRCAT},
{"strupr", T_OP_STRUPR},
{"strlwr", T_OP_STRLWR},
{"include", T_POP_INCLUDE},
{"printt", T_POP_PRINTT},
{"printi", T_POP_PRINTI},
{"printv", T_POP_PRINTV},
{"printf", T_POP_PRINTF},
{"export", T_POP_EXPORT},
{"xdef", T_POP_XDEF},
{"global", T_POP_GLOBAL},
{"ds", T_POP_DS},
{"db", T_POP_DB},
{"dw", T_POP_DW},
{"dl", T_POP_DL},
{"section", T_POP_SECTION},
{"purge", T_POP_PURGE},
{"rsreset", T_POP_RSRESET},
{"rsset", T_POP_RSSET},
{"incbin", T_POP_INCBIN},
{"charmap", T_POP_CHARMAP},
{"newcharmap", T_POP_NEWCHARMAP},
{"setcharmap", T_POP_SETCHARMAP},
{"pushc", T_POP_PUSHC},
{"popc", T_POP_POPC},
{"fail", T_POP_FAIL},
{"warn", T_POP_WARN},
{"fatal", T_POP_FATAL},
{"assert", T_POP_ASSERT},
{"static_assert", T_POP_STATIC_ASSERT},
{"macro", T_POP_MACRO},
/* Not needed but we have it here just to protect the name */
{"endm", T_POP_ENDM},
{"shift", T_POP_SHIFT},
{"rept", T_POP_REPT},
/* Not needed but we have it here just to protect the name */
{"endr", T_POP_ENDR},
{"load", T_POP_LOAD},
{"endl", T_POP_ENDL},
{"if", T_POP_IF},
{"else", T_POP_ELSE},
{"elif", T_POP_ELIF},
{"endc", T_POP_ENDC},
{"union", T_POP_UNION},
{"nextu", T_POP_NEXTU},
{"endu", T_POP_ENDU},
{"wram0", T_SECT_WRAM0},
{"vram", T_SECT_VRAM},
{"romx", T_SECT_ROMX},
{"rom0", T_SECT_ROM0},
{"hram", T_SECT_HRAM},
{"wramx", T_SECT_WRAMX},
{"sram", T_SECT_SRAM},
{"oam", T_SECT_OAM},
{"rb", T_POP_RB},
{"rw", T_POP_RW},
{"equ", T_POP_EQU},
{"equs", T_POP_EQUS},
/* Handled before in list of CPU instructions */
/* {"set", T_POP_SET}, */
{"=", T_POP_EQUAL},
{"pushs", T_POP_PUSHS},
{"pops", T_POP_POPS},
{"pusho", T_POP_PUSHO},
{"popo", T_POP_POPO},
{"opt", T_POP_OPT},
{NULL, 0}
};
const struct sLexFloat tNumberToken = {
ParseNumber,
T_NUMBER
};
const struct sLexFloat tFixedPointToken = {
ParseFixedPoint,
T_NUMBER
};
const struct sLexFloat tIDToken = {
ParseSymbol,
T_ID
};
const struct sLexFloat tMacroArgToken = {
PutMacroArg,
T_LEX_MACROARG
};
const struct sLexFloat tMacroUniqueToken = {
PutUniqueID,
T_LEX_MACROUNIQUE
};
void setup_lexer(void)
{
uint32_t id;
lex_Init();
lex_AddStrings(lexer_strings);
//Macro arguments
id = lex_FloatAlloc(&tMacroArgToken);
lex_FloatAddFirstRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '1', '9');
id = lex_FloatAlloc(&tMacroUniqueToken);
lex_FloatAddFirstRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@');
//Decimal constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '0', '9');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddRange(id, '0', '9');
//Binary constants
id = lex_FloatAlloc(&tNumberToken);
nBinaryID = id;
lex_FloatAddFirstRange(id, '%', '%');
lex_FloatAddSecondRange(id, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddSecondRange(id, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
lex_FloatAddRange(id, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddRange(id, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
//Octal constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '&', '&');
lex_FloatAddSecondRange(id, '0', '7');
lex_FloatAddRange(id, '0', '7');
//Gameboy gfx constants
id = lex_FloatAlloc(&tNumberToken);
nGBGfxID = id;
lex_FloatAddFirstRange(id, '`', '`');
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatAddSecondRange(id, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[0], CurrentOptions.gbgfx[0]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[1], CurrentOptions.gbgfx[1]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[2], CurrentOptions.gbgfx[2]);
lex_FloatAddRange(id, CurrentOptions.gbgfx[3], CurrentOptions.gbgfx[3]);
//Hex constants
id = lex_FloatAlloc(&tNumberToken);
lex_FloatAddFirstRange(id, '$', '$');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddSecondRange(id, 'A', 'F');
lex_FloatAddSecondRange(id, 'a', 'f');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, 'A', 'F');
lex_FloatAddRange(id, 'a', 'f');
//ID 's
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, 'a', 'z');
lex_FloatAddFirstRange(id, 'A', 'Z');
lex_FloatAddFirstRange(id, '_', '_');
lex_FloatAddSecondRange(id, 'a', 'z');
lex_FloatAddSecondRange(id, 'A', 'Z');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddSecondRange(id, '_', '_');
lex_FloatAddSecondRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@');
lex_FloatAddSecondRange(id, '#', '#');
lex_FloatAddRange(id, '.', '.');
lex_FloatAddRange(id, 'a', 'z');
lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, '_', '_');
lex_FloatAddRange(id, '\\', '\\');
lex_FloatAddRange(id, '@', '@');
lex_FloatAddRange(id, '#', '#');
//Local ID
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, '.', '.');
lex_FloatAddSecondRange(id, 'a', 'z');
lex_FloatAddSecondRange(id, 'A', 'Z');
lex_FloatAddSecondRange(id, '_', '_');
lex_FloatAddRange(id, 'a', 'z');
lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9');
lex_FloatAddRange(id, '_', '_');
lex_FloatAddRange(id, '\\', '\\');
lex_FloatAddRange(id, '@', '@');
lex_FloatAddRange(id, '#', '#');
// "@"
id = lex_FloatAlloc(&tIDToken);
lex_FloatAddFirstRange(id, '@', '@');
//Fixed point constants
id = lex_FloatAlloc(&tFixedPointToken);
lex_FloatAddFirstRange(id, '.', '.');
lex_FloatAddFirstRange(id, '0', '9');
lex_FloatAddSecondRange(id, '.', '.');
lex_FloatAddSecondRange(id, '0', '9');
lex_FloatAddRange(id, '.', '.');
lex_FloatAddRange(id, '0', '9');
}
+2576 -935
View File
File diff suppressed because it is too large Load Diff
+109 -18
View File
@@ -1,28 +1,44 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/asm.h"
#include "asm/macro.h"
#include "asm/warning.h"
#define MAXMACROARGS 99999
/*
* Your average macro invocation does not go past the tens, but some go further
* This ensures that sane and slightly insane invocations suffer no penalties,
* and the rest is insane and thus will assume responsibility.
* Additionally, ~300 bytes (on x64) of memory per level of nesting has been
* deemed reasonable. (Halve that on x86.)
*/
#define INITIAL_ARG_SIZE 32
struct MacroArgs {
char *args[MAXMACROARGS];
unsigned int nbArgs;
unsigned int shift;
unsigned int capacity;
char *args[];
};
static struct MacroArgs defaultArgs = { .nbArgs = 0, .shift = 0 };
static struct MacroArgs *macroArgs = &defaultArgs;
static uint32_t uniqueID = -1;
#define SIZEOF_ARGS(nbArgs) (sizeof(struct MacroArgs) + \
sizeof(((struct MacroArgs){0}).args[0]) * (nbArgs))
static struct MacroArgs *macroArgs = NULL;
static uint32_t uniqueID = 0;
static uint32_t maxUniqueID = 0;
/*
* The initialization is somewhat harmful, since it is never used, but it
* guarantees the size of the buffer will be correct. I was unable to find a
* better solution, but if you have one, please feel free!
*/
static char uniqueIDBuf[] = "_" EXPAND_AND_STR(UINT32_MAX);
static char uniqueIDBuf[] = "_u4294967295"; // UINT32_MAX
static char *uniqueIDPtr = NULL;
struct MacroArgs *macro_GetCurrentArgs(void)
@@ -32,19 +48,35 @@ struct MacroArgs *macro_GetCurrentArgs(void)
struct MacroArgs *macro_NewArgs(void)
{
struct MacroArgs *args = malloc(sizeof(*args));
struct MacroArgs *args = malloc(SIZEOF_ARGS(INITIAL_ARG_SIZE));
if (!args)
fatalerror("Unable to register macro arguments: %s\n", strerror(errno));
args->nbArgs = 0;
args->shift = 0;
args->capacity = INITIAL_ARG_SIZE;
return args;
}
void macro_AppendArg(struct MacroArgs *args, char *s)
void macro_AppendArg(struct MacroArgs **argPtr, char *s)
{
if (args->nbArgs == MAXMACROARGS)
yyerror("A maximum of " EXPAND_AND_STR(MAXMACROARGS)
" arguments is allowed");
args->args[args->nbArgs++] = s;
#define macArgs (*argPtr)
if (s[0] == '\0')
warning(WARNING_EMPTY_MACRO_ARG, "Empty macro argument\n");
if (macArgs->nbArgs == MAXMACROARGS)
error("A maximum of " EXPAND_AND_STR(MAXMACROARGS) " arguments is allowed\n");
if (macArgs->nbArgs >= macArgs->capacity) {
macArgs->capacity *= 2;
/* Check that overflow didn't roll us back */
if (macArgs->capacity <= macArgs->nbArgs)
fatalerror("Failed to add new macro argument: capacity overflow\n");
macArgs = realloc(macArgs, SIZEOF_ARGS(macArgs->capacity));
if (!macArgs)
fatalerror("Error adding new macro argument: %s\n", strerror(errno));
}
macArgs->args[macArgs->nbArgs++] = s;
#undef macArgs
}
void macro_UseNewArgs(struct MacroArgs *args)
@@ -60,9 +92,47 @@ void macro_FreeArgs(struct MacroArgs *args)
char const *macro_GetArg(uint32_t i)
{
if (!macroArgs)
return NULL;
uint32_t realIndex = i + macroArgs->shift - 1;
return realIndex >= MAXMACROARGS ? NULL : macroArgs->args[realIndex];
return realIndex >= macroArgs->nbArgs ? NULL
: macroArgs->args[realIndex];
}
char *macro_GetAllArgs(void)
{
if (!macroArgs)
return NULL;
if (macroArgs->shift >= macroArgs->nbArgs)
return "";
size_t len = 0;
for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++)
len += strlen(macroArgs->args[i]) + 1; /* 1 for comma */
char *str = malloc(len + 1); /* 1 for '\0' */
char *ptr = str;
if (!str)
fatalerror("Failed to allocate memory for expanding '\\#': %s\n", strerror(errno));
for (uint32_t i = macroArgs->shift; i < macroArgs->nbArgs; i++) {
size_t n = strlen(macroArgs->args[i]);
memcpy(ptr, macroArgs->args[i], n);
ptr += n;
/* Commas go between args and after a last empty arg */
if (i < macroArgs->nbArgs - 1 || n == 0)
*ptr++ = ','; /* no space after comma */
}
*ptr = '\0';
return str;
}
uint32_t macro_GetUniqueID(void)
@@ -78,19 +148,40 @@ char const *macro_GetUniqueIDStr(void)
void macro_SetUniqueID(uint32_t id)
{
uniqueID = id;
if (id == -1) {
if (id == 0) {
uniqueIDPtr = NULL;
} else {
if (uniqueID > maxUniqueID)
maxUniqueID = uniqueID;
/* The buffer is guaranteed to be the correct size */
sprintf(uniqueIDBuf, "_%u", id);
/* This is a valid label fragment, but not a valid numeric */
sprintf(uniqueIDBuf, "_u%" PRIu32, id);
uniqueIDPtr = uniqueIDBuf;
}
}
void macro_ShiftCurrentArgs(void)
uint32_t macro_UseNewUniqueID(void)
{
if (macroArgs->shift != macroArgs->nbArgs)
macroArgs->shift++;
macro_SetUniqueID(++maxUniqueID);
return maxUniqueID;
}
void macro_ShiftCurrentArgs(int32_t count)
{
if (!macroArgs) {
error("Cannot shift macro arguments outside of a macro\n");
} else if (count > 0 && ((uint32_t)count > macroArgs->nbArgs
|| macroArgs->shift > macroArgs->nbArgs - count)) {
warning(WARNING_MACRO_SHIFT,
"Cannot shift macro arguments past their end\n");
macroArgs->shift = macroArgs->nbArgs;
} else if (count < 0 && macroArgs->shift < (uint32_t)-count) {
warning(WARNING_MACRO_SHIFT,
"Cannot shift macro arguments past their beginning\n");
macroArgs->shift = 0;
} else {
macroArgs->shift += count;
}
}
uint32_t macro_NbArgs(void)
+151 -358
View File
@@ -6,6 +6,7 @@
* SPDX-License-Identifier: MIT
*/
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <inttypes.h>
@@ -17,13 +18,17 @@
#include <string.h>
#include <time.h>
#include "asm/symbol.h"
#include "asm/charmap.h"
#include "asm/format.h"
#include "asm/fstack.h"
#include "asm/lexer.h"
#include "asm/output.h"
#include "asm/main.h"
#include "asm/charmap.h"
#include "asm/opt.h"
#include "asm/output.h"
#include "asm/rpn.h"
#include "asm/symbol.h"
#include "asm/warning.h"
#include "parser.h"
#include "extern/err.h"
#include "extern/getopt.h"
@@ -31,21 +36,9 @@
#include "helpers.h"
#include "version.h"
extern int yyparse(void);
size_t cldefines_index;
size_t cldefines_numindices;
size_t cldefines_bufsize;
const size_t cldefine_entrysize = 2 * sizeof(void *);
char **cldefines;
clock_t nStartClock, nEndClock;
uint32_t nTotalLines, nIFDepth, nUnionDepth;
bool skipElif;
uint32_t unionStart[128], unionSize[128];
int32_t nLineNo;
uint32_t curOffset;
// Old Bison versions (confirmed for 2.3) do not forward-declare `yyparse` in the generated header
// Unfortunately, macOS still ships 2.3, which is from 2008...
int yyparse(void);
#if defined(YYDEBUG) && YYDEBUG
extern int yydebug;
@@ -57,196 +50,10 @@ bool oFailedOnMissingInclude;
bool oGeneratePhonyDeps;
char *tzTargetFileName;
/*
* Option stack
*/
struct sOptions DefaultOptions;
struct sOptions CurrentOptions;
struct sOptionStackEntry {
struct sOptions Options;
struct sOptionStackEntry *pNext;
};
struct sOptionStackEntry *pOptionStack;
void opt_SetCurrentOptions(struct sOptions *pOpt)
{
if (nGBGfxID != -1) {
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatDeleteRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatDeleteSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
}
if (nBinaryID != -1) {
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatDeleteRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatDeleteSecondRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
}
CurrentOptions = *pOpt;
if (nGBGfxID != -1) {
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatAddRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[0],
CurrentOptions.gbgfx[0]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[1],
CurrentOptions.gbgfx[1]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[2],
CurrentOptions.gbgfx[2]);
lex_FloatAddSecondRange(nGBGfxID, CurrentOptions.gbgfx[3],
CurrentOptions.gbgfx[3]);
}
if (nBinaryID != -1) {
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[0],
CurrentOptions.binary[0]);
lex_FloatAddSecondRange(nBinaryID, CurrentOptions.binary[1],
CurrentOptions.binary[1]);
}
}
void opt_Parse(char *s)
{
struct sOptions newopt;
newopt = CurrentOptions;
switch (s[0]) {
case 'g':
if (strlen(&s[1]) == 4) {
newopt.gbgfx[0] = s[1];
newopt.gbgfx[1] = s[2];
newopt.gbgfx[2] = s[3];
newopt.gbgfx[3] = s[4];
} else {
yyerror("Must specify exactly 4 characters for option 'g'");
}
break;
case 'b':
if (strlen(&s[1]) == 2) {
newopt.binary[0] = s[1];
newopt.binary[1] = s[2];
} else {
yyerror("Must specify exactly 2 characters for option 'b'");
}
break;
case 'z':
warning(WARNING_OBSOLETE, "Option 'z' is a deprecated alias for 'p'");
/* fallthrough */
case 'p':
if (strlen(&s[1]) <= 2) {
int32_t result;
unsigned int fillchar;
result = sscanf(&s[1], "%x", &fillchar);
if (result != EOF && result != 1)
yyerror("Invalid argument for option 'z'");
else
newopt.fillchar = fillchar;
} else {
yyerror("Invalid argument for option 'z'");
}
break;
default:
yyerror("Unknown option");
break;
}
opt_SetCurrentOptions(&newopt);
}
void opt_Push(void)
{
struct sOptionStackEntry *pOpt;
pOpt = malloc(sizeof(struct sOptionStackEntry));
if (pOpt == NULL)
fatalerror("No memory for option stack");
pOpt->Options = CurrentOptions;
pOpt->pNext = pOptionStack;
pOptionStack = pOpt;
}
void opt_Pop(void)
{
if (pOptionStack == NULL)
fatalerror("No entries in the option stack");
struct sOptionStackEntry *pOpt;
pOpt = pOptionStack;
opt_SetCurrentOptions(&(pOpt->Options));
pOptionStack = pOpt->pNext;
free(pOpt);
}
void opt_AddDefine(char *s)
{
char *value, *equals;
if (cldefines_index >= cldefines_numindices) {
/* Check for overflows */
if ((cldefines_numindices * 2) < cldefines_numindices)
fatalerror("No memory for command line defines");
if ((cldefines_bufsize * 2) < cldefines_bufsize)
fatalerror("No memory for command line defines");
cldefines_numindices *= 2;
cldefines_bufsize *= 2;
cldefines = realloc(cldefines, cldefines_bufsize);
if (!cldefines)
fatalerror("No memory for command line defines");
}
equals = strchr(s, '=');
if (equals) {
*equals = '\0';
value = equals + 1;
} else {
value = "1";
}
cldefines[cldefines_index++] = s;
cldefines[cldefines_index++] = value;
}
static void opt_ParseDefines(void)
{
uint32_t i;
for (i = 0; i < cldefines_index; i += 2)
sym_AddString(cldefines[i], cldefines[i + 1]);
}
bool haltnop;
bool optimizeloads;
bool verbose;
bool warnings; /* True to enable warnings, false to disable them. */
/* Escapes Make-special chars from a string */
static char *make_escape(const char *str)
@@ -269,7 +76,7 @@ static char *make_escape(const char *str)
}
/* Short options */
static char const *optstring = "b:D:Eg:hi:LM:o:p:r:VvW:w";
static const char *optstring = "b:D:Eg:hi:LM:o:p:r:VvW:w";
/* Variables for the long-only options */
static int depType; /* Variants of `-M` */
@@ -311,7 +118,7 @@ static void print_usage(void)
fputs(
"Usage: rgbasm [-EhLVvw] [-b chars] [-D name[=value]] [-g chars] [-i path]\n"
" [-M depend_file] [-MG] [-MP] [-MT target_file] [-MQ target_file]\n"
" [-o out_file] [-p pad_value] [-r depth] [-W warning] <file> ...\n"
" [-o out_file] [-p pad_value] [-r depth] [-W warning] <file>\n"
"Useful options:\n"
" -E, --export-all export all labels\n"
" -M, --dependfile <path> set the output dependency file\n"
@@ -320,7 +127,7 @@ static void print_usage(void)
" -V, --version print RGBASM version and exit\n"
" -W, --warning <warning> enable or disable warnings\n"
"\n"
"For help, use `man rgbasm' or go to https://rednex.github.io/rgbds/\n",
"For help, use `man rgbasm' or go to https://rgbds.gbdev.io/docs/\n",
stderr);
exit(1);
}
@@ -330,158 +137,173 @@ int main(int argc, char *argv[])
int ch;
char *ep;
struct sOptions newopt;
time_t now = time(NULL);
char const *sourceDateEpoch = getenv("SOURCE_DATE_EPOCH");
char *tzMainfile;
/*
* Support SOURCE_DATE_EPOCH for reproducible builds
* https://reproducible-builds.org/docs/source-date-epoch/
*/
if (sourceDateEpoch)
now = (time_t)strtoul(sourceDateEpoch, NULL, 0);
dependfile = NULL;
/* Initial number of allocated elements in array */
cldefines_numindices = 32;
cldefines_bufsize = cldefines_numindices * cldefine_entrysize;
cldefines = malloc(cldefines_bufsize);
if (!cldefines)
fatalerror("No memory for command line defines");
#if defined(YYDEBUG) && YYDEBUG
yydebug = 1;
#endif
nMaxRecursionDepth = 64;
// Perform some init for below
sym_Init(now);
// Set defaults
oGeneratePhonyDeps = false;
oGeneratedMissingIncludes = false;
oFailedOnMissingInclude = false;
tzTargetFileName = NULL;
opt_B("01");
opt_G("0123");
opt_P(0);
optimizeloads = true;
haltnop = true;
verbose = false;
warnings = true;
sym_SetExportAll(false);
uint32_t maxRecursionDepth = 64;
size_t nTargetFileNameLen = 0;
DefaultOptions.gbgfx[0] = '0';
DefaultOptions.gbgfx[1] = '1';
DefaultOptions.gbgfx[2] = '2';
DefaultOptions.gbgfx[3] = '3';
DefaultOptions.binary[0] = '0';
DefaultOptions.binary[1] = '1';
DefaultOptions.exportall = false;
DefaultOptions.fillchar = 0;
DefaultOptions.optimizeloads = true;
DefaultOptions.haltnop = true;
DefaultOptions.verbose = false;
DefaultOptions.warnings = true;
opt_SetCurrentOptions(&DefaultOptions);
newopt = CurrentOptions;
while ((ch = musl_getopt_long_only(argc, argv, optstring, longopts,
NULL)) != -1) {
while ((ch = musl_getopt_long_only(argc, argv, optstring, longopts, NULL)) != -1) {
switch (ch) {
case 'b':
if (strlen(optarg) == 2) {
newopt.binary[0] = optarg[1];
newopt.binary[1] = optarg[2];
} else {
if (strlen(musl_optarg) == 2)
opt_B(&musl_optarg[1]);
else
errx(1, "Must specify exactly 2 characters for option 'b'");
}
break;
char *equals;
case 'D':
opt_AddDefine(optarg);
break;
case 'E':
newopt.exportall = true;
break;
case 'g':
if (strlen(optarg) == 4) {
newopt.gbgfx[0] = optarg[1];
newopt.gbgfx[1] = optarg[2];
newopt.gbgfx[2] = optarg[3];
newopt.gbgfx[3] = optarg[4];
equals = strchr(musl_optarg, '=');
if (equals) {
*equals = '\0';
sym_AddString(musl_optarg, equals + 1);
} else {
errx(1, "Must specify exactly 4 characters for option 'g'");
sym_AddString(musl_optarg, "1");
}
break;
case 'E':
sym_SetExportAll(true);
break;
case 'g':
if (strlen(musl_optarg) == 4)
opt_G(&musl_optarg[1]);
else
errx(1, "Must specify exactly 4 characters for option 'g'");
break;
case 'h':
newopt.haltnop = false;
haltnop = false;
break;
case 'i':
fstk_AddIncludePath(optarg);
fstk_AddIncludePath(musl_optarg);
break;
case 'L':
newopt.optimizeloads = false;
optimizeloads = false;
break;
case 'M':
if (!strcmp("-", optarg))
if (!strcmp("-", musl_optarg))
dependfile = stdout;
else
dependfile = fopen(optarg, "w");
dependfile = fopen(musl_optarg, "w");
if (dependfile == NULL)
err(1, "Could not open dependfile %s",
optarg);
err(1, "Could not open dependfile %s", musl_optarg);
break;
case 'o':
out_SetFileName(optarg);
break;
case 'p':
newopt.fillchar = strtoul(optarg, &ep, 0);
if (optarg[0] == '\0' || *ep != '\0')
case 'o':
out_SetFileName(musl_optarg);
break;
unsigned long fill;
case 'p':
fill = strtoul(musl_optarg, &ep, 0);
if (musl_optarg[0] == '\0' || *ep != '\0')
errx(1, "Invalid argument for option 'p'");
if (newopt.fillchar < 0 || newopt.fillchar > 0xFF)
if (fill < 0 || fill > 0xFF)
errx(1, "Argument for option 'p' must be between 0 and 0xFF");
opt_P(fill);
break;
case 'r':
nMaxRecursionDepth = strtoul(optarg, &ep, 0);
if (optarg[0] == '\0' || *ep != '\0')
case 'r':
maxRecursionDepth = strtoul(musl_optarg, &ep, 0);
if (musl_optarg[0] == '\0' || *ep != '\0')
errx(1, "Invalid argument for option 'r'");
break;
case 'V':
printf("rgbasm %s\n", get_package_version_string());
exit(0);
case 'v':
newopt.verbose = true;
verbose = true;
break;
case 'W':
processWarningFlag(optarg);
processWarningFlag(musl_optarg);
break;
case 'w':
newopt.warnings = false;
warnings = false;
break;
/* Long-only options */
case 0:
if (depType) {
switch (depType) {
case 'G':
oGeneratedMissingIncludes = true;
break;
case 'P':
oGeneratePhonyDeps = true;
break;
case 'Q':
case 'T':
if (optind == argc)
errx(1, "-M%c takes a target file name argument",
depType);
ep = optarg;
if (depType == 'Q')
ep = make_escape(ep);
switch (depType) {
case 'G':
oGeneratedMissingIncludes = true;
break;
nTargetFileNameLen += strlen(ep) + 1;
tzTargetFileName =
realloc(tzTargetFileName,
nTargetFileNameLen + 1);
if (tzTargetFileName == NULL)
err(1, "Cannot append new file to target file list");
strcat(tzTargetFileName, ep);
if (depType == 'Q')
free(ep);
char *ptr = tzTargetFileName +
strlen(tzTargetFileName);
*ptr++ = ' ';
*ptr = '\0';
break;
case 'P':
oGeneratePhonyDeps = true;
break;
case 'Q':
case 'T':
if (musl_optind == argc)
errx(1, "-M%c takes a target file name argument", depType);
ep = musl_optarg;
if (depType == 'Q')
ep = make_escape(ep);
nTargetFileNameLen += strlen(ep) + 1;
if (!tzTargetFileName) {
/* On first alloc, make an empty str */
tzTargetFileName = malloc(nTargetFileNameLen + 1);
if (tzTargetFileName)
*tzTargetFileName = '\0';
} else {
tzTargetFileName = realloc(tzTargetFileName,
nTargetFileNameLen + 1);
}
if (tzTargetFileName == NULL)
err(1, "Cannot append new file to target file list");
strcat(tzTargetFileName, ep);
if (depType == 'Q')
free(ep);
char *ptr = tzTargetFileName + strlen(tzTargetFileName);
*ptr++ = ' ';
*ptr = '\0';
break;
}
break;
@@ -491,79 +313,50 @@ int main(int argc, char *argv[])
/* NOTREACHED */
}
}
argc -= optind;
argv += optind;
if (tzTargetFileName == NULL)
tzTargetFileName = tzObjectname;
opt_SetCurrentOptions(&newopt);
DefaultOptions = CurrentOptions;
if (argc == 0) {
fputs("FATAL: no input files\n", stderr);
if (argc == musl_optind) {
fputs("FATAL: No input files\n", stderr);
print_usage();
} else if (argc != musl_optind + 1) {
fputs("FATAL: More than one input file given\n", stderr);
print_usage();
}
tzMainfile = argv[argc - 1];
char const *mainFileName = argv[musl_optind];
setup_lexer();
if (CurrentOptions.verbose)
printf("Assembling %s\n", tzMainfile);
if (verbose)
printf("Assembling %s\n", mainFileName);
if (dependfile) {
if (!tzTargetFileName)
errx(1, "Dependency files can only be created if a target file is specified with either -o, -MQ or -MT.\n");
errx(1, "Dependency files can only be created if a target file is specified with either -o, -MQ or -MT\n");
fprintf(dependfile, "%s: %s\n", tzTargetFileName, tzMainfile);
fprintf(dependfile, "%s: %s\n", tzTargetFileName, mainFileName);
}
nStartClock = clock();
charmap_New("main", NULL);
nLineNo = 1;
nTotalLines = 0;
nIFDepth = 0;
skipElif = true;
nUnionDepth = 0;
sym_Init();
sym_SetExportAll(CurrentOptions.exportall);
fstk_Init(tzMainfile);
opt_ParseDefines();
charmap_InitMain();
// Init lexer and file stack, prodiving file info
lexer_Init();
fstk_Init(mainFileName, maxRecursionDepth);
yy_set_state(LEX_STATE_NORMAL);
opt_SetCurrentOptions(&DefaultOptions);
// Perform parse (yyparse is auto-generated from `parser.y`)
if (yyparse() != 0 && nbErrors == 0)
nbErrors = 1;
if (yyparse() != 0 || nbErrors != 0)
errx(1, "Assembly aborted (%u errors)!", nbErrors);
if (dependfile)
fclose(dependfile);
if (nIFDepth != 0)
errx(1, "Unterminated IF construct (%u levels)!", nIFDepth);
sect_CheckUnionClosed();
if (nUnionDepth != 0) {
errx(1, "Unterminated UNION construct (%u levels)!",
nUnionDepth);
}
double timespent;
nEndClock = clock();
timespent = ((double)(nEndClock - nStartClock))
/ (double)CLOCKS_PER_SEC;
if (CurrentOptions.verbose) {
printf("Success! %u lines in %d.%02d seconds ", nTotalLines,
(int)timespent, ((int)(timespent * 100.0)) % 100);
if (timespent < FLT_MIN_EXP)
printf("(INFINITY lines/minute)\n");
else
printf("(%d lines/minute)\n",
(int)(60 / timespent * nTotalLines));
}
if (nbErrors != 0)
errx(1, "Assembly aborted (%u error%s)!", nbErrors,
nbErrors == 1 ? "" : "s");
// If parse aborted due to missing an include, and `-MG` was given, exit normally
if (oFailedOnMissingInclude)
return 0;
-142
View File
@@ -1,142 +0,0 @@
/*
* This file is part of RGBDS.
*
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
*
* SPDX-License-Identifier: MIT
*/
/*
* Fixedpoint math routines
*/
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include "asm/mymath.h"
#include "asm/symbol.h"
#define fx2double(i) ((double)((i) / 65536.0))
#define double2fx(d) ((int32_t)((d) * 65536.0))
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
/*
* Define the _PI symbol
*/
void math_DefinePI(void)
{
sym_AddEqu("_PI", double2fx(M_PI));
}
/*
* Print a fixed point value
*/
void math_Print(int32_t i)
{
if (i >= 0)
printf("%d.%05d", i >> 16,
((int32_t)(fx2double(i) * 100000 + 0.5)) % 100000);
else
printf("-%d.%05d", (-i) >> 16,
((int32_t)(fx2double(-i) * 100000 + 0.5)) % 100000);
}
/*
* Calculate sine
*/
int32_t math_Sin(int32_t i)
{
return double2fx(sin(fx2double(i) * 2 * M_PI / 65536));
}
/*
* Calculate cosine
*/
int32_t math_Cos(int32_t i)
{
return double2fx(cos(fx2double(i) * 2 * M_PI / 65536));
}
/*
* Calculate tangent
*/
int32_t math_Tan(int32_t i)
{
return double2fx(tan(fx2double(i) * 2 * M_PI / 65536));
}
/*
* Calculate arcsine
*/
int32_t math_ASin(int32_t i)
{
return double2fx(asin(fx2double(i)) / 2 / M_PI * 65536);
}
/*
* Calculate arccosine
*/
int32_t math_ACos(int32_t i)
{
return double2fx(acos(fx2double(i)) / 2 / M_PI * 65536);
}
/*
* Calculate arctangent
*/
int32_t math_ATan(int32_t i)
{
return double2fx(atan(fx2double(i)) / 2 / M_PI * 65536);
}
/*
* Calculate atan2
*/
int32_t math_ATan2(int32_t i, int32_t j)
{
return double2fx(atan2(fx2double(i), fx2double(j)) / 2 / M_PI * 65536);
}
/*
* Multiplication
*/
int32_t math_Mul(int32_t i, int32_t j)
{
return double2fx(fx2double(i) * fx2double(j));
}
/*
* Division
*/
int32_t math_Div(int32_t i, int32_t j)
{
return double2fx(fx2double(i) / fx2double(j));
}
/*
* Round
*/
int32_t math_Round(int32_t i)
{
return double2fx(round(fx2double(i)));
}
/*
* Ceil
*/
int32_t math_Ceil(int32_t i)
{
return double2fx(ceil(fx2double(i)));
}
/*
* Floor
*/
int32_t math_Floor(int32_t i)
{
return double2fx(floor(fx2double(i)));
}
+111
View File
@@ -0,0 +1,111 @@
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/lexer.h"
#include "asm/section.h"
#include "asm/warning.h"
struct OptStackEntry {
char binary[2];
char gbgfx[4];
int32_t fillByte;
struct OptStackEntry *next;
};
static struct OptStackEntry *stack = NULL;
void opt_B(char chars[2])
{
lexer_SetBinDigits(chars);
}
void opt_G(char chars[4])
{
lexer_SetGfxDigits(chars);
}
void opt_P(uint8_t fill)
{
fillByte = fill;
}
void opt_Parse(char *s)
{
switch (s[0]) {
case 'b':
if (strlen(&s[1]) == 2)
opt_B(&s[1]);
else
error("Must specify exactly 2 characters for option 'b'\n");
break;
case 'g':
if (strlen(&s[1]) == 4)
opt_G(&s[1]);
else
error("Must specify exactly 4 characters for option 'g'\n");
break;
case 'p':
if (strlen(&s[1]) <= 2) {
int result;
unsigned int fillchar;
result = sscanf(&s[1], "%x", &fillchar);
if (result != EOF && result != 1)
error("Invalid argument for option 'p'\n");
else
opt_P(fillchar);
} else {
error("Invalid argument for option 'p'\n");
}
break;
default:
error("Unknown option '%c'\n", s[0]);
break;
}
}
void opt_Push(void)
{
struct OptStackEntry *entry = malloc(sizeof(*entry));
if (entry == NULL)
fatalerror("Failed to alloc option stack entry: %s\n", strerror(errno));
// Both of these pulled from lexer.h
entry->binary[0] = binDigits[0];
entry->binary[1] = binDigits[1];
entry->gbgfx[0] = gfxDigits[0];
entry->gbgfx[1] = gfxDigits[1];
entry->gbgfx[2] = gfxDigits[2];
entry->gbgfx[3] = gfxDigits[3];
entry->fillByte = fillByte; // Pulled from section.h
entry->next = stack;
stack = entry;
}
void opt_Pop(void)
{
if (stack == NULL) {
error("No entries in the option stack\n");
return;
}
struct OptStackEntry *entry = stack;
opt_B(entry->binary);
opt_G(entry->gbgfx);
opt_P(entry->fillByte);
stack = entry->next;
free(entry);
}
+248 -140
View File
@@ -12,12 +12,12 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "asm/asm.h"
#include "asm/charmap.h"
#include "asm/fstack.h"
#include "asm/main.h"
@@ -30,14 +30,18 @@
#include "extern/err.h"
#include "linkdefs.h"
#include "platform.h" // strdup
struct Patch {
char tzFilename[_MAX_PATH + 1];
struct FileStackNode const *src;
uint32_t lineNo;
uint32_t nOffset;
uint8_t nType;
struct Section *pcSection;
uint32_t pcOffset;
uint8_t type;
uint32_t nRPNSize;
uint8_t *pRPN;
struct Patch *pNext;
struct Patch *next;
};
struct Assertion {
@@ -53,25 +57,23 @@ char *tzObjectname;
struct Section *pSectionList, *pCurrentSection;
/* Linked list of symbols to put in the object file */
static struct sSymbol *objectSymbols = NULL;
static struct sSymbol **objectSymbolsTail = &objectSymbols;
static struct Symbol *objectSymbols = NULL;
static struct Symbol **objectSymbolsTail = &objectSymbols;
static uint32_t nbSymbols = 0; /* Length of the above list */
static struct Assertion *assertions = NULL;
static struct FileStackNode *fileStackNodes = NULL;
/*
* Count the number of sections used in this object
*/
static uint32_t countsections(void)
static uint32_t countSections(void)
{
struct Section *pSect;
uint32_t count = 0;
pSect = pSectionList;
while (pSect) {
for (struct Section const *sect = pSectionList; sect; sect = sect->next)
count++;
pSect = pSect->pNext;
}
return count;
}
@@ -79,16 +81,13 @@ static uint32_t countsections(void)
/*
* Count the number of patches used in this object
*/
static uint32_t countpatches(struct Section *pSect)
static uint32_t countPatches(struct Section const *sect)
{
struct Patch *pPatch;
uint32_t r = 0;
pPatch = pSect->pPatches;
while (pPatch) {
for (struct Patch const *patch = sect->patches; patch != NULL;
patch = patch->next)
r++;
pPatch = pPatch->pNext;
}
return r;
}
@@ -96,7 +95,7 @@ static uint32_t countpatches(struct Section *pSect)
/**
* Count the number of assertions used in this object
*/
static uint32_t countasserts(void)
static uint32_t countAsserts(void)
{
struct Assertion *assert = assertions;
uint32_t count = 0;
@@ -111,114 +110,176 @@ static uint32_t countasserts(void)
/*
* Write a long to a file (little-endian)
*/
static void fputlong(uint32_t i, FILE *f)
static void putlong(uint32_t i, FILE *f)
{
fputc(i, f);
fputc(i >> 8, f);
fputc(i >> 16, f);
fputc(i >> 24, f);
putc(i, f);
putc(i >> 8, f);
putc(i >> 16, f);
putc(i >> 24, f);
}
/*
* Write a NULL-terminated string to a file
*/
static void fputstring(char const *s, FILE *f)
static void putstring(char const *s, FILE *f)
{
while (*s)
fputc(*s++, f);
fputc(0, f);
putc(*s++, f);
putc(0, f);
}
static uint32_t getNbFileStackNodes(void)
{
return fileStackNodes ? fileStackNodes->ID + 1 : 0;
}
void out_RegisterNode(struct FileStackNode *node)
{
/* If node is not already registered, register it (and parents), and give it a unique ID */
while (node->ID == (uint32_t)-1) {
node->ID = getNbFileStackNodes();
if (node->ID == (uint32_t)-1)
fatalerror("Reached too many file stack nodes; try splitting the file up\n");
node->next = fileStackNodes;
fileStackNodes = node;
/* Also register the node's parents */
node = node->parent;
if (!node)
break;
}
}
void out_ReplaceNode(struct FileStackNode *node)
{
(void)node;
#if 0
This is code intended to replace a node, which is pretty useless until ref counting is added...
struct FileStackNode **ptr = &fileStackNodes;
/*
* The linked list is supposed to have decrementing IDs, so iterate with less memory reads,
* to hopefully hit the cache less. A debug check is added after, in case a change is made
* that breaks this assumption.
*/
for (uint32_t i = fileStackNodes->ID; i != node->ID; i--)
ptr = &(*ptr)->next;
assert((*ptr)->ID == node->ID);
node->next = (*ptr)->next;
assert(!node->next || node->next->ID == node->ID - 1); /* Catch inconsistencies early */
/* TODO: unreference the node */
*ptr = node;
#endif
}
/*
* Return a section's ID
*/
static uint32_t getsectid(struct Section *pSect)
static uint32_t getsectid(struct Section const *sect)
{
struct Section *sec;
struct Section const *sec = pSectionList;
uint32_t ID = 0;
sec = pSectionList;
while (sec) {
if (sec == pSect)
if (sec == sect)
return ID;
ID++;
sec = sec->pNext;
sec = sec->next;
}
fatalerror("Unknown section '%s'", pSect->pzName);
fatalerror("Unknown section '%s'\n", sect->name);
}
static uint32_t getSectIDIfAny(struct Section const *sect)
{
return sect ? getsectid(sect) : -1;
}
/*
* Write a patch to a file
*/
static void writepatch(struct Patch *pPatch, FILE *f)
static void writepatch(struct Patch const *patch, FILE *f)
{
fputstring(pPatch->tzFilename, f);
fputlong(pPatch->nOffset, f);
fputc(pPatch->nType, f);
fputlong(pPatch->nRPNSize, f);
fwrite(pPatch->pRPN, 1, pPatch->nRPNSize, f);
assert(patch->src->ID != -1);
putlong(patch->src->ID, f);
putlong(patch->lineNo, f);
putlong(patch->nOffset, f);
putlong(getSectIDIfAny(patch->pcSection), f);
putlong(patch->pcOffset, f);
putc(patch->type, f);
putlong(patch->nRPNSize, f);
fwrite(patch->pRPN, 1, patch->nRPNSize, f);
}
/*
* Write a section to a file
*/
static void writesection(struct Section *pSect, FILE *f)
static void writesection(struct Section const *sect, FILE *f)
{
fputstring(pSect->pzName, f);
putstring(sect->name, f);
fputlong(pSect->size, f);
putlong(sect->size, f);
fputc(pSect->nType | pSect->isUnion << 7, f);
bool isUnion = sect->modifier == SECTION_UNION;
bool isFragment = sect->modifier == SECTION_FRAGMENT;
fputlong(pSect->nOrg, f);
fputlong(pSect->nBank, f);
fputlong(pSect->nAlign, f);
putc(sect->type | isUnion << 7 | isFragment << 6, f);
if (sect_HasData(pSect->nType)) {
struct Patch *pPatch;
putlong(sect->org, f);
putlong(sect->bank, f);
putc(sect->align, f);
putlong(sect->alignOfs, f);
fwrite(pSect->tData, 1, pSect->size, f);
fputlong(countpatches(pSect), f);
if (sect_HasData(sect->type)) {
fwrite(sect->data, 1, sect->size, f);
putlong(countPatches(sect), f);
pPatch = pSect->pPatches;
while (pPatch) {
writepatch(pPatch, f);
pPatch = pPatch->pNext;
}
for (struct Patch const *patch = sect->patches; patch != NULL;
patch = patch->next)
writepatch(patch, f);
}
}
/*
* Write a symbol to a file
*/
static void writesymbol(struct sSymbol const *pSym, FILE *f)
static void writesymbol(struct Symbol const *sym, FILE *f)
{
fputstring(pSym->tzName, f);
if (!sym_IsDefined(pSym)) {
fputc(SYMTYPE_IMPORT, f);
putstring(sym->name, f);
if (!sym_IsDefined(sym)) {
putc(SYMTYPE_IMPORT, f);
} else {
fputc(pSym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
fputstring(pSym->tzFileName, f);
fputlong(pSym->nFileLine, f);
fputlong(pSym->pSection ? getsectid(pSym->pSection) : -1, f);
fputlong(pSym->nValue, f);
assert(sym->src->ID != -1);
putc(sym->isExported ? SYMTYPE_EXPORT : SYMTYPE_LOCAL, f);
putlong(sym->src->ID, f);
putlong(sym->fileLine, f);
putlong(getSectIDIfAny(sym_GetSection(sym)), f);
putlong(sym->value, f);
}
}
static void registerSymbol(struct Symbol *sym)
{
*objectSymbolsTail = sym;
objectSymbolsTail = &sym->next;
out_RegisterNode(sym->src);
if (nbSymbols == (uint32_t)-1)
fatalerror("Registered too many symbols (%" PRIu32
"); try splitting up your files\n", (uint32_t)-1);
sym->ID = nbSymbols++;
}
/*
* Returns a symbol's ID within the object file
* If the symbol does not have one, one is assigned by registering the symbol
*/
static uint32_t getSymbolID(struct sSymbol *sym)
static uint32_t getSymbolID(struct Symbol *sym)
{
if (sym->ID == -1) {
sym->ID = nbSymbols++;
*objectSymbolsTail = sym;
objectSymbolsTail = &sym->next;
}
if (sym->ID == (uint32_t)-1 && !sym_IsPC(sym))
registerSymbol(sym);
return sym->ID;
}
@@ -233,6 +294,11 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
uint8_t rpndata = popbyte();
switch (rpndata) {
struct Symbol *sym;
uint32_t value;
uint8_t b;
size_t i;
case RPN_CONST:
writebyte(RPN_CONST);
writebyte(popbyte());
@@ -240,13 +306,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
writebyte(popbyte());
writebyte(popbyte());
break;
case RPN_SYM:
{
for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
;
struct sSymbol *sym = sym_FindSymbol(tzSym);
uint32_t value;
case RPN_SYM:
i = 0;
do {
tzSym[i] = popbyte();
} while (tzSym[i++]);
// The symbol name is always written expanded
sym = sym_FindExactSymbol(tzSym);
if (sym_IsConstant(sym)) {
writebyte(RPN_CONST);
value = sym_GetConstantValue(tzSym);
@@ -254,18 +322,22 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
writebyte(RPN_SYM);
value = getSymbolID(sym);
}
writebyte(value & 0xFF);
writebyte(value >> 8);
writebyte(value >> 16);
writebyte(value >> 24);
break;
}
case RPN_BANK_SYM:
{
for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
;
struct sSymbol *sym = sym_FindSymbol(tzSym);
uint32_t value = getSymbolID(sym);
i = 0;
do {
tzSym[i] = popbyte();
} while (tzSym[i++]);
// The symbol name is always written expanded
sym = sym_FindExactSymbol(tzSym);
value = getSymbolID(sym);
writebyte(RPN_BANK_SYM);
writebyte(value & 0xFF);
@@ -273,18 +345,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
writebyte(value >> 16);
writebyte(value >> 24);
break;
}
case RPN_BANK_SECT:
{
uint8_t b;
case RPN_BANK_SECT:
writebyte(RPN_BANK_SECT);
do {
b = popbyte();
writebyte(b);
} while (b != 0);
break;
}
default:
writebyte(rpndata);
break;
@@ -296,42 +365,61 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
/*
* Allocate a new patch structure and link it into the list
* WARNING: all patches are assumed to eventually be written, so the file stack node is registered
*/
static struct Patch *allocpatch(uint32_t type, struct Expression const *expr,
uint32_t ofs)
static struct Patch *allocpatch(uint32_t type, struct Expression const *expr, uint32_t ofs)
{
struct Patch *pPatch;
struct Patch *patch = malloc(sizeof(struct Patch));
uint32_t rpnSize = expr->isKnown ? 5 : expr->nRPNPatchSize;
struct FileStackNode *node = fstk_GetFileStack();
pPatch = malloc(sizeof(struct Patch));
if (!patch)
fatalerror("No memory for patch: %s\n", strerror(errno));
if (!pPatch)
fatalerror("No memory for patch: %s", strerror(errno));
pPatch->pRPN = malloc(sizeof(*pPatch->pRPN) * expr->nRPNPatchSize);
patch->pRPN = malloc(sizeof(*patch->pRPN) * rpnSize);
if (!patch->pRPN)
fatalerror("No memory for patch's RPN expression: %s\n", strerror(errno));
if (!pPatch->pRPN)
fatalerror("No memory for patch's RPN expression: %s",
strerror(errno));
patch->type = type;
patch->src = node;
out_RegisterNode(node);
patch->lineNo = lexer_GetLineNo();
patch->nOffset = ofs;
patch->pcSection = sect_GetSymbolSection();
patch->pcOffset = sect_GetSymbolOffset();
pPatch->nRPNSize = 0;
pPatch->nType = type;
fstk_DumpToStr(pPatch->tzFilename, sizeof(pPatch->tzFilename));
pPatch->nOffset = ofs;
/* If the expression's value is known, output a constant RPN expression directly */
if (expr->isKnown) {
patch->nRPNSize = rpnSize;
/* Make sure to update `rpnSize` above if modifying this! */
patch->pRPN[0] = RPN_CONST;
patch->pRPN[1] = (uint32_t)(expr->nVal) & 0xFF;
patch->pRPN[2] = (uint32_t)(expr->nVal) >> 8;
patch->pRPN[3] = (uint32_t)(expr->nVal) >> 16;
patch->pRPN[4] = (uint32_t)(expr->nVal) >> 24;
} else {
patch->nRPNSize = 0;
writerpn(patch->pRPN, &patch->nRPNSize, expr->tRPN, expr->nRPNLength);
}
assert(patch->nRPNSize == rpnSize);
writerpn(pPatch->pRPN, &pPatch->nRPNSize, expr->tRPN, expr->nRPNLength);
assert(pPatch->nRPNSize == expr->nRPNPatchSize);
return pPatch;
return patch;
}
/*
* Create a new patch (includes the rpn expr)
*/
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs)
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift)
{
struct Patch *pPatch = allocpatch(type, expr, ofs);
struct Patch *patch = allocpatch(type, expr, ofs);
pPatch->pNext = pCurrentSection->pPatches;
pCurrentSection->pPatches = pPatch;
// If the patch had a quantity of bytes output before it,
// PC is not at the patch's location, but at the location
// before those bytes.
patch->pcOffset -= pcShift;
patch->next = pCurrentSection->patches;
pCurrentSection->patches = patch;
}
/**
@@ -346,7 +434,6 @@ bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
return false;
assertion->patch = allocpatch(type, expr, ofs);
assertion->section = pCurrentSection;
assertion->message = strdup(message);
if (!assertion->message) {
free(assertion);
@@ -362,17 +449,33 @@ bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
static void writeassert(struct Assertion *assert, FILE *f)
{
writepatch(assert->patch, f);
fputlong(assert->section ? getsectid(assert->section) : -1, f);
fputstring(assert->message, f);
putstring(assert->message, f);
}
static void registerExportedSymbol(struct sSymbol *symbol, void *arg)
static void writeFileStackNode(struct FileStackNode const *node, FILE *f)
{
(void)arg;
if (symbol->isExported && symbol->ID == -1) {
*objectSymbolsTail = symbol;
objectSymbolsTail = &symbol->next;
nbSymbols++;
putlong(node->parent ? node->parent->ID : -1, f);
putlong(node->lineNo, f);
putc(node->type, f);
if (node->type != NODE_REPT) {
putstring(((struct FileStackNamedNode const *)node)->name, f);
} else {
struct FileStackReptNode const *reptNode = (struct FileStackReptNode const *)node;
putlong(reptNode->reptDepth, f);
/* Iters are stored by decreasing depth, so reverse the order for output */
for (uint32_t i = reptNode->reptDepth; i--; )
putlong(reptNode->iters[i], f);
}
}
static void registerUnregisteredSymbol(struct Symbol *symbol, void *arg)
{
(void)arg; // sym_ForEach requires a void* parameter, but we are not using it.
// Check for symbol->src, to skip any built-in symbol from rgbasm
if (symbol->src && symbol->ID == (uint32_t)-1) {
registerSymbol(symbol);
}
}
@@ -382,37 +485,42 @@ static void registerExportedSymbol(struct sSymbol *symbol, void *arg)
void out_WriteObject(void)
{
FILE *f;
struct Section *pSect;
struct Assertion *assert = assertions;
if (strcmp(tzObjectname, "-") != 0)
f = fopen(tzObjectname, "wb");
else
f = fdopen(1, "wb");
f = fopen(tzObjectname, "wb");
if (!f)
err(1, "Couldn't write file '%s'", tzObjectname);
/* Also write exported symbols that weren't written above */
sym_ForEach(registerExportedSymbol, NULL);
/* Also write symbols that weren't written above */
sym_ForEach(registerUnregisteredSymbol, NULL);
fprintf(f, RGBDS_OBJECT_VERSION_STRING, RGBDS_OBJECT_VERSION_NUMBER);
fputlong(RGBDS_OBJECT_REV, f);
putlong(RGBDS_OBJECT_REV, f);
fputlong(nbSymbols, f);
fputlong(countsections(), f);
putlong(nbSymbols, f);
putlong(countSections(), f);
for (struct sSymbol const *sym = objectSymbols; sym; sym = sym->next) {
putlong(getNbFileStackNodes(), f);
for (struct FileStackNode const *node = fileStackNodes; node; node = node->next) {
writeFileStackNode(node, f);
if (node->next && node->next->ID != node->ID - 1)
fatalerror("Internal error: fstack node #%" PRIu32 " follows #%" PRIu32
". Please report this to the developers!\n",
node->next->ID, node->ID);
}
for (struct Symbol const *sym = objectSymbols; sym; sym = sym->next)
writesymbol(sym, f);
}
pSect = pSectionList;
while (pSect) {
writesection(pSect, f);
pSect = pSect->pNext;
}
for (struct Section *sect = pSectionList; sect; sect = sect->next)
writesection(sect, f);
fputlong(countasserts(), f);
while (assert) {
putlong(countAsserts(), f);
for (struct Assertion *assert = assertions; assert;
assert = assert->next)
writeassert(assert, f);
assert = assert->next;
}
fclose(f);
}
@@ -423,6 +531,6 @@ void out_WriteObject(void)
void out_SetFileName(char *s)
{
tzObjectname = s;
if (CurrentOptions.verbose)
if (verbose)
printf("Output filename %s\n", s);
}
+2223
View File
File diff suppressed because it is too large Load Diff
+67 -18
View File
@@ -1,11 +1,11 @@
.\"
.\" This file is part of RGBDS.
.\"
.\" Copyright (c) 2010-2019, Anthony J. Bentley and RGBDS contributors.
.\" Copyright (c) 2010-2021, Anthony J. Bentley and RGBDS contributors.
.\"
.\" SPDX-License-Identifier: MIT
.\"
.Dd July 8, 2019
.Dd March 28, 2021
.Dt RGBASM 1
.Os
.Sh NAME
@@ -19,6 +19,10 @@
.Op Fl g Ar chars
.Op Fl i Ar path
.Op Fl M Ar depend_file
.Op Fl MG
.Op Fl MP
.Op Fl MT Ar target_file
.Op Fl MQ Ar target_file
.Op Fl o Ar out_file
.Op Fl p Ar pad_value
.Op Fl r Ar recursion_depth
@@ -79,13 +83,48 @@ Add an include path.
Disable the optimization that turns loads of the form
.Ic LD [$FF00+n8],A
into the opcode
.Ic LDH [$FF00+n8],A
.Ic LD [H $FF00+n8],A
in order to have full control of the result in the final ROM.
.It Fl M Ar depend_file , Fl Fl dependfile Ar depend_file
Print
.Xr make 1
dependencies to
.Ar depend_file .
.It Fl MG
To be used in conjunction with
.Fl M .
This makes
.Nm
assume that missing files are auto-generated: when
.Ic INCLUDE
or
.Ic INCBIN
is attempted on a non-existent file, it is added as a dependency, then
.Nm
exits normally instead of erroring out.
This feature is used in automatic updating of makefiles.
.It Fl MP
When enabled, this causes a phony target to be added for each dependency other than the main file.
This prevents
.Xr make 1
from erroring out when dependency files are deleted.
.It Fl MT Ar target_file
Add a target to the rules emitted by
.Fl M .
The exact string provided will be written, including spaces and special characters.
.Dl Fl MT No fileA Fl MT No fileB
is equivalent to
.Dl Fl MT No 'fileA fileB' .
If neither this nor
.Fl MQ
is specified, the output file name is used.
.It Fl MQ Ar target_file
Same as
.Fl MT ,
but additionally escapes any special
.Xr make 1
characters, essentially
.Sq $ .
.It Fl o Ar out_file , Fl Fl output Ar out_file
Write an object file to the given filename.
.It Fl p Ar pad_value , Fl Fl pad-value Ar pad_value
@@ -140,9 +179,9 @@ Enables literally every warning.
.Pp
The following warnings are actual warning flags; with each description, the corresponding warning flag is included.
Note that each of these flag also has a negation (for example,
.Fl Wempty-entry
.Fl Wcharmap-redef
enables the warning that
.Fl Wno-empty-entry
.Fl Wno-charmap-redef
disables).
Only the non-default flag is listed here.
Ignoring the
@@ -164,14 +203,22 @@ Warn about incorrect arguments to built-in functions, such as
with indexes outside of the string's bounds.
This warning is enabled by
.Fl Wall .
.It Fl Wcharmap-redef
Warn when re-defining a charmap mapping.
This warning is enabled by
.Fl Wall .
.It Fl Wdiv
Warn when dividing the smallest negative integer by -1, which yields itself due to integer overflow.
.It Fl Wempty-entry
Warn when an empty entry is encountered in a
.Ic db , dw , dl
list.
.It Fl Wempty-macro-arg
Warn when a macro argument is empty.
This warning is enabled by
.Fl Wextra .
.It Fl Wempty-strrpl
Warn when
.Fn STRRPL
is called with an empty string as its second argument (the substring to replace).
This warning is enabled by
.Fl Wall .
.It Fl Wlarge-constant
Warn when a constant too large to fit in a signed 32-bit integer is encountered.
This warning is enabled by
@@ -180,14 +227,16 @@ This warning is enabled by
Warn when a string too long to fit in internal buffers is encountered.
This warning is enabled by
.Fl Wall .
.It Fl Wobsolete
Warn when obsolete constructs such as the
.Ic jp [hl]
instruction or
.Ic HOME
section type are encountered.
.It Fl Wmacro-shift
Warn when shifting macro arguments past their limits.
This warning is enabled by
.Fl Wextra .
.It Fl Wno-obsolete
Warn when obsolete constructs such as the
.Ic _PI
constant or
.Ic PRINTT
directive are encountered.
.It Fl Wshift
Warn when shifting right a negative value.
Use a division by 2^N instead.
@@ -195,7 +244,7 @@ Use a division by 2^N instead.
Warn when a shift's operand is negative or greater than 32.
.It Fl Wno-truncation
Warn when an implicit truncation (for example,
.Ic db )
.Ic LD [B @] )
loses some bits.
.It Fl Wno-user
Warn when the
@@ -223,7 +272,7 @@ and then
.Xr rgbfix 1 .
.Sh BUGS
Please report bugs on
.Lk https://github.com/rednex/rgbds/issues GitHub .
.Lk https://github.com/gbdev/rgbds/issues GitHub .
.Sh SEE ALSO
.Xr rgbasm 5 ,
.Xr rgbfix 1 ,
@@ -235,4 +284,4 @@ Please report bugs on
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package, and was later packaged in RGBDS by Justin Lloyd.
It is now maintained by a number of contributors at
.Lk https://github.com/rednex/rgbds .
.Lk https://github.com/gbdev/rgbds .
+827 -352
View File
File diff suppressed because it is too large Load Diff
+100 -117
View File
@@ -12,17 +12,21 @@
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/asm.h"
#include "asm/main.h"
#include "asm/output.h"
#include "asm/rpn.h"
#include "asm/section.h"
#include "asm/symbol.h"
#include "asm/warning.h"
#include "opmath.h"
/* Makes an expression "not known", also setting its error message */
#define makeUnknown(expr_, ...) do { \
struct Expression *_expr = expr_; \
@@ -30,7 +34,7 @@
/* If we had `asprintf` this would be great, but alas. */ \
_expr->reason = malloc(128); /* Use an initial reasonable size */ \
if (!_expr->reason) \
fatalerror("Can't allocate err string: %s", strerror(errno)); \
fatalerror("Can't allocate err string: %s\n", strerror(errno)); \
int size = snprintf(_expr->reason, 128, __VA_ARGS__); \
if (size >= 128) { /* If this wasn't enough, try again */ \
_expr->reason = realloc(_expr->reason, size + 1); \
@@ -45,22 +49,23 @@ static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
/* If there isn't enough room to reserve the space, realloc */
if (!expr->tRPN)
expr->nRPNCapacity = 256; /* Initial size */
else if (expr->nRPNCapacity >= MAXRPNLEN)
/*
* To avoid generating humongous object files, cap the
* size of RPN expressions
*/
fatalerror("RPN expression cannot grow larger than %d bytes",
MAXRPNLEN);
else if (expr->nRPNCapacity > MAXRPNLEN / 2)
expr->nRPNCapacity = MAXRPNLEN;
else
expr->nRPNCapacity *= 2;
while (expr->nRPNCapacity - expr->nRPNLength < size) {
if (expr->nRPNCapacity >= MAXRPNLEN)
/*
* To avoid generating humongous object files, cap the
* size of RPN expressions
*/
fatalerror("RPN expression cannot grow larger than "
EXPAND_AND_STR(MAXRPNLEN) " bytes\n");
else if (expr->nRPNCapacity > MAXRPNLEN / 2)
expr->nRPNCapacity = MAXRPNLEN;
else
expr->nRPNCapacity *= 2;
}
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
if (!expr->tRPN)
fatalerror("Failed to grow RPN expression: %s",
strerror(errno));
fatalerror("Failed to grow RPN expression: %s\n", strerror(errno));
}
uint8_t *ptr = expr->tRPN + expr->nRPNLength;
@@ -102,38 +107,26 @@ void rpn_Number(struct Expression *expr, uint32_t i)
expr->nVal = i;
}
void rpn_Symbol(struct Expression *expr, char *tzSym)
void rpn_Symbol(struct Expression *expr, char const *tzSym)
{
struct sSymbol *sym = sym_FindSymbol(tzSym);
struct Symbol *sym = sym_FindScopedSymbol(tzSym);
if (sym == pPCSymbol && !pPCSymbol->pSection) {
yyerror("PC has no value outside a section");
if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
error("PC has no value outside a section\n");
rpn_Number(expr, 0);
} else if (!sym || !sym_IsConstant(sym)) {
rpn_Init(expr);
expr->isSymbol = true;
sym_Ref(tzSym);
makeUnknown(expr, strcmp(tzSym, "@")
? "'%s' is not constant at assembly time"
: "PC is not constant at assembly time",
tzSym);
makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time"
: "'%s' is not constant at assembly time", tzSym);
sym = sym_Ref(tzSym);
expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */
size_t nameLen = strlen(sym->name) + 1; /* Don't forget NUL! */
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_SYM;
memcpy(ptr, tzSym, nameLen);
/* RGBLINK assumes PC is at the byte being computed... */
if (sym == pPCSymbol && nPCOffset) {
struct Expression pc = *expr, offset;
rpn_Number(&offset, nPCOffset);
rpn_BinaryOp(RPN_SUB, expr, &pc, &offset);
if (!rpn_isKnown(expr))
expr->isSymbol = true;
}
memcpy(ptr, sym->name, nameLen);
} else {
rpn_Number(expr, sym_GetConstantValue(tzSym));
}
@@ -143,44 +136,46 @@ void rpn_BankSelf(struct Expression *expr)
{
rpn_Init(expr);
if (pCurrentSection->nBank == -1) {
if (!pCurrentSection) {
error("PC has no bank outside a section\n");
expr->nVal = 1;
} else if (pCurrentSection->bank == (uint32_t)-1) {
makeUnknown(expr, "Current section's bank is not known");
expr->nRPNPatchSize++;
*reserveSpace(expr, 1) = RPN_BANK_SELF;
} else {
expr->nVal = pCurrentSection->nBank;
expr->nVal = pCurrentSection->bank;
}
}
void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
{
struct sSymbol const *sym = sym_FindSymbol(tzSym);
struct Symbol const *sym = sym_FindScopedSymbol(tzSym);
/* The @ symbol is treated differently. */
if (sym == pPCSymbol) {
if (sym_IsPC(sym)) {
rpn_BankSelf(expr);
return;
}
rpn_Init(expr);
if (sym && !sym_IsLabel(sym)) {
yyerror("BANK argument must be a label");
error("BANK argument must be a label\n");
} else {
sym_Ref(tzSym);
/* If the symbol didn't exist, `sym_Ref` created it */
struct sSymbol *pSymbol = sym_FindSymbol(tzSym);
sym = sym_Ref(tzSym);
assert(sym); // If the symbol didn't exist, it should have been created
if (pSymbol->pSection && pSymbol->pSection->nBank != -1) {
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != (uint32_t)-1) {
/* Symbol's section is known and bank is fixed */
expr->nVal = pSymbol->pSection->nBank;
expr->nVal = sym_GetSection(sym)->bank;
} else {
makeUnknown(expr, "\"%s\"'s bank is not known", tzSym);
expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */
size_t nameLen = strlen(tzSym) + 1; /* Room for NUL! */
size_t nameLen = strlen(sym->name) + 1; /* Room for NUL! */
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
*ptr++ = RPN_BANK_SYM;
memcpy(ptr, tzSym, nameLen);
memcpy(ptr, sym->name, nameLen);
}
}
}
@@ -191,8 +186,8 @@ void rpn_BankSection(struct Expression *expr, char const *tzSectionName)
struct Section *pSection = out_FindSectionByName(tzSectionName);
if (pSection && pSection->nBank != -1) {
expr->nVal = pSection->nBank;
if (pSection && pSection->bank != (uint32_t)-1) {
expr->nVal = pSection->bank;
} else {
makeUnknown(expr, "Section \"%s\"'s bank is not known",
tzSectionName);
@@ -218,7 +213,7 @@ void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src)
/* That range is valid, but only keep the lower byte */
expr->nVal &= 0xFF;
} else if (expr->nVal < 0 || expr->nVal > 0xFF) {
yyerror("Source address $%x not in $FF00 to $FFFF", expr->nVal);
error("Source address $%" PRIx32 " not between $FF00 to $FFFF\n", expr->nVal);
}
}
@@ -229,7 +224,7 @@ void rpn_CheckRST(struct Expression *expr, const struct Expression *src)
if (rpn_isKnown(expr)) {
/* A valid RST address must be masked with 0x38 */
if (expr->nVal & ~0x38)
yyerror("Invalid address $%x for RST", expr->nVal);
error("Invalid address $%" PRIx32 " for RST\n", expr->nVal);
/* The target is in the "0x38" bits, all other bits are set */
expr->nVal |= 0xC7;
} else {
@@ -251,64 +246,30 @@ void rpn_LOGNOT(struct Expression *expr, const struct Expression *src)
}
}
static int32_t shift(int32_t shiftee, int32_t amount)
{
if (amount >= 0) {
// Left shift
if (amount >= 32) {
warning(WARNING_SHIFT_AMOUNT, "Shifting left by large amount %d",
amount);
return 0;
} else {
/*
* Use unsigned to force a bitwise shift
* Casting back is OK because the types implement two's
* complement behavior
*/
return (uint32_t)shiftee << amount;
}
} else {
// Right shift
amount = -amount;
if (amount >= 32) {
warning(WARNING_SHIFT_AMOUNT, "Shifting right by large amount %d",
amount);
return shiftee < 0 ? -1 : 0;
} else if (shiftee >= 0) {
return shiftee >> amount;
} else {
/*
* The C standard leaves shifting right negative values
* undefined, so use a left shift manually sign-extended
*/
return (uint32_t)shiftee >> amount
| -((uint32_t)1 << (32 - amount));
}
}
}
static struct sSymbol const *symbolOf(struct Expression const *expr)
struct Symbol const *rpn_SymbolOf(struct Expression const *expr)
{
if (!rpn_isSymbol(expr))
return NULL;
return sym_FindSymbol((char *)expr->tRPN + 1);
return sym_FindScopedSymbol((char *)expr->tRPN + 1);
}
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
{
/* Check if both expressions only refer to a single symbol */
struct Symbol const *sym1 = rpn_SymbolOf(src);
if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
return false;
struct Section const *section1 = sym_GetSection(sym1);
struct Section const *section2 = sym_GetSection(sym);
return section1 && (section1 == section2);
}
static bool isDiffConstant(struct Expression const *src1,
struct Expression const *src2)
{
/* Check if both expressions only refer to a single symbol */
struct sSymbol const *symbol1 = symbolOf(src1);
struct sSymbol const *symbol2 = symbolOf(src2);
if (!symbol1 || !symbol2
|| symbol1->type != SYM_LABEL || symbol2->type != SYM_LABEL)
return false;
return symbol1->pSection == symbol2->pSection;
return rpn_IsDiffConstant(src1, rpn_SymbolOf(src2));
}
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
@@ -366,45 +327,67 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
break;
case RPN_SHL:
if (src2->nVal < 0)
warning(WARNING_SHIFT_AMOUNT, "Shifting left by negative amount %d",
warning(WARNING_SHIFT_AMOUNT,
"Shifting left by negative amount %" PRId32 "\n",
src2->nVal);
expr->nVal = shift(src1->nVal, src2->nVal);
if (src2->nVal >= 32)
warning(WARNING_SHIFT_AMOUNT,
"Shifting left by large amount %" PRId32 "\n",
src2->nVal);
expr->nVal = op_shift_left(src1->nVal, src2->nVal);
break;
case RPN_SHR:
if (src1->nVal < 0)
warning(WARNING_SHIFT, "Shifting negative value %d",
warning(WARNING_SHIFT, "Shifting right negative value %"
PRId32 "\n",
src1->nVal);
if (src2->nVal < 0)
warning(WARNING_SHIFT_AMOUNT, "Shifting right by negative amount %d",
warning(WARNING_SHIFT_AMOUNT,
"Shifting right by negative amount %" PRId32 "\n",
src2->nVal);
expr->nVal = shift(src1->nVal, -src2->nVal);
if (src2->nVal >= 32)
warning(WARNING_SHIFT_AMOUNT,
"Shifting right by large amount %" PRId32 "\n",
src2->nVal);
expr->nVal = op_shift_right(src1->nVal, src2->nVal);
break;
case RPN_MUL:
expr->nVal = uleft * uright;
break;
case RPN_DIV:
if (src2->nVal == 0)
fatalerror("Division by zero");
fatalerror("Division by zero\n");
if (src1->nVal == INT32_MIN
&& src2->nVal == -1) {
warning(WARNING_DIV, "Division of min value by -1");
if (src1->nVal == INT32_MIN && src2->nVal == -1) {
warning(WARNING_DIV, "Division of %" PRId32 " by -1 yields %"
PRId32 "\n", INT32_MIN, INT32_MIN);
expr->nVal = INT32_MIN;
} else {
expr->nVal = src1->nVal / src2->nVal;
expr->nVal = op_divide(src1->nVal, src2->nVal);
}
break;
case RPN_MOD:
if (src2->nVal == 0)
fatalerror("Division by zero");
fatalerror("Modulo by zero\n");
if (src1->nVal == INT32_MIN && src2->nVal == -1)
expr->nVal = 0;
else
expr->nVal = src1->nVal % src2->nVal;
expr->nVal = op_modulo(src1->nVal, src2->nVal);
break;
case RPN_EXP:
if (src2->nVal < 0)
fatalerror("Exponentiation by negative power\n");
if (src1->nVal == INT32_MIN && src2->nVal == -1)
expr->nVal = 0;
else
expr->nVal = op_exponent(src1->nVal, src2->nVal);
break;
case RPN_UNSUB:
@@ -417,12 +400,12 @@ void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
case RPN_RST:
case RPN_CONST:
case RPN_SYM:
fatalerror("%d is no binary operator", op);
fatalerror("%d is not a binary operator\n", op);
}
} else if (op == RPN_SUB && isDiffConstant(src1, src2)) {
struct sSymbol const *symbol1 = symbolOf(src1);
struct sSymbol const *symbol2 = symbolOf(src2);
struct Symbol const *symbol1 = rpn_SymbolOf(src1);
struct Symbol const *symbol2 = rpn_SymbolOf(src2);
expr->nVal = sym_GetValue(symbol1) - sym_GetValue(symbol2);
expr->isKnown = true;
+539 -291
View File
File diff suppressed because it is too large Load Diff
+490 -328
View File
File diff suppressed because it is too large Load Diff
+47 -11
View File
@@ -6,6 +6,7 @@
* SPDX-License-Identifier: MIT
*/
#include <ctype.h>
#include <stdint.h>
#include "asm/main.h"
@@ -15,7 +16,9 @@
#include "extern/utf8decoder.h"
/*
* Calculate the hash value for a string
* Calculate the hash value for a string.
* Uses the djb2 algorithm (xor version).
* http://www.cse.yorku.ca/~oz/hash.html
*/
uint32_t calchash(const char *s)
{
@@ -27,21 +30,54 @@ uint32_t calchash(const char *s)
return hash;
}
int32_t readUTF8Char(char *dest, char *src)
char const *print(int c)
{
uint32_t state;
uint32_t codep;
int32_t i;
static char buf[5]; /* '\xNN' + '\0' */
for (i = 0, state = 0;; i++) {
if (decode(&state, &codep, (uint8_t)src[i]) == 1)
fatalerror("invalid UTF-8 character");
if (c == EOF)
return "EOF";
if (isprint(c)) {
buf[0] = c;
buf[1] = '\0';
return buf;
}
buf[0] = '\\';
switch (c) {
case '\n':
buf[1] = 'n';
break;
case '\r':
buf[1] = 'r';
break;
case '\t':
buf[1] = 't';
break;
default: /* Print as hex */
buf[1] = 'x';
sprintf(&buf[2], "%02hhx", (uint8_t)c);
return buf;
}
buf[2] = '\0';
return buf;
}
size_t readUTF8Char(uint8_t *dest, char const *src)
{
uint32_t state = 0;
uint32_t codep;
size_t i = 0;
for (;;) {
if (decode(&state, &codep, src[i]) == 1)
return 0;
dest[i] = src[i];
i++;
if (state == 0) {
dest[++i] = '\0';
if (state == 0)
return i;
}
}
}
+55 -41
View File
@@ -10,6 +10,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "asm/fstack.h"
@@ -28,17 +29,22 @@ enum WarningState {
};
static enum WarningState const defaultWarnings[NB_WARNINGS] = {
WARNING_ENABLED, /* Assertions */
WARNING_DISABLED, /* Invalid args to builtins */
WARNING_DISABLED, /* Division undefined behavior */
WARNING_DISABLED, /* Empty entry in `db`, `dw` or `dl` */
WARNING_DISABLED, /* Constants too large */
WARNING_DISABLED, /* String too long for internal buffers */
WARNING_DISABLED, /* Obsolete things */
WARNING_DISABLED, /* Shifting undefined behavior */
WARNING_DISABLED, /* Strange shift amount */
WARNING_ENABLED, /* Implicit truncation loses some bits */
WARNING_ENABLED, /* User warnings */
[WARNING_ASSERT] = WARNING_ENABLED,
[WARNING_BUILTIN_ARG] = WARNING_DISABLED,
[WARNING_CHARMAP_REDEF] = WARNING_DISABLED,
[WARNING_DIV] = WARNING_DISABLED,
[WARNING_EMPTY_DATA_DIRECTIVE] = WARNING_DISABLED,
[WARNING_EMPTY_MACRO_ARG] = WARNING_DISABLED,
[WARNING_EMPTY_STRRPL] = WARNING_DISABLED,
[WARNING_LARGE_CONSTANT] = WARNING_DISABLED,
[WARNING_LONG_STR] = WARNING_DISABLED,
[WARNING_MACRO_SHIFT] = WARNING_DISABLED,
[WARNING_NESTED_COMMENT] = WARNING_ENABLED,
[WARNING_OBSOLETE] = WARNING_ENABLED,
[WARNING_SHIFT] = WARNING_DISABLED,
[WARNING_SHIFT_AMOUNT] = WARNING_DISABLED,
[WARNING_TRUNCATION] = WARNING_ENABLED,
[WARNING_USER] = WARNING_ENABLED,
};
static enum WarningState warningStates[NB_WARNINGS];
@@ -48,7 +54,7 @@ static bool warningsAreErrors; /* Set if `-Werror` was specified */
static enum WarningState warningState(enum WarningID id)
{
/* Check if warnings are globally disabled */
if (!CurrentOptions.warnings)
if (!warnings)
return WARNING_DISABLED;
/* Get the actual state */
@@ -67,10 +73,15 @@ static enum WarningState warningState(enum WarningID id)
static char const *warningFlags[NB_WARNINGS_ALL] = {
"assert",
"builtin-args",
"charmap-redef",
"div",
"empty-entry",
"empty-data-directive",
"empty-macro-arg",
"empty-strrpl",
"large-constant",
"long-string",
"macro-shift",
"nested-comment",
"obsolete",
"shift",
"shift-amount",
@@ -90,6 +101,9 @@ enum MetaWarningCommand {
/* Warnings that probably indicate an error */
static uint8_t const _wallCommands[] = {
WARNING_BUILTIN_ARG,
WARNING_CHARMAP_REDEF,
WARNING_EMPTY_DATA_DIRECTIVE,
WARNING_EMPTY_STRRPL,
WARNING_LARGE_CONSTANT,
WARNING_LONG_STR,
META_WARNING_DONE
@@ -97,8 +111,9 @@ static uint8_t const _wallCommands[] = {
/* Warnings that are less likely to indicate an error */
static uint8_t const _wextraCommands[] = {
WARNING_EMPTY_ENTRY,
WARNING_OBSOLETE,
WARNING_EMPTY_MACRO_ARG,
WARNING_MACRO_SHIFT,
WARNING_NESTED_COMMENT,
META_WARNING_DONE
};
@@ -106,9 +121,13 @@ static uint8_t const _wextraCommands[] = {
static uint8_t const _weverythingCommands[] = {
WARNING_BUILTIN_ARG,
WARNING_DIV,
WARNING_EMPTY_ENTRY,
WARNING_EMPTY_DATA_DIRECTIVE,
WARNING_EMPTY_MACRO_ARG,
WARNING_EMPTY_STRRPL,
WARNING_LARGE_CONSTANT,
WARNING_LONG_STR,
WARNING_MACRO_SHIFT,
WARNING_NESTED_COMMENT,
WARNING_OBSOLETE,
WARNING_SHIFT,
WARNING_SHIFT_AMOUNT,
@@ -192,32 +211,32 @@ void processWarningFlag(char const *flag)
warnx("Unknown warning `%s`", flag);
}
void verror(const char *fmt, va_list args, char const *flag)
void printDiag(const char *fmt, va_list args, char const *type,
char const *flagfmt, char const *flag)
{
fputs("ERROR: ", stderr);
fstk_Dump();
fprintf(stderr, flag ? ": [-Werror=%s]\n " : ":\n ", flag);
fputs(type, stderr);
fstk_DumpCurrent();
fprintf(stderr, flagfmt, flag);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
fstk_DumpStringExpansions();
lexer_DumpStringExpansions();
}
void error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
printDiag(fmt, args, "ERROR: ", ":\n ", NULL);
va_end(args);
nbErrors++;
}
void yyerror(const char *fmt, ...)
_Noreturn void fatalerror(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
verror(fmt, args, NULL);
va_end(args);
}
noreturn_ void fatalerror(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
verror(fmt, args, NULL);
printDiag(fmt, args, "FATAL: ", ":\n ", NULL);
va_end(args);
exit(1);
@@ -235,24 +254,19 @@ void warning(enum WarningID id, char const *fmt, ...)
return;
case WARNING_ERROR:
verror(fmt, args, flag);
printDiag(fmt, args, "ERROR: ", ": [-Werror=%s]\n ", flag);
va_end(args);
return;
case WARNING_DEFAULT:
trap_;
unreachable_();
/* Not reached */
case WARNING_ENABLED:
break;
}
fputs("warning: ", stderr);
fstk_Dump();
fprintf(stderr, ": [-W%s]\n ", flag);
vfprintf(stderr, fmt, args);
fputc('\n', stderr);
fstk_DumpStringExpansions();
printDiag(fmt, args, "warning: ", ": [-W%s]\n ", flag);
va_end(args);
}
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
bison -V | awk -v major="$1" -v minor="$2" '
/^bison.*[0-9]+(\.[0-9]+)(\.[0-9]+)?$/ {
match($0, /[0-9]+(\.[0-9]+)(\.[0-9]+)?$/);
split(substr($0, RSTART), ver, ".");
if (ver[1] == major && ver[2] >= minor) { exit 0 } else { exit 1 }
}'
+4 -4
View File
@@ -34,7 +34,7 @@ void rgbds_vwarnx(const char *fmt, va_list ap)
putc('\n', stderr);
}
noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap)
_Noreturn void rgbds_verr(int status, const char *fmt, va_list ap)
{
fprintf(stderr, "error: ");
if (fmt) {
@@ -46,7 +46,7 @@ noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap)
exit(status);
}
noreturn_ void rgbds_verrx(int status, const char *fmt, va_list ap)
_Noreturn void rgbds_verrx(int status, const char *fmt, va_list ap)
{
fprintf(stderr, "error");
if (fmt) {
@@ -75,7 +75,7 @@ void rgbds_warnx(const char *fmt, ...)
va_end(ap);
}
noreturn_ void rgbds_err(int status, const char *fmt, ...)
_Noreturn void rgbds_err(int status, const char *fmt, ...)
{
va_list ap;
@@ -84,7 +84,7 @@ noreturn_ void rgbds_err(int status, const char *fmt, ...)
va_end(ap);
}
noreturn_ void rgbds_errx(int status, const char *fmt, ...)
_Noreturn void rgbds_errx(int status, const char *fmt, ...)
{
va_list ap;
+179 -72
View File
@@ -1,5 +1,5 @@
/*
* Copyright © 2005-2019 Rich Felker, et al.
* Copyright © 2005-2020 Rich Felker, et al.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -26,80 +26,180 @@
#include <stddef.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include "extern/getopt.h"
int __optpos, __optreset;
char *musl_optarg;
int musl_optind = 1, musl_opterr = 1, musl_optopt;
int musl_optreset = 0;
static int musl_optpos;
void musl__getopt_msg(const char *a, const char *b, const char *c, size_t l)
static void musl_getopt_msg(const char *a, const char *b, const char *c, size_t l)
{
FILE *f = stderr;
(void)(fputs(a, f)>=0
&& fwrite(b, strlen(b), 1, f)
&& fwrite(c, 1, l, f)==l
&& putc('\n', f));
if (fputs(a, f) >= 0 &&
fwrite(b, strlen(b), 1, f) &&
fwrite(c, 1, l, f) == l)
putc('\n', f);
}
static int getopt(int argc, char *argv[], const char *optstring)
{
int i;
wchar_t c, d;
int k, l;
char *optchar;
if (!musl_optind || musl_optreset) {
musl_optreset = 0;
musl_optpos = 0;
musl_optind = 1;
}
if (musl_optind >= argc || !argv[musl_optind])
return -1;
if (argv[musl_optind][0] != '-') {
if (optstring[0] == '-') {
musl_optarg = argv[musl_optind++];
return 1;
}
return -1;
}
if (!argv[musl_optind][1])
return -1;
if (argv[musl_optind][1] == '-' && !argv[musl_optind][2])
return musl_optind++, -1;
if (!musl_optpos)
musl_optpos++;
k = mbtowc(&c, argv[musl_optind] + musl_optpos, MB_LEN_MAX);
if (k < 0) {
k = 1;
c = 0xfffd; /* replacement char */
}
optchar = argv[musl_optind] + musl_optpos;
musl_optpos += k;
if (!argv[musl_optind][musl_optpos]) {
musl_optind++;
musl_optpos = 0;
}
if (optstring[0] == '-' || optstring[0] == '+')
optstring++;
i = 0;
d = 0;
do {
l = mbtowc(&d, optstring+i, MB_LEN_MAX);
if (l > 0)
i += l;
else
i++;
} while (l && d != c);
if (d != c || c == ':') {
musl_optopt = c;
if (optstring[0] != ':' && musl_opterr)
musl_getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
return '?';
}
if (optstring[i] == ':') {
musl_optarg = 0;
if (optstring[i + 1] != ':' || musl_optpos) {
musl_optarg = argv[musl_optind++] + musl_optpos;
musl_optpos = 0;
}
if (musl_optind > argc) {
musl_optopt = c;
if (optstring[0] == ':')
return ':';
if (musl_opterr)
musl_getopt_msg(argv[0], ": option requires an argument: ",
optchar, k);
return '?';
}
}
return c;
}
static void permute(char **argv, int dest, int src)
{
char **av = (char **)argv;
char *tmp = av[src];
char *tmp = argv[src];
int i;
for (i=src; i>dest; i--)
av[i] = av[i-1];
av[dest] = tmp;
for (i = src; i > dest; i--)
argv[i] = argv[i-1];
argv[dest] = tmp;
}
static int musl__getopt_long_core(int argc, char **argv, const char *optstring, const struct option *longopts, int *idx, int longonly);
static int musl_getopt_long_core(int argc, char **argv, const char *optstring, const struct option *longopts, int *idx, int longonly);
static int musl__getopt_long(int argc, char **argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
static int musl_getopt_long(int argc, char **argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
{
int ret, skipped, resumed;
if (!optind || __optreset) {
__optreset = 0;
__optpos = 0;
optind = 1;
if (!musl_optind || musl_optreset) {
musl_optreset = 0;
musl_optpos = 0;
musl_optind = 1;
}
if (optind >= argc || !argv[optind]) return -1;
skipped = optind;
if (musl_optind >= argc || !argv[musl_optind])
return -1;
skipped = musl_optind;
if (optstring[0] != '+' && optstring[0] != '-') {
int i;
for (i=optind; ; i++) {
if (i >= argc || !argv[i]) return -1;
if (argv[i][0] == '-' && argv[i][1]) break;
for (i = musl_optind; ; i++) {
if (i >= argc || !argv[i])
return -1;
if (argv[i][0] == '-' && argv[i][1])
break;
}
optind = i;
musl_optind = i;
}
resumed = optind;
ret = musl__getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
resumed = musl_optind;
ret = musl_getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
if (resumed > skipped) {
int i, cnt = optind-resumed;
for (i=0; i<cnt; i++)
permute(argv, skipped, optind-1);
optind = skipped + cnt;
int i, cnt = musl_optind - resumed;
for (i = 0; i < cnt; i++)
permute(argv, skipped, musl_optind - 1);
musl_optind = skipped + cnt;
}
return ret;
}
static int musl__getopt_long_core(int argc, char **argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
static int musl_getopt_long_core(int argc, char **argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
{
optarg = 0;
if (longopts && argv[optind][0] == '-' &&
((longonly && argv[optind][1] && argv[optind][1] != '-') ||
(argv[optind][1] == '-' && argv[optind][2])))
{
int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
int i, cnt, match;
char *arg, *opt, *start = argv[optind]+1;
for (cnt=i=0; longopts[i].name; i++) {
musl_optarg = 0;
if (longopts && argv[musl_optind][0] == '-' &&
((longonly && argv[musl_optind][1] && argv[musl_optind][1] != '-') ||
(argv[musl_optind][1] == '-' && argv[musl_optind][2]))) {
int colon = optstring[optstring[0] == '+' || optstring[0] == '-'] == ':';
int i, cnt, match = 0;
char *arg = 0, *opt, *start = argv[musl_optind] + 1;
for (cnt = i = 0; longopts[i].name; i++) {
const char *name = longopts[i].name;
opt = start;
if (*opt == '-') opt++;
while (*opt && *opt != '=' && *opt == *name)
name++, opt++;
if (*opt && *opt != '=') continue;
if (*opt == '-')
opt++;
while (*opt && *opt != '=' && *opt == *name) {
name++;
opt++;
}
if (*opt && *opt != '=')
continue;
arg = opt;
match = i;
if (!*name) {
@@ -108,62 +208,69 @@ static int musl__getopt_long_core(int argc, char **argv, const char *optstring,
}
cnt++;
}
if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) {
int l = arg-start;
for (i=0; optstring[i]; i++) {
int j;
for (j=0; j<l && start[j]==optstring[i+j]; j++);
if (j==l) {
if (cnt == 1 && longonly && arg - start == mblen(start, MB_LEN_MAX)) {
int l = arg - start;
for (i = 0; optstring[i]; i++) {
int j = 0;
while (j < l && start[j] == optstring[i + j])
j++;
if (j == l) {
cnt++;
break;
}
}
}
if (cnt==1) {
if (cnt == 1) {
i = match;
opt = arg;
optind++;
musl_optind++;
if (*opt == '=') {
if (!longopts[i].has_arg) {
optopt = longopts[i].val;
if (colon || !opterr)
musl_optopt = longopts[i].val;
if (colon || !musl_opterr)
return '?';
musl__getopt_msg(argv[0],
musl_getopt_msg(argv[0],
": option does not take an argument: ",
longopts[i].name,
strlen(longopts[i].name));
return '?';
}
optarg = opt+1;
musl_optarg = opt + 1;
} else if (longopts[i].has_arg == required_argument) {
if (!(optarg = argv[optind])) {
optopt = longopts[i].val;
if (colon) return ':';
if (!opterr) return '?';
musl__getopt_msg(argv[0],
musl_optarg = argv[musl_optind];
if (!musl_optarg) {
musl_optopt = longopts[i].val;
if (colon)
return ':';
if (!musl_opterr)
return '?';
musl_getopt_msg(argv[0],
": option requires an argument: ",
longopts[i].name,
strlen(longopts[i].name));
return '?';
}
optind++;
musl_optind++;
}
if (idx) *idx = i;
if (idx)
*idx = i;
if (longopts[i].flag) {
*longopts[i].flag = longopts[i].val;
return 0;
}
return longopts[i].val;
}
if (argv[optind][1] == '-') {
optopt = 0;
if (!colon && opterr)
musl__getopt_msg(argv[0], cnt ?
if (argv[musl_optind][1] == '-') {
musl_optopt = 0;
if (!colon && musl_opterr)
musl_getopt_msg(argv[0], cnt ?
": option is ambiguous: " :
": unrecognized option: ",
argv[optind]+2,
strlen(argv[optind]+2));
optind++;
argv[musl_optind] + 2,
strlen(argv[musl_optind] + 2));
musl_optind++;
return '?';
}
}
@@ -172,5 +279,5 @@ static int musl__getopt_long_core(int argc, char **argv, const char *optstring,
int musl_getopt_long_only(int argc, char **argv, const char *optstring, const struct option *longopts, int *idx)
{
return musl__getopt_long(argc, argv, optstring, longopts, idx, 1);
return musl_getopt_long(argc, argv, optstring, longopts, idx, 1);
}
+1 -1
View File
@@ -38,7 +38,7 @@ static const uint8_t utf8d[] = {
1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* s8 */
};
uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte)
uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte)
{
uint32_t type = utf8d[byte];
+1084 -439
View File
File diff suppressed because it is too large Load Diff

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