Compare commits

..

121 Commits

Author SHA1 Message Date
Antonio Niño Díaz
83348100f3 Improve MinGW target of Makefile
It works now with an install of MinGW for both Win32 and Win64. It needs
libpng and zlib.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 17:28:07 +01:00
Antonio Niño Díaz
57bf32f35a Point at the documentation from README
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 14:49:57 +01:00
Antonio Niño Díaz
0030e0371a Rename object file format description man page
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 14:15:46 +01:00
Antonio Niño Díaz
42400ec6a0 Fix links in HTML documentation
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 23:08:33 +01:00
Antonio Niño Díaz
2e793fb7dc Clean wwwman target of Makefile
The substitution of OpenBSD by General is not portable.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 22:52:10 +01:00
Antonio Niño Díaz
ac69e9863e Fix documentation in HTML format
For some reason, `No` looks weird in the HTML version of the docs.

Some other random fixes.

Tables in src/asm/rgbasm.5 are still broken in the HTML docs.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 22:50:54 +01:00
Antonio Niño Díaz
59c065cf31 Merge pull request #165 from AntonioND/an/rgbasm-manual
Add documentation of rgbds to man pages and cleanup code

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 20:13:49 +01:00
Antonio Niño Díaz
729683fb1f Remove RPN_RANGECHECK
Leftover code from ASMotor.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 19:55:00 +01:00
Antonio Niño Díaz
ed6e4c4769 Clean object file format code and documentation
Remove unused code.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 19:54:58 +01:00
Antonio Niño Díaz
d92c284b85 Add documentation about the object file format
Copied from the HTML documentation and updated.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 19:54:55 +01:00
Antonio Niño Díaz
26af7fcffe Add complete documentation of rgbds to man pages
Copied from the old html documentation and fixed where it was needed.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-16 19:54:50 +01:00
Antonio Niño Díaz
f7f697c267 Fix parsing of first line of included linkerscripts
When including a linkerscript from a parent one, the lexer didn't
include a newline character because the INCLUDE command was handled
before reaching the newline. This behaviour is needed to parse the last
line of a linkerscript correctly (it doesn't have a newline character).

However, this meant that when the included file was being parsed, the
first line was considered a continuation of the last line of the parent
script (the INCLUDE command), which means that the first line of an
included linkerscript could only contain a comment (or nothing at all).

This patch adds a newline character to the buffer used by the lexer so
that the parser will receive a newline and it will handle the first line
of the included file as expected.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-14 17:07:01 +01:00
Antonio Niño Díaz
554b5292de Rename ISO 8601 timestamp defines
The previous names were ridiculously long.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-12 22:19:53 +01:00
Antonio Niño Díaz
a7393d7e45 Merge pull request #163 from AntonioND/an/iso-8601
Add equates with ISO 8601 date and time

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-10 23:34:12 +01:00
Antonio Niño Díaz
fe9e4f0583 Merge pull request #169 from AntonioND/an/travis-test
Add Travis CI configuration file

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-10 22:59:10 +01:00
Antonio Niño Díaz
362aea22bd Fix conflict in yacc
`LD HL,n16` and `LD SP,n16` are handled in a different rule as
`LD r16,n16`, but they are also part of that rule.

This patch converts the `LD r16,n16` rule into two rules, one for doing
`LD BC,n16` and other one for `LD DE,n16`.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-10 22:57:05 +01:00
Antonio Niño Díaz
9bc6083e49 Add Travis CI configuration file
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-10 22:10:26 +01:00
Antonio Niño Díaz
2b5ad9dc38 Make test scripts return error code
Make them executable.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-10 22:10:10 +01:00
Antonio Niño Díaz
5679c7066b Restore behaviour of option -w and add option -d
rgblink option -w has been restored to its previous behaviour: make WRAM
a continous section instead of spliting it into WRAM0 and WRAMX.

To enable DMG mode, option -d has to be used instead. This option
automatically enables -w.

Update tests.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-10 20:03:52 +01:00
Antonio Niño Díaz
4395ed893a Merge pull request #168 from Ben10do/fix-implicit-yyparse
Fix implicit declaration of yyparse()

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-10 19:51:28 +01:00
Ben10do
0d80f60fcc Fix implicit declaration of yyparse()
This was causing compilation errors, as yyparse() hadn’t been defined in lexer.l.
2017-04-10 10:44:31 +01:00
Antonio Niño Díaz
7097b9885e Fix clean target of the Makefile
Two html documentation files weren't cleaned as expected.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-09 22:06:49 +01:00
Antonio Niño Díaz
f2c207cb44 Remove EX instruction
This is leftover code from ASMotor.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-09 21:51:30 +01:00
Antonio Niño Díaz
be50f2d302 Remove unused patch enum element
If the next release is going to break compatibility with older object
file formats it doesn't make sense to keep this.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-09 21:25:20 +01:00
Antonio Niño Díaz
fa767f3228 Merge pull request #161 from AntonioND/an/linkerscript-include
Add support for including files in linkerscript

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-09 17:19:13 +01:00
Antonio Niño Díaz
5cfa15f963 Add equates with ISO 8601 date and time
Added `__TIMESTAMP_ISO_8601_LOCAL__` and `__TIMESTAMP_ISO_8601_UTC__`,
with the correct ISO 8601 representation of time and date from years to
seconds (including local timezone in the local time string).

Also, if the current time cannot be obtained from the OS, it will output
a warning and the time strings will be filled with '?' instead of
numbers and characters.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-09 16:49:34 +01:00
Antonio Niño Díaz
23584a584f Fix __FILE__, __TIME__ and __DATE__
If they don't have quotes when passed to sym_AddString() they can't be
used at all by the assembler. I suppose nobody actually used them, they
seem to have been broken forever.

Added a comment to the function to say how to use it correctly for
strings.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-09 15:40:06 +01:00
Antonio Niño Díaz
53fa608161 Deprecate IMPORT keyword
IMPORT is simply useless, any symbol that isn't found in the current
file is automatically flagged as imported symbol.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:47:10 +01:00
Antonio Niño Díaz
1154a173cc Merge pull request #153 from AntonioND/an/opcode-ref
Add GBZ80 opcode reference man page

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:43:21 +01:00
Antonio Niño Díaz
ca3e55cc45 Update remaining dates in man pages
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:18:59 +01:00
Antonio Niño Díaz
206275df57 Add support for including files in linkerscript
Files can now be included with the following syntax:

    INCLUDE "path.link"

The maximum include depth is 5.

Fixed linkerscript parser and lexer error messages so that they are more
informative (show file and line of the error).

Man page updated.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:10:24 +01:00
Antonio Niño Díaz
3d8396b86f Remove progname variable
The error message shouldn't specify the name of the binary, that's
supposed to be known by the caller.

Update test reference outputs.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:10:14 +01:00
Antonio Niño Díaz
77546e9c58 Make WARN output a warning instead of an error
This is the expected behaviour.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:09:02 +01:00
Antonio Niño Díaz
540f8597d4 Update history in man pages
Fix format in LICENSE file.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:08:57 +01:00
Antonio Niño Díaz
e3109af2f8 Rename OPT_CONTWRAM to OPT_DMG_MODE
Now, it will also make sure that VRAM bank 1 isn't used.

Man page updated.

Tests added.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 18:08:51 +01:00
Antonio Niño Díaz
cf99f33dd6 Fix reference list of hex codes
Fix tabulations.

Add missing byte to STOP.

Add comments about where HL+ and HL- are used.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 17:43:06 +01:00
Antonio Niño Díaz
0b6438ae0a Add GBZ80 opcode reference man page
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-08 17:38:04 +01:00
AntonioND
928b347dfc Merge pull request #158 from Ben10do/remove-legacy-object-files
Remove support for legacy object files
2017-04-08 13:30:15 +01:00
AntonioND
ce21cfad4e Merge pull request #160 from AntonioND/an/high-low
Implement HIGH() and LOW() operators
2017-04-08 13:30:10 +01:00
Antonio Niño Díaz
dda3a066be Add test for HIGH() and LOW()
It compares the results of the operators with the expected result if
doing the same thing manually.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-06 22:40:38 +01:00
Antonio Niño Díaz
a6a47ff66d Implement HIGH() and LOW() operators
They work with the 16-bit registers BC, DE and HL, returning the
corresponding 8-bit register. HIGH() works with AF as well, returning A.

They also work with any kind of constant or symbol, generating a RPN
patch in the object file if the value is not defined at assembly time.

They work with macro arguments as well.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-06 22:40:34 +01:00
Daniel Hauck
bfcef01211 Add DESTDIR to Makefile
Allow separate definition of binary and manpage directory.

Document Makefile changes in README.
2017-04-06 20:47:14 +01:00
AntonioND
07861b3b4a Output warning with deprecated section types
Code that uses keywords HOME, DATA, CODE or BSS generates warnings.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-06 20:30:21 +01:00
AntonioND
24439003f3 Remove newlines from warning message strings
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-06 20:30:21 +01:00
AntonioND
3c43cc14d9 Remove unused code
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-06 20:30:21 +01:00
AntonioND
52081f32f0 Add flag -w to rgbasm to disable warnings
A lot of warnings are being added (and more will come) so it makes sense
to be able to disable them in legacy source that generates warnings but
is otherwise correct.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-06 20:30:21 +01:00
Ben10do
6e5a28226b Include object file version in error message
When an unsupported object file version is encountered, the version number is now printed in the displayed error message.
2017-04-06 08:02:28 +01:00
Antonio Niño Díaz
2783a36b17 Add missing license header to man page
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-06 00:00:56 +01:00
Anthony J. Bentley
2c3afc833f Add license information to manpages. 2017-04-05 23:39:42 +01:00
AntonioND
0f3b708dce Merge pull request #157 from AntonioND/an/error-undef-diff
Output error message if diff of labels not defined
2017-04-05 23:08:37 +01:00
AntonioND
7eb9101d43 Update README and LICENSE files
Add history of RGBDS and original license.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-05 01:24:36 +01:00
Ben10do
032e698f46 Update the object file documentation
Updates the object file documentation in mylink.h to match the newest object file format.
2017-04-05 01:10:00 +01:00
Ben10do
63103c050d Remove support for old object files
Remove support for RGB0 and RGB1-2 object files, reducing the amount of duplicate work that needs doing when maintaining the linker in the future.

A new error message has also been implemented if an unsupported object file version has been encounted, which informs the user that they should reassemble.
2017-04-05 01:09:51 +01:00
AntonioND
7e107ab41a Update references of linker tests
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-04 23:13:42 +01:00
AntonioND
a009a372c5 Remove noyywrap from src/link/lexer.l
Workaround for flex version 2.6.3.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-04 23:13:36 +01:00
AntonioND
5f299bfe6c Fix whitespace
Replace spaces by tabs for consistency. The rest of the codebase uses
tabs, so the linkerscript parser has to change.

Removed trailing tabs in all codebase.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-04 22:14:46 +01:00
AntonioND
07cc4fb8fd Remove warnings when calculating banks
getsymbank() is used for more things than just when the code explicitly
has a BANK() operator, which causes a lot of noise when building code
that has more than one object file and places variables on HRAM or OAM.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-04 21:56:22 +01:00
AntonioND
720ae59af8 Merge pull request #154 from AntonioND/an/tiny-contwram
Make the options -t and -w of rgblink consistent
2017-04-04 21:42:20 +01:00
AntonioND
e63e801e9c Output error message if diff of labels not defined
When calculating the difference of addresses between two labels, for it
to be defined, either:

- Both of them must have their absolute address defined.
- They belong to the same section, so their relative addresses are
  compatible.

This patch adds a check to make sure that any other case is detected so
that the programmer can correct the code.

This applies to rgbasm. The difference of labels can be used, for
example, as argument of DS. The linker can't resize sections, which
means that the final value must be defined when creating the object
file.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-04 21:40:59 +01:00
AntonioND
2abdc9c59d Add whitespace to error and warning messages
Test reference output updated.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 23:46:19 +01:00
AntonioND
be200593d6 Fix typo in README
This is the correct name since 2016.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 23:43:32 +01:00
AntonioND
43228f16f0 Improve README
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 22:17:20 +01:00
AntonioND
f14b061ea7 Add script to update references of rgbasm tests
Update test references.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 21:36:42 +01:00
AntonioND
f431b384a2 Add tests for rgblink options -t and -w
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 21:29:22 +01:00
AntonioND
7e3720b627 Make options -t and -w consistent
Instead of converting from ROMX to ROM0 with -t and preventing the use
of WRAMX at all with -w, make each option prohibit the type of section
they affect.

This is a good idea because it can prevent a developer from making
mistakes when switching from using the options to not using them.
Generally, a change from using one single bank to multiple banks is
something that will take a lot of effort, and forgetting sections in
ROM0 or WRAM0 will only make the free space of those areas to be
reduced (and maybe prevent compilation), but it won't cause any problems
because of a forgotten bank swap in the code.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 21:22:16 +01:00
AntonioND
e9ed81074b Rename OPT_SMALL to OPT_TINY
This way it is easier to identify the flag passed to the binary (-t).

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 21:22:16 +01:00
AntonioND
e16af28676 Automate and improve rgblink test
Check all sections when testing BANK().

Add scripts to verify the tests and update the reference if needed.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 21:19:39 +01:00
AntonioND
25be5c6561 Improve error and warning output
Improve error messages generated by `errx()`, `warnx()` and similar.

Set `progname` to a static string with the name of the program so that
the path of the binary isn't included in error messages.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 21:16:43 +01:00
AntonioND
e4b4e427f1 Return bank 0 for labels in HRAM
Instead of returning the internal representation of the linker, return
0 when using BANK() on a label in HRAM.

Also, generate a warning when calculating the bank of labels in OAM
and HRAM, as there is no valid reason for doing it, so it's likely a
programming mistake.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-03 21:15:14 +01:00
AntonioND
2138bb46fd Fix generation of html man page in Makefile
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 21:08:53 +01:00
AntonioND
ec5eb4f9ff Merge pull request #152 from Ben10do/update-readme-for-mac
Update the README’s Mac-specific instructions
2017-04-02 18:08:47 +01:00
Ben10do
b31632b51d Update the README’s Mac-specific instructions
- Rename the “Installing RGBDS (UNIX)” section to “Building RGBDS”, as that’s what we’re doing, regardless of platform.
- Update references of Mac OS X to macOS.
- State that only libpng and pkg-config need to be downloaded with Homebrew; the others are pre-installed along with Xcode.
- State that RGBDS itself is available through Homebrew.
2017-04-02 17:57:51 +01:00
AntonioND
e50e3e5a23 Remove trailing whitespace
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 17:46:14 +01:00
AntonioND
f63339472e Update reference output of tests
Due to recent changes, lots of tests generated a slightly different
error output.

- bank-noexist : This test doesn't generate any error output now as
  unknown labels are left for the linker to resolve.

- null-in-macro : This test used to crash. Now, the parser verifies that
  a MACRO ends in ENDM, generating an error message if not.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 17:18:08 +01:00
AntonioND
43fd1ee024 Fix some signed/unsigned comparison warnings
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 17:08:12 +01:00
AntonioND
d61a0a8a8f Cleanup Makefile
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 17:07:40 +01:00
AntonioND
ec44b554e8 Merge pull request #150 from Ben10do/deprecation-positions
Add a warning() function, similiar to other error handlers
2017-04-02 17:03:03 +01:00
AntonioND
01a710a47d Remove Zero Page linker patch RPN_PCEZP
This patch isn't used because it's meant to be an optimization for
labels in the memory region 0x2000-0x20FF. That memory region doesn't
have anything special on the Game Boy, and there are no instructions
optimized to read or write from there, so it was probably meant for
another hardware that was supported by ASMotor in the past.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 16:19:45 +01:00
Ben10do
ff2ba7290c Add a warning() function, similiar to yyerror()
This function produces a similar output to the other error handlers, including printing to stderr, and including a stack trace. However, ‘warning’ is displayed instead of ‘ERROR’, and the compilation does not fail.

This function is now used for the deprecation warnings, ensuring that these errors can be found.
2017-04-02 13:18:29 +01:00
AntonioND
53842cd07d Create man5 folder when installing
`make install` would blindly try to copy `rgblink.5` even if the
destination folder didn't exist.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 00:40:35 +01:00
AntonioND
85ff75d2d3 Merge pull request #146 from AntonioND/an/same-name
Prohibit sections from having the same name
2017-04-02 00:36:28 +01:00
AntonioND
adef2e18cc Fix bank assignments from linkerscript
Even though the bank number was read from the linkerscript and the
linker verified that each section could be mapped in the final rom, the
bank number was never actually set by the linkerscript parser.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-02 00:22:37 +01:00
AntonioND
5ba8405dfa Prohibit sections from having the same name
To make the behaviour of the linkerscript consistent, every section read
from an object file must have an unique name. This is needed as the
linkerscript uses the name of sections to place them and it expects
every section to have a different name.

This doesn't break compatibility with the old behaviour that allowed to
continue sections if they had the same name, bank number and starting
address. That's still allowed because `rgbasm` outputs a single section
if this functionality is used, it is transparent to `rgblink`.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-04-01 15:33:17 +01:00
AntonioND
f0d4750ebc Fix rgblink.5 man page installation path
The man page rgblink.5 was installed in the `man1` folder instead of
`man5` as expected.
2017-04-01 15:06:26 +01:00
AntonioND
eed098ac8e Merge pull request #140 from AntonioND/an/linkerscript
Implement linkerscript
2017-04-01 10:33:49 +01:00
AntonioND
64dbcc0912 Update README.md
Inform about the actual dependencies.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-28 22:19:50 +01:00
AntonioND
5947ca10dc Document linkerscript format in manpage
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-28 22:19:50 +01:00
AntonioND
d1ed4fbded Use linkerscript parser in rgblink
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-28 22:19:50 +01:00
AntonioND
22d4a10cb6 Implement linkerscript parser
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-28 22:19:45 +01:00
AntonioND
dfb99618f5 Document missing build options
Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-28 19:37:18 +01:00
AntonioND
6b21e02c95 Merge pull request #143 from Sanqui/parametrize-makefile
Parametrize install arguments in Makefile
2017-03-28 12:49:23 +01:00
Sanqui
011c2c953b Parametrize install arguments in Makefile 2017-03-28 13:22:33 +02:00
AntonioND
8eb1a42e31 Merge pull request #141 from AntonioND/an/deprecate-jp-hl
Declare some opcodes obsolete
2017-03-24 23:23:43 +00:00
AntonioND
c51aac0c20 Declare some opcodes obsolete
They are still working, they just output a warning.

`jp [hl]` is confusing as it may be thought that the CPU reads the value
pointed by hl and jumps to it.

`ldi a,hl` and `ldd a,hl` are also confusing as they load from the
address pointed by `hl`, the correct mnemonic should say `[hl]`.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-24 23:22:30 +00:00
AntonioND
6feaba2343 Document -w option of rgblink
This option hadn't been added to the manpage.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-23 22:12:06 +00:00
AntonioND
0867476bde Allow ',' to be escaped in string literals
It should only be needed for macro arguments, added to string parsing
function as well for consistency.
2017-03-19 00:05:50 +00:00
AntonioND
fa962b9470 Merge pull request #139 from chastai/escape-cb
Allow { and } to be escaped in string literals
2017-03-18 23:54:59 +00:00
Christophe Staïesse
b8642bf3af Allow { and } to be escaped in string literals
As stated in the documentation but that was not actually implemented.
2017-03-18 16:23:41 +01:00
AntonioND
317b206fa8 Improve map file output
Print the name of each section along with the size, base and end
addresses. If a section is empty, don't print the end address, as it
can overflow if the base address is 0.

Signed-off-by: AntonioND <antonio_nd@outlook.com>
2017-03-15 23:52:56 +00:00
AntonioND
469e3e7c86 Merge branch 'contiguous-wram' of git://github.com/TwitchPlaysPokemon/rgbds into TwitchPlaysPokemon-contiguous-wram 2017-03-15 21:00:06 +00:00
AntonioND
9193710ff9 Merge pull request #131 from Sanqui/overlay
Add overlay to rgblink
2017-03-15 20:42:32 +00:00
Sanqui
263c9222ab Require all sections to be fixed when using overlay 2017-03-13 17:08:27 +01:00
AntonioND
947d767c64 Merge pull request #135 from Ben10do/improve-assign-error-messages
Improve assignment error messages
2017-03-12 17:06:54 +00:00
AntonioND
82cf3eb48f Merge pull request #134 from Ben10do/oam-sections
Add support for OAM Sections
2017-03-11 12:18:40 +00:00
Ben10do
a75c15ec46 Improve assignment error messages
Make the error messages in assign.c more descriptive, including the name of the section that caused the error, and its alignment.
2017-03-10 23:21:59 +00:00
Ben10do
3dcfe2b9f6 Add support for OAM Sections
Allows sections (and labels within) to be defined that correspond to the Game Boy’s Object Attributes Memory.
2017-03-10 22:18:14 +00:00
Ben10do
523b7538f0 Replace magic numbers with BANK_COUNT_* constants
Previously, some instances of the number of banks for each section remained hardcoded. These have been replaced with BANK_COUNT_* constants.

As a side-effect, this could fix a theoretical bug when using BANK(label) when the label is in a high SRAM bank (≥ 4).
2017-03-10 19:24:54 +00:00
Sanqui
bc2f885d29 Also require ROM0 sections to be fixed when using overlay 2017-03-02 23:02:56 +01:00
Sanqui
bd00b9ab59 Merge branch 'master' of github.com:rednex/rgbds into overlay 2017-03-02 22:46:19 +01:00
AntonioND
4f86a12539 Merge pull request #125 from Ben10do/section-alignment
Implement byte alignment for data
2017-03-02 09:17:46 +00:00
Ben
7e2457c9be Re-allow alignment of 0 bits 2017-03-02 08:29:28 +00:00
Ben10do
7993d3455d Update alignment error handling
Ensure (in rgbasm) that the alignment value is between 1-16. Replaces the previous “alignment must not be negative” check.
2017-03-02 08:02:05 +00:00
Sanqui
c9daf80f11 Merge github.com:rednex/rgbds into overlay 2017-02-28 18:58:58 +01:00
Sanqui
5a7faa7dff Add overlay to rgblink manpage 2017-02-28 18:48:09 +01:00
Ben10do
1ab93a194e Implement ALIGN keyword in rgbasm
The ALIGN keyword specifies the number of bits that should be zero at the start of a section. It works in a simliar fashion to BANK.
2017-02-23 15:00:57 +00:00
Ben10do
1b05c43b97 Implement byte alignment in section assingment
Yay, more refactoring of the section assignment… This version of the linker will allocate sections by their alignment, and then by their size (largest first, in both cases).

In future, this may be improved by using dense packing (as suggested by #83).
2017-02-19 22:43:45 +00:00
Ben10do
e4cbf773f6 Add alignment of sections to objects
Aligned sections can now be created with out_NewAlignedSection(). This information is stored in created object files, and read by the linker.

The names of each section are also included in the object file, enabling potential improvements to error messages in the future.
2017-02-19 22:35:32 +00:00
Ben10do
b07c04cd74 Implement a malloc-based readasciiz()
Instead of reading into a pre-sized buffer, this function now uses malloc to create a buffer, and resizes it if necessary.

This reduces the risk of memory issues if a long string (< 255 chars) was encountered.
2017-02-19 22:20:21 +00:00
scnorton
6d1c60b0a6 Contiguous WRAM 2017-02-06 16:31:57 -05:00
Sanqui
280ca83acd Fix opening nonexistent overlay files 2016-03-28 20:47:47 +02:00
Sanqui
2e9c68f8c3 Add overlay file option to rgblink (-O)
This option takes a file and places fixed sections on top of it.
Should prove useful for patches and partial disassemblies.
2016-03-28 01:02:05 +02:00
81 changed files with 5471 additions and 1110 deletions

13
.travis-deps.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/sh
if [ $TRAVIS_OS_NAME = "osx" ]; then
brew update
brew install libpng pkg-config
else # linux
sudo apt-get -qq update
sudo apt-get install -y -q bison flex libpng-dev pkg-config
fi
echo "Dependencies:"
yacc --version
flex --version

16
.travis.yml Normal file
View File

@@ -0,0 +1,16 @@
language: c
sudo: required
install:
- ./.travis-deps.sh
os:
- linux
- osx
compiler:
- clang
- gcc
script:
- make
- sudo make install
after_success:
- pushd test/asm/ && ./test.sh && popd
- pushd test/link/ && ./test.sh && popd

34
LICENSE
View File

@@ -1,34 +0,0 @@
rgbasm and rgblink are derived from Justin Lloyd's RGBDS, which is
released under the following license:
DO WHATEVER PUBLIC LICENSE*
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You can do whatever you want to with the work.
1. You cannot stop anybody from doing whatever they want to with the work.
2. You cannot revoke anybody elses DO WHATEVER PUBLIC LICENSE in the work.
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the DO WHATEVER PUBLIC LICENSE
Software originally created by Justin Lloyd @ http://otakunozoku.com/
rgbfix was rewritten from scratch by Anthony J. Bentley, and is released
under the ISC license; see the source file for the text of the license.
rgbgfx was written by stag019, and is released under the ISC license.
The UTF-8 decoder in src/asm/charmap.c was written by Björn Höhrmann and is
released under the MIT license. The remainder of charmap.c was written by
stag019, and is released under the ISC license.
extern/err.c is derived from the Musl C library, http://www.musl-libc.org,
and is released under the MIT license.
extern/reallocarray.c is derived from the OpenBSD Project,
http://www.openbsd.org, and is released under the ISC license.
extern/strl.c is derived from the OpenBSD Project, http://www.openbsd.org,
and is released under the BSD license.

74
LICENSE.md Normal file
View File

@@ -0,0 +1,74 @@
# Original code
Copyright (C) 1997 Carsten Sorensen <surfsmurf@matilde.demon.co.uk>
The ASMotor package (xAsm, xLink, RGBFix, examples and documentation) is
freeware and distributed as is. The author retains his copyright and right to
modify the specifications and operation of the software without notice.
In other words this means I encourage you to...
- use it for whatever purpose even professional work without me charging you a
penny
- copy it to another person (wholly or in part, though I'm sure he'd appreciate
the whole package) in whatever form you find suitable
- mass-distribute the ASMotor package if it is complete (xAsm, xLink, RGBFix and
documentation).
- contact me if you have any problems
This also means you can't...
- blame me for loss of profit, data, sleep, food or other nasty things through
the use or distribution of ASMotor. If you choose to use ASMotor you do so at
your own risk.
- expect me to be able to help you should you have a problem related or not to
ASMotor.
# Otaku no Zoku's modifications
Copyright (C) 1999 Justin Lloyd <jlloyd@imf.la> (?)
```
DO WHATEVER PUBLIC LICENSE*
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You can do whatever you want to with the work.
1. You cannot stop anybody from doing whatever they want to with the work.
2. You cannot revoke anybody elses DO WHATEVER PUBLIC LICENSE in the work.
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the DO WHATEVER PUBLIC LICENSE
Software originally created by Justin Lloyd @ http://otakunozoku.com/
```
# rgbds-linux
Copyright (C) 2009 Vegard Nossum <vegard.nossum@gmail.com>
# Current
rgbasm and rgblink are derived from Justin Lloyd's RGBDS.
rgbfix was rewritten from scratch by Anthony J. Bentley, and is released
under the ISC license; see the source file for the text of the license.
rgbgfx was written by stag019, and is released under the ISC license.
Some files of rgblink were written by Antonio Niño Díaz, and they are relased
under the ISC license. The affected files have the appropriate license in the
header of the file.
The UTF-8 decoder in src/asm/charmap.c was written by Björn Höhrmann and is
released under the MIT license. The remainder of charmap.c was written by
stag019, and is released under the ISC license.
extern/err.c is derived from the Musl C library, http://www.musl-libc.org,
and is released under the MIT license.
extern/reallocarray.c is derived from the OpenBSD Project,
http://www.openbsd.org, and is released under the ISC license.
extern/strl.c is derived from the OpenBSD Project, http://www.openbsd.org,
and is released under the BSD license.

121
Makefile
View File

@@ -1,14 +1,23 @@
PKG_CONFIG = pkg-config
WARNFLAGS = -Wall -Werror=implicit
PNGFLAGS != ${PKG_CONFIG} --cflags libpng
REALCFLAGS = ${CFLAGS} ${WARNFLAGS} ${PNGFLAGS} -Iinclude -g \
PKG_CONFIG = pkg-config
WARNFLAGS = -Wall -Werror
PNGFLAGS != ${PKG_CONFIG} --cflags libpng
REALCFLAGS = ${CFLAGS} ${WARNFLAGS} ${PNGFLAGS} -Iinclude -g \
-std=c99 -D_POSIX_C_SOURCE=200809L
LFLAGS := --nounistd
YACC := yacc
FLEX := flex
RM := rm -rf
# User-defined variables
PREFIX = /usr/local
BINPREFIX = ${PREFIX}/bin
MANPREFIX = ${PREFIX}/man
Q = @
PREFIX = /usr/local
bindir = ${PREFIX}/bin
mandir = ${PREFIX}/man
Q = @
STRIP = -s
BINMODE = 555
MANMODE = 444
rgbasm_obj = \
src/asm/asmy.o \
@@ -29,12 +38,15 @@ rgbasm_obj = \
rgblink_obj = \
src/link/assign.o \
src/link/lexer.o \
src/link/library.o \
src/link/main.o \
src/link/mapfile.o \
src/link/object.o \
src/link/output.o \
src/link/patch.o \
src/link/parser.o \
src/link/script.o \
src/link/symbol.o \
src/extern/err.o
@@ -51,25 +63,30 @@ rgbgfx_obj = \
all: rgbasm rgblink rgbfix rgbgfx
clean:
$Qrm -rf rgbds.html
$Qrm -rf rgbasm rgbasm.exe ${rgbasm_obj} rgbasm.html
$Qrm -rf rgblink rgblink.exe ${rgblink_obj} rgblink.html
$Qrm -rf rgbfix rgbfix.exe ${rgbfix_obj} rgbfix.html
$Qrm -rf rgbgfx rgbgfx.exe ${rgbgfx_obj} rgbgfx.html
$Qrm -rf src/asm/asmy.c src/asm/asmy.h
$Q${RM} rgbds.7.html gbz80.7.html rgbds.5.html
$Q${RM} rgbasm rgbasm.exe ${rgbasm_obj} rgbasm.1.html rgbasm.5.html
$Q${RM} rgblink rgblink.exe ${rgblink_obj} rgblink.1.html rgblink.5.html
$Q${RM} rgbfix rgbfix.exe ${rgbfix_obj} rgbfix.1.html
$Q${RM} rgbgfx rgbgfx.exe ${rgbgfx_obj} rgbgfx.1.html
$Q${RM} src/asm/asmy.c src/asm/asmy.h
$Q${RM} src/link/lexer.c src/link/parser.c src/link/parser.h
install: all
$Qmkdir -p ${BINPREFIX}
$Qinstall -s -m 555 rgbasm ${BINPREFIX}/rgbasm
$Qinstall -s -m 555 rgbfix ${BINPREFIX}/rgbfix
$Qinstall -s -m 555 rgblink ${BINPREFIX}/rgblink
$Qinstall -s -m 555 rgbgfx ${BINPREFIX}/rgbgfx
$Qmkdir -p ${MANPREFIX}/man1 ${MANPREFIX}/man7
$Qinstall -m 444 src/rgbds.7 ${MANPREFIX}/man7/rgbds.7
$Qinstall -m 444 src/asm/rgbasm.1 ${MANPREFIX}/man1/rgbasm.1
$Qinstall -m 444 src/fix/rgbfix.1 ${MANPREFIX}/man1/rgbfix.1
$Qinstall -m 444 src/link/rgblink.1 ${MANPREFIX}/man1/rgblink.1
$Qinstall -m 444 src/gfx/rgbgfx.1 ${MANPREFIX}/man1/rgbgfx.1
$Qmkdir -p ${DESTDIR}${bindir}
$Qinstall ${STRIP} -m ${BINMODE} rgbasm ${DESTDIR}${bindir}/rgbasm
$Qinstall ${STRIP} -m ${BINMODE} rgbfix ${DESTDIR}${bindir}/rgbfix
$Qinstall ${STRIP} -m ${BINMODE} rgblink ${DESTDIR}${bindir}/rgblink
$Qinstall ${STRIP} -m ${BINMODE} rgbgfx ${DESTDIR}${bindir}/rgbgfx
$Qmkdir -p ${DESTDIR}${mandir}/man1 ${DESTDIR}${mandir}/man5 ${DESTDIR}${mandir}/man7
$Qinstall -m ${MANMODE} src/rgbds.7 ${DESTDIR}${mandir}/man7/rgbds.7
$Qinstall -m ${MANMODE} src/gbz80.7 ${DESTDIR}${mandir}/man7/gbz80.7
$Qinstall -m ${MANMODE} src/rgbds.5 ${DESTDIR}${mandir}/man7/rgbds.5
$Qinstall -m ${MANMODE} src/asm/rgbasm.1 ${DESTDIR}${mandir}/man1/rgbasm.1
$Qinstall -m ${MANMODE} src/asm/rgbasm.5 ${DESTDIR}${mandir}/man1/rgbasm.5
$Qinstall -m ${MANMODE} src/fix/rgbfix.1 ${DESTDIR}${mandir}/man1/rgbfix.1
$Qinstall -m ${MANMODE} src/link/rgblink.1 ${DESTDIR}${mandir}/man1/rgblink.1
$Qinstall -m ${MANMODE} src/link/rgblink.5 ${DESTDIR}${mandir}/man5/rgblink.5
$Qinstall -m ${MANMODE} src/gfx/rgbgfx.1 ${DESTDIR}${mandir}/man1/rgbgfx.1
rgbasm: ${rgbasm_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgbasm_obj} -lm
@@ -86,37 +103,55 @@ rgbgfx: ${rgbgfx_obj}
.y.c:
$Q${YACC} -d ${YFLAGS} -o $@ $<
.l.o:
$Q${RM} $*.c
$Q${FLEX} ${LFLAGS} -o $*.c $<
$Q${CC} ${REALCFLAGS} -c -o $@ $*.c
$Q${RM} $*.c
.c.o:
$Q${CC} ${REALCFLAGS} -c -o $@ $<
src/asm/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h
src/asm/asmy.h: src/asm/asmy.c
src/link/lexer.o : src/link/parser.h
src/link/parser.h : src/link/parser.c
# Below is a target for the project maintainer to easily create win32 exes.
# This is not for Windows users!
# If you're building on Windows with Cygwin or Mingw, just follow the Unix
# install instructions instead.
mingw:
$Qenv PATH=/usr/local/mingw32/bin:/bin:/usr/bin:/usr/local/bin \
make WARNFLAGS= CC=gcc CFLAGS="-I/usr/local/mingw32/include \
${CFLAGS}"
$Qmv rgbasm rgbasm.exe
$Qmv rgblink rgblink.exe
$Qmv rgbfix rgbfix.exe
$Qmv rgbgfx rgbgfx.exe
$Q${RM} win32 win64
$Qmkdir win32 win64
$Qenv make clean
$Qenv PKG_CONFIG_PATH=/usr/i686-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=i686-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm win32/rgbasm.exe
$Qmv rgblink win32/rgblink.exe
$Qmv rgbfix win32/rgbfix.exe
$Qmv rgbgfx win32/rgbgfx.exe
$Qenv make clean
$Qenv PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=x86_64-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm win64/rgbasm.exe
$Qmv rgblink win64/rgblink.exe
$Qmv rgbfix win64/rgbfix.exe
$Qmv rgbgfx win64/rgbgfx.exe
$Qenv make clean
# Below is a target for the project maintainer to easily create web manuals.
# It relies on mandoc: http://mdocml.bsd.lv
MANDOC = -Thtml -Ios=General -Oman=/rgbds/manual/%N/ \
-Ostyle=/rgbds/manual/manual.css
MANDOC = -Thtml -Ios=General -Oman=%N.%S.html -Ostyle=manual.css
wwwman:
$Qmandoc ${MANDOC} src/rgbds.7 | sed s/OpenBSD/General/ > rgbds.html
$Qmandoc ${MANDOC} src/asm/rgbasm.1 | sed s/OpenBSD/General/ > \
rgbasm.html
$Qmandoc ${MANDOC} src/fix/rgbfix.1 | sed s/OpenBSD/General/ > \
rgbfix.html
$Qmandoc ${MANDOC} src/link/rgblink.1 | sed s/OpenBSD/General/ > \
rgblink.html
$Qmandoc ${MANDOC} src/gfx/rgbgfx.1 | sed s/OpenBSD/General/ > \
rgbgfx.html
$Qmandoc ${MANDOC} src/rgbds.7 > rgbds.7.html
$Qmandoc ${MANDOC} src/gbz80.7 > gbz80.7.html
$Qmandoc ${MANDOC} src/rgbds.5 > rgbds.5.html
$Qmandoc ${MANDOC} src/asm/rgbasm.1 > rgbasm.1.html
$Qmandoc ${MANDOC} src/asm/rgbasm.5 > rgbasm.5.html
$Qmandoc ${MANDOC} src/fix/rgbfix.1 > rgbfix.1.html
$Qmandoc ${MANDOC} src/link/rgblink.1 > rgblink.1.html
$Qmandoc ${MANDOC} src/link/rgblink.5 > rgblink.5.html
$Qmandoc ${MANDOC} src/gfx/rgbgfx.1 > rgbgfx.1.html

142
README.md
View File

@@ -8,63 +8,151 @@ for the Game Boy and Game Boy Color. It consists of:
- rgbfix (checksum/header fixer)
- rgbgfx (PNGtoGame Boy graphics converter)
rgbds-linux is a fork of the original RGBDS which aims to make the programs
more like other UNIX tools.
This is a fork of the original RGBDS which aims to make the programs more like
other UNIX tools.
This toolchain is maintained on [GitHub](https://github.com/rednex/rgbds), as
well as its [documentation](https://github.com/rednex/rednex.github.io).
The documentation of this toolchain can be viewed online
[here](https://rednex.github.io/), it is generated from the man pages found in
this repository.
## 1. Installing RGBDS
### 1.1 Windows
Windows builds are available in the releases page on GitHub:
https://github.com/rednex/rgbds/releases
Copy the `.exe` files to `C:\Windows\` or similar.
If you require the latest version in development, it should be possible to
compile RGBDS with MinGW or Cygwin by following the instructions to build it
on UNIX systems.
### 1.2 macOS
You can build RGBDS by following the instructions below. However, if you would
prefer not to build RGBDS yourself, you may also install it using
[Homebrew](http://brew.sh/).
To install the latest release, use:
```sh
brew install rgbds
```
To install RGBDS with all of the current changes in development (as seen on the
`master` branch on GitHub), use:
```sh
brew install rgbds --HEAD
```
### 1.3 Other UNIX-like systems
No official binaries of RGBDS are distributed for these systems, you must follow
the simple instructions below to compile and install it.
## Installing RGBDS (UNIX)
## 2. Building RGBDS from source
RGBDS requires libpng and pkg-config to be installed.
RGBDS can be built in UNIX-like systems by following the instructions below.
On Mac OS X, install them with [Homebrew](http://brew.sh/). On other Unixes,
use the built-in package manager.
### 2.1 Dependencies
You can test if they're installed by running `pkg-config --cflags libpng`:
if the output is a path, then you're good, and if it outputs an error then
you need to install them via a package manager.
RGBDS requires yacc, flex, libpng and pkg-config to be installed.
To build the programs on a UNIX or UNIX-like system, just run in your terminal:
On macOS, install the latter two with [Homebrew](http://brew.sh/):
```sh
brew install libpng pkg-config
```
On other Unixes, use the built-in package manager. For example, on Debian or
Ubuntu:
```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:
```sh
make
```
Then to install the compiled programs and manual pages, run (with appropriate
privileges):
Then, to install the compiled programs and manual pages, run (with appropriate
privileges, e.g, with `sudo`):
```sh
make install
```
After installation, you can read the manuals with the man(1) command. E.g.,
After installation, you can read the manuals with the `man` command. E.g.,
```sh
man 1 rgbasm
man 7 rgbds
```
Note: the variables described below can affect installation behavior when given
on the make command line. For example, to install rgbds in your home directory
instead of systemwide, run the following:
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:
```sh
mkdir -p $HOME/{bin,man/man1,man/man7}
make install PREFIX=$HOME
```
`PREFIX`: Location where RGBDS will be installed. Defaults to /usr/local.
To do a verbose build, run:
`BINPREFIX`: Location where the RGBDS programs will be installed. Defaults
to ${PREFIX}/bin.
```sh
make Q=
```
`MANPREFIX`: Location where the RGBDS man pages will be installed. Defaults
to ${PREFIX}/man.
This is the complete list of user-defined variables:
`Q`: Whether to quiet the build or not. To make the build more verbose, clear
this variable. Defaults to @.
- `PREFIX`: Location where RGBDS will be installed. Defaults to `/usr/local`.
- `bindir`: Location where the binaries will be installed. Defaults to `${PREFIX}/bin`.
## Installing RGBDS (Windows)
- `mandir`: Location where the manpages will be installed. Defaults to `${PREFIX}/man`.
Windows builds are available here: https://github.com/bentley/rgbds/releases
- `DESTDIR`: This is prepended to all paths during the installation. It is
mainly used for packaging.
Copy the .exe files to C:\Windows\ or similar.
- `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`.
## 3 History
- Around 1997, Carsten Sorensen (AKA SurfSmurf) writes ASMotor as a
general-purpose assembler/linker system for DOS/Win32
- Around 1999, Justin Lloyd (AKA Otaku no Zoku) adapts ASMotor to read and
produce GBZ80 assembly/machine code, and releases this version as RGBDS.
- 2009, Vegard Nossum adapts the code to be more UNIX-like and releases this
version as rgbds-linux on [GitHub](https://github.com/vegard/rgbds-linux).
- 2010, Anthony J. Bentley forks that repository. The fork becomes the reference
implementation of rgbds.
- 2017, Bentley's repository is moved to a neutral name.

View File

@@ -4,80 +4,79 @@
n = 8-bit
nn = 16-bit
*ADC A,n : 0xCE
*ADC A,r : 0x88|r
*ADD A,n : 0xC6
*ADD A,r : 0x80|r
*ADD HL,ss : 0x09|(ss<<4)
*ADD SP,n : 0xE8
*AND A,n : 0xE6
*AND A,r : 0xA0|r
*BIT n3,r : 0xCB 0x40|(n3<<3)|r
*CALL cc,nn : 0xC4|(cc<<3)
*CALL nn : 0xCD
*CCF : 0x3F
*CP A,n : 0xFE
*CP A,r : 0xB8|r
*CPL : 0x2F
*DAA : 0x27
*DEC r : 0x05|(r<<3)
*DEC ss : 0x0B|(ss<<4)
*DI : 0xF3
*EI : 0xFB
*EX HL,(SP) : 0xE3
*HALT : 0x76
*INC r : 0x04|(r<<3)
*INC ss : 0x03|(ss<<4)
*JP (HL) : 0xE9
*JP cc,nn : 0xC2|(cc<<3)
*JP nn : 0xC3|(cc<<3)
*JR n : 0x18
*JR cc,n : 0x20|(cc<<3)
*LD (nn),SP : 0x08
*LD ($FF00+C),A : 0xE2
*LD ($FF00+n),A : 0xE0
*LD (nn),A : 0xEA
*LD (rr),A : 0x02|(rr<<4)
*LD A,($FF00+C) : 0xF2
*LD A,($FF00+n) : 0xF0
*LD A,(nn) : 0xFA
*LD A,(rr) : 0x0A|(rr<<4)
*LD HL,(SP+n) : 0xF8
*LD SP,HL : 0xF9
*LD r,n : 0x06|(r<<3)
*LD r,r' : 0x40|(r<<3)|r' // NOTE: LD (HL),(HL) not allowed
*LD ss,nn : 0x01|(ss<<4)
*NOP : 0x00
*OR A,n : 0xF6
*OR A,r : 0xB0|r
*POP tt : 0xC1|(tt<<4)
*PUSH tt : 0xC5|(tt<<4)
*RES n3,r : 0xCB 0x80|(n3<<3)|r
*RET : 0xC9
*RET cc : 0xC0|(cc<<3)
*RETI : 0xD9
*RL r : 0xCB 0x10|r
*RLA : 0x17
*RLC r : 0xCB 0x00|r
*RLCA : 0x07
*RR r : 0xCB 0x18|r
*RRA : 0x1F
*RRC r : 0xCB 0x08|r
*RRCA : 0x0F
*RST n : 0xC7|n
*SBC A,n : 0xDE
*SBC A,r : 0x98|r
*SCF : 0x37
*SET n3,r : 0xCB 0xC0|(n8<<3)|r
*SLA r : 0xCB 0x20|r
*SRA r : 0xCB 0x28|r
*SRL r : 0xCB 0x38|r
*STOP : 0x10
*SUB A,n : 0xD6
*SUB A,r : 0x90|r
*SWAP r : 0xCB 0x30|r
*XOR A,n : 0xEE
*XOR A,r : 0xA8|r
* 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
*/

View File

@@ -11,6 +11,7 @@ struct sOptions {
bool verbose;
bool haltnop;
bool exportall;
bool warnings; /* true to enable warnings, false to disable them. */
//-1 == random
};
@@ -27,6 +28,7 @@ extern void opt_Parse(char *s);
noreturn void fatalerror(const char *fmt, ...);
void yyerror(const char *fmt, ...);
void warning(const char *fmt, ...);
#define YY_FATAL_ERROR fatalerror

View File

@@ -1,60 +1,6 @@
#ifndef RGBDS_ASM_LINK_H
#define RGBDS_ASM_LINK_H
/* RGB0 .obj format:
*
* Header
* Symbols
* Sections
*
* Header:
* "RGB0"
* LONG NumberOfSymbols
* LONG NumberOfSections
*
* Symbols:
* Symbol[NumberOfSymbols]
*
* Symbol:
* char Name (NULL terminated)
* char nType
* if( nType!=SYM_IMPORT )
* {
* LONG SectionID
* LONG Offset
* }
*
* Sections:
* Section[NumberOfSections]
*
* Section:
* LONG SizeInBytes
* char Type
* if( Type!=WRAM0 )
* {
* char Data[SizeInBytes]
* Patches
* }
*
* Patches:
* LONG NumberOfPatches
* Patch[NumberOfPatches]
*
* Patch:
* char Filename NULL-terminated
* LONG LineNo
* LONG Offset
* char Type
* LONG RpnByteSize
* Rpn[RpnByteSize]
*
* Rpn:
* Operators: 0x00-0x7F
* Constants: 0x80 0x00000000
* Symbols : 0x81 0x00000000
*
*/
enum {
RPN_ADD = 0,
RPN_SUB,
@@ -86,10 +32,6 @@ enum {
RPN_HRAM,
RPN_PCEZP,
RPN_RANGECHECK,
RPN_CONST = 0x80,
RPN_SYM = 0x81
};
@@ -101,7 +43,8 @@ enum {
SECT_ROM0,
SECT_HRAM,
SECT_WRAMX,
SECT_SRAM
SECT_SRAM,
SECT_OAM
};
enum {
@@ -113,8 +56,6 @@ enum {
enum {
PATCH_BYTE = 0,
PATCH_WORD_L,
PATCH_LONG_L,
PATCH_WORD_B,
PATCH_LONG_B
PATCH_LONG_L
};
#endif

View File

@@ -10,6 +10,7 @@ struct Section {
ULONG nPC;
ULONG nOrg;
ULONG nBank;
ULONG nAlign;
struct Section *pNext;
struct Patch *pPatches;
struct Charmap *charmap;
@@ -20,6 +21,7 @@ void out_PrepPass2(void);
void out_SetFileName(char *s);
void out_NewSection(char *pzName, ULONG secttype);
void out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank);
void out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank);
void out_AbsByte(int b);
void out_AbsByteGroup(char *s, int length);
void out_RelByte(struct Expression * expr);

View File

@@ -15,68 +15,67 @@ ULONG rpn_isPCRelative(struct Expression * expr);
void rpn_Symbol(struct Expression * expr, char *tzSym);
void rpn_Number(struct Expression * expr, ULONG i);
void rpn_LOGNOT(struct Expression * expr, struct Expression * src1);
void
void
rpn_LOGOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_LOGAND(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_LOGGT(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_LOGLT(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_LOGGE(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_LOGLE(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_LOGNE(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_ADD(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_SUB(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_XOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_OR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_AND(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_SHL(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_SHR(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_MUL(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_DIV(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void
void
rpn_MOD(struct Expression * expr, struct Expression * src1,
struct Expression * src2);
void rpn_HIGH(struct Expression * expr, struct Expression * src);
void rpn_LOW(struct Expression * expr, struct Expression * src);
void rpn_UNNEG(struct Expression * expr, struct Expression * src);
void rpn_UNNOT(struct Expression * expr, struct Expression * src);
UWORD rpn_PopByte(struct Expression * expr);
void rpn_Bank(struct Expression * expr, char *tzSym);
void rpn_Reset(struct Expression * expr);
int
rpn_RangeCheck(struct Expression * expr, struct Expression * src, SLONG low,
SLONG high);
void rpn_CheckHRAM(struct Expression * expr, struct Expression * src1);
#endif

View File

@@ -54,7 +54,6 @@ void sym_AddEqu(char *tzSym, SLONG value);
void sym_AddSet(char *tzSym, SLONG value);
void sym_Init(void);
ULONG sym_GetConstantValue(char *s);
void sym_Import(char *tzSym);
ULONG sym_isConstant(char *s);
struct sSymbol *sym_FindSymbol(char *tzName);
void sym_Global(char *tzSym);
@@ -71,5 +70,6 @@ ULONG sym_GetDefinedValue(char *s);
ULONG sym_isDefined(char *tzName);
void sym_Purge(char *tzName);
ULONG sym_isConstDefined(char *tzName);
int sym_IsRelocDiffDefined(char *tzSym1, char *tzSym2);
#endif

View File

@@ -12,5 +12,5 @@
#define noreturn _declspec( noreturn)
#else
/* unsupported, but no need to throw a fit */
#define noreturn
#define noreturn
#endif

View File

@@ -1,30 +1,33 @@
#ifndef RGBDS_LINK_ASSIGN_H
#define RGBDS_LINK_ASSIGN_H
#include "mylink.h"
#include "types.h"
enum eBankDefine {
BANK_ROM0 = 0,
BANK_ROMX,
BANK_WRAM0 = 512,
BANK_WRAMX,
BANK_VRAM = 520,
BANK_HRAM = 522,
BANK_SRAM = 523
};
enum eBankCount {
BANK_COUNT_ROM0 = 1,
BANK_COUNT_ROMX = 511,
BANK_COUNT_WRAM0 = 1,
BANK_COUNT_WRAMX = 7,
BANK_COUNT_VRAM = 2,
BANK_COUNT_OAM = 1,
BANK_COUNT_HRAM = 1,
BANK_COUNT_SRAM = 16
};
enum eBankDefine {
BANK_ROM0 = 0,
BANK_ROMX = BANK_ROM0 + BANK_COUNT_ROM0,
BANK_WRAM0 = BANK_ROMX + BANK_COUNT_ROMX,
BANK_WRAMX = BANK_WRAM0 + BANK_COUNT_WRAM0,
BANK_VRAM = BANK_WRAMX + BANK_COUNT_WRAMX,
BANK_OAM = BANK_VRAM + BANK_COUNT_VRAM,
BANK_HRAM = BANK_OAM + BANK_COUNT_OAM,
BANK_SRAM = BANK_HRAM + BANK_COUNT_HRAM
};
#define MAXBANKS (BANK_COUNT_ROM0 + BANK_COUNT_ROMX + BANK_COUNT_WRAM0 + BANK_COUNT_WRAMX \
+ BANK_COUNT_VRAM + BANK_COUNT_HRAM + BANK_COUNT_SRAM)
+ BANK_COUNT_VRAM + BANK_COUNT_OAM + BANK_COUNT_HRAM + BANK_COUNT_SRAM)
extern SLONG area_Avail(SLONG bank);
extern void AssignSections(void);
@@ -32,4 +35,16 @@ extern void CreateSymbolTable(void);
extern SLONG MaxBankUsed;
extern SLONG MaxAvail[MAXBANKS];
int
IsSectionNameInUse(const char *name);
void
SetLinkerscriptName(char *tzLinkerscriptFile);
int
IsSectionSameTypeBankAndFloating(const char *name, enum eSectionType type, int bank);
unsigned int
AssignSectionAddressAndBankByName(const char *name, unsigned int address, int bank);
#endif

View File

@@ -8,8 +8,11 @@
#include "types.h"
extern SLONG options;
#define OPT_SMALL 0x01
#define OPT_TINY 0x01
#define OPT_SMART_C_LINK 0x02
#define OPT_OVERLAY 0x04
#define OPT_CONTWRAM 0x08
#define OPT_DMG_MODE 0x10
enum eRpnData {
RPN_ADD = 0,
@@ -42,10 +45,6 @@ enum eRpnData {
RPN_HRAM,
RPN_PCEZP,
RPN_RANGECHECK,
RPN_CONST = 0x80,
RPN_SYM = 0x81
};
@@ -57,14 +56,17 @@ enum eSectionType {
SECT_ROM0,
SECT_HRAM,
SECT_WRAMX,
SECT_SRAM
SECT_SRAM,
SECT_OAM
};
struct sSection {
SLONG nBank;
SLONG nOrg;
SLONG nAlign;
BBOOL oAssigned;
char *pzName;
SLONG nByteSize;
enum eSectionType Type;
UBYTE *pData;
@@ -92,9 +94,7 @@ struct sSymbol {
enum ePatchType {
PATCH_BYTE = 0,
PATCH_WORD_L,
PATCH_LONG_L,
PATCH_WORD_B,
PATCH_LONG_B
PATCH_LONG_L
};
struct sPatch {

View File

@@ -2,6 +2,7 @@
#define RGBDS_LINK_OUTPUT_H
void out_Setname(char *tzOutputfile);
void out_SetOverlayname(char *tzOverlayfile);
void Output(void);
#endif

37
include/link/script.h Normal file
View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef RGBDS_LINK_SCRIPT_H
#define RGBDS_LINK_SCRIPT_H
#include "extern/stdnoreturn.h"
noreturn void script_fatalerror(const char *fmt, ...);
void script_Parse(const char *path);
void script_IncludeFile(const char *path);
int script_IncludeDepthGet(void);
void script_IncludePop(void);
void script_InitSections(void);
void script_SetCurrentSectionType(const char *type, unsigned int bank);
void script_SetAddress(unsigned int addr);
void script_SetAlignment(unsigned int alignment);
void script_OutputSection(const char *section_name);
#endif

View File

@@ -118,7 +118,6 @@ ULONG str2int2( char *s, int length )
r<<=8;
r|=(UBYTE)(s[i]);
i++;
}
return( r );
}
@@ -460,7 +459,7 @@ void if_skip_to_endc( void )
%left T_OP_MUL T_OP_DIV T_OP_MOD
%left T_OP_NOT
%left T_OP_DEF
%left T_OP_BANK
%left T_OP_BANK T_OP_ALIGN
%left T_OP_SIN
%left T_OP_COS
%left T_OP_TAN
@@ -474,6 +473,7 @@ void if_skip_to_endc( void )
%left T_OP_CEIL
%left T_OP_FLOOR
%token T_OP_HIGH T_OP_LOW
%left T_OP_STRCMP
%left T_OP_STRIN
@@ -513,13 +513,14 @@ void if_skip_to_endc( void )
%token T_POP_POPO
%token T_POP_PUSHO
%token T_POP_OPT
%token T_SECT_WRAM0 T_SECT_VRAM T_SECT_ROMX T_SECT_ROM0 T_SECT_HRAM T_SECT_WRAMX T_SECT_SRAM
%token T_SECT_WRAM0 T_SECT_VRAM T_SECT_ROMX T_SECT_ROM0 T_SECT_HRAM T_SECT_WRAMX T_SECT_SRAM T_SECT_OAM
%token T_SECT_HOME T_SECT_DATA T_SECT_CODE T_SECT_BSS
%token T_Z80_ADC T_Z80_ADD T_Z80_AND
%token T_Z80_BIT
%token T_Z80_CALL T_Z80_CCF T_Z80_CP T_Z80_CPL
%token T_Z80_DAA T_Z80_DEC T_Z80_DI
%token T_Z80_EI T_Z80_EX
%token T_Z80_EI
%token T_Z80_HALT
%token T_Z80_INC
%token T_Z80_JP T_Z80_JR
@@ -537,11 +538,12 @@ void if_skip_to_endc( void )
%token T_Z80_SLA T_Z80_SRA T_Z80_SRL T_Z80_SUB T_Z80_SWAP
%token T_Z80_XOR
%token T_MODE_A T_MODE_B T_MODE_C T_MODE_C_IND T_MODE_D T_MODE_E T_MODE_H T_MODE_L
%token T_TOKEN_A T_TOKEN_B T_TOKEN_C T_TOKEN_D T_TOKEN_E T_TOKEN_H T_TOKEN_L
%token T_MODE_AF
%token T_MODE_BC T_MODE_BC_IND
%token T_MODE_DE T_MODE_DE_IND
%token T_MODE_SP T_MODE_SP_IND
%token T_MODE_C_IND
%token T_MODE_HL T_MODE_HL_IND T_MODE_HL_INDDEC T_MODE_HL_INDINC
%token T_CC_NZ T_CC_Z T_CC_NC
@@ -679,7 +681,7 @@ fail : T_POP_FAIL string {
};
warn : T_POP_WARN string {
yyerror("%s", $2);
warning("%s", $2);
};
shift : T_POP_SHIFT
@@ -770,7 +772,13 @@ import_list : import_list_entry
| import_list_entry ',' import_list
;
import_list_entry : T_ID { sym_Import($1); }
import_list_entry : T_ID {
/* This is done automatically if
* the label isn't found in the
* list of defined symbols. */
if( nPass==1 )
warning("IMPORT is a deprecated keyword with no effect: %s", $1);
}
;
export : T_POP_EXPORT export_list
@@ -992,6 +1000,10 @@ relocconst : T_ID
{ rpn_UNNEG(&$$,&$2); }
| T_OP_NOT relocconst %prec NEG
{ rpn_UNNOT(&$$,&$2); }
| T_OP_HIGH '(' relocconst ')'
{ rpn_HIGH(&$$, &$3); }
| T_OP_LOW '(' relocconst ')'
{ rpn_LOW(&$$, &$3); }
| T_OP_BANK '(' T_ID ')'
{ rpn_Bank(&$$,$3); $$.nVal = 0; }
| T_OP_DEF { oDontExpandStrings = true; } '(' T_ID ')'
@@ -1040,9 +1052,14 @@ const : T_ID { $$ = sym_GetConstantValue($1); }
| const T_OP_LOGICNE const { $$ = $1 != $3; }
| const T_OP_ADD const { $$ = $1 + $3; }
| const T_OP_SUB const { $$ = $1 - $3; }
| T_ID T_OP_SUB T_ID { $$ = sym_GetDefinedValue($1) - sym_GetDefinedValue($3); }
| T_ID T_OP_SUB T_ID
{
if (sym_IsRelocDiffDefined($1, $3) == 0)
fatalerror("'%s - %s' not defined.", $1, $3);
$$ = sym_GetDefinedValue($1) - sym_GetDefinedValue($3);
}
| const T_OP_XOR const { $$ = $1 ^ $3; }
| const T_OP_OR const { $$ = $1 | $3; }
| const T_OP_OR const { $$ = $1 | $3; }
| const T_OP_AND const { $$ = $1 & $3; }
| const T_OP_SHL const { $$ = $1 << $3; }
| const T_OP_SHR const { $$ = $1 >> $3; }
@@ -1113,6 +1130,10 @@ section:
else
yyerror("Address $%x not 16-bit", $6);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']'
{
out_NewAlignedSection($2, $4, $8, -1);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']'
{
bankrangecheck($2, $4, -1, $8);
@@ -1124,6 +1145,14 @@ section:
}
bankrangecheck($2, $4, $6, $11);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']' ',' T_OP_BANK '[' const ']'
{
out_NewAlignedSection($2, $4, $8, $13);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']' ',' T_OP_ALIGN '[' const ']'
{
out_NewAlignedSection($2, $4, $13, $8);
}
;
sectiontype:
@@ -1134,6 +1163,23 @@ sectiontype:
| T_SECT_HRAM { $$=SECT_HRAM; }
| T_SECT_WRAMX { $$=SECT_WRAMX; }
| T_SECT_SRAM { $$=SECT_SRAM; }
| T_SECT_OAM { $$=SECT_OAM; }
| T_SECT_HOME {
warning("HOME section name is deprecated, use ROM0 instead.");
$$=SECT_ROM0;
}
| T_SECT_DATA {
warning("DATA section name is deprecated, use ROMX instead.");
$$=SECT_ROMX;
}
| T_SECT_CODE {
warning("CODE section name is deprecated, use ROMX instead.");
$$=SECT_ROMX;
}
| T_SECT_BSS {
warning("BSS section name is deprecated, use WRAM0 instead.");
$$=SECT_WRAM0;
}
;
@@ -1149,7 +1195,6 @@ cpu_command : z80_adc
| z80_dec
| z80_di
| z80_ei
| z80_ex
| z80_halt
| z80_inc
| z80_jp
@@ -1240,12 +1285,6 @@ z80_ei : T_Z80_EI
{ out_AbsByte(0xFB); }
;
z80_ex : T_Z80_EX T_MODE_HL comma T_MODE_SP_IND
{ out_AbsByte(0xE3); }
| T_Z80_EX T_MODE_SP_IND comma T_MODE_HL
{ out_AbsByte(0xE3); }
;
z80_halt: T_Z80_HALT
{
out_AbsByte(0x76);
@@ -1266,7 +1305,11 @@ z80_jp : T_Z80_JP const_16bit
| T_Z80_JP ccode comma const_16bit
{ out_AbsByte(0xC2|($2<<3)); out_RelWord(&$4); }
| T_Z80_JP T_MODE_HL_IND
{ out_AbsByte(0xE9); }
{
out_AbsByte(0xE9);
if( nPass==1 )
warning("'JP [HL]' is obsolete, use 'JP HL' instead.");
}
| T_Z80_JP T_MODE_HL
{ out_AbsByte(0xE9); }
;
@@ -1280,7 +1323,11 @@ z80_jr : T_Z80_JR const_PCrel
z80_ldi : T_Z80_LDI T_MODE_HL_IND comma T_MODE_A
{ out_AbsByte(0x02|(2<<4)); }
| T_Z80_LDI T_MODE_A comma T_MODE_HL
{ out_AbsByte(0x0A|(2<<4)); }
{
out_AbsByte(0x0A|(2<<4));
if( nPass==1 )
warning("'LDI A,HL' is obsolete, use 'LDI A,[HL]' or 'LD A,[HL+] instead.");
}
| T_Z80_LDI T_MODE_A comma T_MODE_HL_IND
{ out_AbsByte(0x0A|(2<<4)); }
;
@@ -1288,7 +1335,11 @@ z80_ldi : T_Z80_LDI T_MODE_HL_IND comma T_MODE_A
z80_ldd : T_Z80_LDD T_MODE_HL_IND comma T_MODE_A
{ out_AbsByte(0x02|(3<<4)); }
| T_Z80_LDD T_MODE_A comma T_MODE_HL
{ out_AbsByte(0x0A|(3<<4)); }
{
out_AbsByte(0x0A|(3<<4));
if( nPass==1 )
warning("'LDD A,HL' is obsolete, use 'LDD A,[HL]' or 'LD A,[HL-] instead.");
}
| T_Z80_LDD T_MODE_A comma T_MODE_HL_IND
{ out_AbsByte(0x0A|(3<<4)); }
;
@@ -1424,8 +1475,14 @@ z80_ld_a : T_Z80_LD reg_r comma T_MODE_C_IND
}
;
z80_ld_ss : T_Z80_LD reg_ss comma const_16bit
{ out_AbsByte(0x01|($2<<4)); out_RelWord(&$4); }
z80_ld_ss : T_Z80_LD T_MODE_BC comma const_16bit
{ out_AbsByte(0x01|(REG_BC<<4)); out_RelWord(&$4); }
| T_Z80_LD T_MODE_DE comma const_16bit
{ out_AbsByte(0x01|(REG_DE<<4)); out_RelWord(&$4); }
/*
* HL is taken care of in z80_ld_hl
* SP is taken care of in z80_ld_sp
*/
;
z80_nop : T_Z80_NOP
@@ -1565,10 +1622,33 @@ op_a_n : const_8bit { $$ = $1; }
comma : ','
;
T_MODE_A : T_TOKEN_A
| T_OP_HIGH '(' T_MODE_AF ')'
;
T_MODE_B : T_TOKEN_B
| T_OP_HIGH '(' T_MODE_BC ')'
;
T_MODE_C : T_TOKEN_C
| T_OP_LOW '(' T_MODE_BC ')'
;
T_MODE_D : T_TOKEN_D
| T_OP_HIGH '(' T_MODE_DE ')'
;
T_MODE_E : T_TOKEN_E
| T_OP_LOW '(' T_MODE_DE ')'
;
T_MODE_H : T_TOKEN_H
| T_OP_HIGH '(' T_MODE_HL ')'
;
T_MODE_L : T_TOKEN_L
| T_OP_LOW '(' T_MODE_HL ')'
;
ccode : T_CC_NZ { $$ = CC_NZ; }
| T_CC_Z { $$ = CC_Z; }
| T_CC_NC { $$ = CC_NC; }
| T_MODE_C { $$ = CC_C; }
| T_TOKEN_C { $$ = CC_C; }
;
reg_r : T_MODE_B { $$ = REG_B; }

View File

@@ -107,7 +107,8 @@ readUTF8Char(char *dest, char *src)
int
charmap_Add(char *input, UBYTE output)
{
int i, input_length;
int i;
size_t input_length;
char temp1i[CHARMAPLENGTH + 1], temp2i[CHARMAPLENGTH + 1], temp1o = 0,
temp2o = 0;

View File

@@ -47,7 +47,7 @@ ULONG ulMacroReturnValue;
/*
* Context push and pop
*/
void
void
pushcontext(void)
{
struct sContext **ppFileStack;
@@ -84,7 +84,7 @@ pushcontext(void)
fatalerror("No memory for context");
}
int
int
popcontext(void)
{
struct sContext *pLastFile, **ppLastFile;
@@ -148,7 +148,7 @@ popcontext(void)
return (1);
}
int
int
yywrap(void)
{
return (popcontext());
@@ -157,7 +157,7 @@ yywrap(void)
/*
* Dump the context stack to stderr
*/
void
void
fstk_Dump(void)
{
struct sContext *pLastFile;
@@ -176,7 +176,7 @@ fstk_Dump(void)
/*
* Extra includepath stuff
*/
void
void
fstk_AddIncludePath(char *s)
{
if (NextIncPath == MAXINCPATHS) {
@@ -202,7 +202,7 @@ fstk_FindFile(char *fname)
}
for (i = 0; i < NextIncPath; ++i) {
if (strlcpy(path, IncludePaths[i], sizeof path) >=
if (strlcpy(path, IncludePaths[i], sizeof path) >=
sizeof path) {
continue;
}
@@ -251,7 +251,7 @@ fstk_RunInclude(char *tzFileName)
/*
* Set up a macro for parsing
*/
ULONG
ULONG
fstk_RunMacro(char *s)
{
struct sSymbol *sym;
@@ -278,7 +278,7 @@ fstk_RunMacro(char *s)
/*
* Set up a macroargument for parsing
*/
void
void
fstk_RunMacroArg(SLONG s)
{
char *sym;
@@ -301,7 +301,7 @@ fstk_RunMacroArg(SLONG s)
/*
* Set up a stringequate for parsing
*/
void
void
fstk_RunString(char *s)
{
struct sSymbol *pSym;
@@ -320,7 +320,7 @@ fstk_RunString(char *s)
/*
* Set up a repeat block for parsing
*/
void
void
fstk_RunRept(ULONG count)
{
if (count) {
@@ -346,7 +346,9 @@ fstk_Init(char *s)
{
char tzFileName[_MAX_PATH + 1];
sym_AddString("__FILE__", s);
char tzSymFileName[_MAX_PATH + 1 + 2];
snprintf(tzSymFileName, sizeof(tzSymFileName), "\"%s\"", s);
sym_AddString("__FILE__", tzSymFileName);
strcpy(tzFileName, s);
pFileStack = NULL;

View File

@@ -17,7 +17,7 @@ bool oDontExpandStrings = false;
SLONG nGBGfxID = -1;
SLONG nBinaryID = -1;
SLONG
SLONG
gbgfx2bin(char ch)
{
SLONG i;
@@ -31,7 +31,7 @@ gbgfx2bin(char ch)
return (0);
}
SLONG
SLONG
binary2bin(char ch)
{
SLONG i;
@@ -45,7 +45,7 @@ binary2bin(char ch)
return (0);
}
SLONG
SLONG
char2bin(char ch)
{
if (ch >= 'a' && ch <= 'f')
@@ -62,7 +62,7 @@ char2bin(char ch)
typedef SLONG(*x2bin) (char ch);
SLONG
SLONG
ascii2bin(char *s)
{
SLONG radix = 10;
@@ -107,7 +107,7 @@ ascii2bin(char *s)
return (result);
}
ULONG
ULONG
ParseFixedPoint(char *s, ULONG size)
{
//char dest[256];
@@ -133,7 +133,7 @@ ParseFixedPoint(char *s, ULONG size)
return (1);
}
ULONG
ULONG
ParseNumber(char *s, ULONG size)
{
char dest[256];
@@ -145,7 +145,7 @@ ParseNumber(char *s, ULONG size)
return (1);
}
ULONG
ULONG
ParseSymbol(char *src, ULONG size)
{
char dest[MAXSYMLEN + 1];
@@ -203,7 +203,7 @@ ParseSymbol(char *src, ULONG size)
}
}
ULONG
ULONG
PutMacroArg(char *src, ULONG size)
{
char *s;
@@ -221,7 +221,7 @@ PutMacroArg(char *src, ULONG size)
return (0);
}
ULONG
ULONG
PutUniqueArg(char *src, ULONG size)
{
char *s;
@@ -267,6 +267,7 @@ struct sLexInitString staticstrings[] = {
{"def", T_OP_DEF},
{"bank", T_OP_BANK},
{"align", T_OP_ALIGN},
{"round", T_OP_ROUND},
{"ceil", T_OP_CEIL},
@@ -281,6 +282,9 @@ struct sLexInitString staticstrings[] = {
{"atan", T_OP_ATAN},
{"atan2", T_OP_ATAN2},
{"high", T_OP_HIGH},
{"low", T_OP_LOW},
{"strcmp", T_OP_STRCMP},
{"strin", T_OP_STRIN},
{"strsub", T_OP_STRSUB},
@@ -301,9 +305,6 @@ struct sLexInitString staticstrings[] = {
{"ds", T_POP_DS},
{NAME_DB, T_POP_DB},
{NAME_DW, T_POP_DW},
#ifdef NAME_DL
{NAME_DL, T_POP_DL},
#endif
{"section", T_POP_SECTION},
{"purge", T_POP_PURGE},
@@ -331,22 +332,22 @@ struct sLexInitString staticstrings[] = {
{"endc", T_POP_ENDC},
{"wram0", T_SECT_WRAM0},
{"bss", T_SECT_WRAM0}, /* deprecated */
{"vram", T_SECT_VRAM},
{"code", T_SECT_ROMX}, /* deprecated */
{"data", T_SECT_ROMX}, /* deprecated */
{"romx", T_SECT_ROMX},
{"home", T_SECT_ROM0}, /* deprecated */
{"rom0", T_SECT_ROM0},
{"hram", T_SECT_HRAM},
{"wramx", T_SECT_WRAMX},
{"sram", T_SECT_SRAM},
{"oam", T_SECT_OAM},
/* Deprecated section type names */
{"home", T_SECT_HOME},
{"code", T_SECT_CODE},
{"data", T_SECT_DATA},
{"bss", T_SECT_BSS},
{NAME_RB, T_POP_RB},
{NAME_RW, T_POP_RW},
#ifdef NAME_RL
{NAME_RL, T_POP_RL},
#endif
{"equ", T_POP_EQU},
{"equs", T_POP_EQUS},
@@ -388,7 +389,7 @@ struct sLexFloat tMacroUniqueToken = {
T_LEX_MACROUNIQUE
};
void
void
setuplex(void)
{
ULONG id;

View File

@@ -39,7 +39,7 @@ ULONG tFloatingChars[256];
ULONG nFloating;
enum eLexerState lexerstate = LEX_STATE_NORMAL;
void
void
upperstring(char *s)
{
while (*s) {
@@ -48,7 +48,7 @@ upperstring(char *s)
}
}
void
void
lowerstring(char *s)
{
while (*s) {
@@ -57,19 +57,19 @@ lowerstring(char *s)
}
}
void
void
yyskipbytes(ULONG count)
{
pLexBuffer += count;
}
void
void
yyunputbytes(ULONG count)
{
pLexBuffer -= count;
}
void
void
yyunput(char c)
{
if (pLexBuffer <= pLexBufferRealStart)
@@ -78,7 +78,7 @@ yyunput(char c)
*(--pLexBuffer) = c;
}
void
void
yyunputstr(char *s)
{
int i, len;
@@ -92,26 +92,26 @@ yyunputstr(char *s)
*(--pLexBuffer) = s[i];
}
void
void
yy_switch_to_buffer(YY_BUFFER_STATE buf)
{
pCurrentBuffer = buf;
}
void
void
yy_set_state(enum eLexerState i)
{
lexerstate = i;
}
void
void
yy_delete_buffer(YY_BUFFER_STATE buf)
{
free(buf->pBufferStart - SAFETYMARGIN);
free(buf);
}
YY_BUFFER_STATE
YY_BUFFER_STATE
yy_scan_bytes(char *mem, ULONG size)
{
YY_BUFFER_STATE pBuffer;
@@ -132,7 +132,7 @@ yy_scan_bytes(char *mem, ULONG size)
return (NULL);
}
YY_BUFFER_STATE
YY_BUFFER_STATE
yy_create_buffer(FILE * f)
{
YY_BUFFER_STATE pBuffer;
@@ -219,7 +219,7 @@ lex_CheckCharacterRange(UWORD start, UWORD end)
}
}
void
void
lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end)
{
lex_CheckCharacterRange(start, end);
@@ -230,7 +230,7 @@ lex_FloatDeleteRange(ULONG id, UWORD start, UWORD end)
}
}
void
void
lex_FloatAddRange(ULONG id, UWORD start, UWORD end)
{
lex_CheckCharacterRange(start, end);
@@ -241,7 +241,7 @@ lex_FloatAddRange(ULONG id, UWORD start, UWORD end)
}
}
void
void
lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end)
{
lex_CheckCharacterRange(start, end);
@@ -252,7 +252,7 @@ lex_FloatDeleteFirstRange(ULONG id, UWORD start, UWORD end)
}
}
void
void
lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end)
{
lex_CheckCharacterRange(start, end);
@@ -263,7 +263,7 @@ lex_FloatAddFirstRange(ULONG id, UWORD start, UWORD end)
}
}
void
void
lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end)
{
lex_CheckCharacterRange(start, end);
@@ -274,7 +274,7 @@ lex_FloatDeleteSecondRange(ULONG id, UWORD start, UWORD end)
}
}
void
void
lex_FloatAddSecondRange(ULONG id, UWORD start, UWORD end)
{
lex_CheckCharacterRange(start, end);
@@ -302,7 +302,7 @@ lexgetfloat(ULONG nFloatMask)
return (&tLexFloat[i]);
}
ULONG
ULONG
lexcalchash(char *s)
{
ULONG hash = 0;
@@ -314,7 +314,7 @@ lexcalchash(char *s)
return (hash % LEXHASHSIZE);
}
void
void
lex_Init(void)
{
ULONG i;
@@ -333,7 +333,7 @@ lex_Init(void)
nFloating = 0;
}
void
void
lex_AddStrings(struct sLexInitString * lex)
{
while (lex->tzName) {
@@ -435,10 +435,10 @@ yylex_GetLongestFixed()
size_t
CopyMacroArg(char *dest, size_t maxLength, char c)
{
int i;
size_t i;
char *s;
int argNum;
switch (c) {
case '1':
case '2':
@@ -565,6 +565,15 @@ yylex_ReadQuotedString()
case '"':
ch = '"';
break;
case ',':
ch = ',';
break;
case '{':
ch = '{';
break;
case '}':
ch = '}';
break;
default:
maxLength = MAXSTRLEN - index;
length = CopyMacroArg(&yylval.tzString[index], maxLength, ch);
@@ -698,6 +707,15 @@ yylex_MACROARGS()
case '\\':
ch = '\\';
break;
case ',':
ch = ',';
break;
case '{':
ch = '{';
break;
case '}':
ch = '}';
break;
default:
maxLength = MAXSTRLEN - index;
length = CopyMacroArg(&yylval.tzString[index], maxLength, ch);
@@ -706,7 +724,7 @@ yylex_MACROARGS()
index += length;
else
fatalerror("Illegal character escape '%c'", ch);
ch = 0;
break;
}
@@ -739,7 +757,7 @@ yylex_MACROARGS()
return 0;
}
ULONG
ULONG
yylex(void)
{
switch (lexerstate) {

View File

@@ -17,7 +17,6 @@ struct sLexInitString localstrings[] = {
{"dec", T_Z80_DEC},
{"di", T_Z80_DI},
{"ei", T_Z80_EI},
{"ex", T_Z80_EX},
{"halt", T_Z80_HALT},
{"inc", T_Z80_INC},
{"jp", T_Z80_JP},
@@ -60,30 +59,31 @@ struct sLexInitString localstrings[] = {
{"nz", T_CC_NZ},
{"z", T_CC_Z},
{"nc", T_CC_NC},
/* { "c", T_MODE_C }, */
/* { "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},
{"hl", T_MODE_HL},
{"af", T_MODE_AF},
{"[bc]", T_MODE_BC_IND},
{"bc", T_MODE_BC},
{"[de]", T_MODE_DE_IND},
{"de", T_MODE_DE},
{"[sp]", T_MODE_SP_IND},
{"af", T_MODE_AF},
{"bc", T_MODE_BC},
{"de", T_MODE_DE},
{"hl", T_MODE_HL},
{"sp", T_MODE_SP},
{"a", T_MODE_A},
{"b", T_MODE_B},
{"[$ff00+c]", T_MODE_C_IND},
{"[c]", T_MODE_C_IND},
{"c", T_MODE_C},
{"d", T_MODE_D},
{"e", T_MODE_E},
{"h", T_MODE_H},
{"l", T_MODE_L},
{"[$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},
{NULL, 0}
};

View File

@@ -20,8 +20,6 @@ int cldefines_index;
int cldefines_size;
char **cldefines;
char *progname;
clock_t nStartClock, nEndClock;
SLONG nLineNo;
ULONG nTotalLines, nPass, nPC, nIFDepth, nErrors;
@@ -42,7 +40,7 @@ struct sOptionStackEntry {
struct sOptionStackEntry *pOptionStack = NULL;
void
void
opt_SetCurrentOptions(struct sOptions * pOpt)
{
if (nGBGfxID != -1) {
@@ -105,7 +103,7 @@ opt_SetCurrentOptions(struct sOptions * pOpt)
}
}
void
void
opt_Parse(char *s)
{
struct sOptions newopt;
@@ -154,7 +152,7 @@ opt_Parse(char *s)
opt_SetCurrentOptions(&newopt);
}
void
void
opt_Push(void)
{
struct sOptionStackEntry *pOpt;
@@ -167,7 +165,7 @@ opt_Push(void)
fatalerror("No memory for option stack");
}
void
void
opt_Pop(void)
{
if (pOptionStack) {
@@ -226,15 +224,15 @@ opt_ParseDefines()
void
verror(const char *fmt, va_list args)
{
fprintf(stderr, "ERROR:\t");
fprintf(stderr, "ERROR: ");
fstk_Dump();
fprintf(stderr, " :\n\t");
fprintf(stderr, ":\n\t");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
nErrors += 1;
}
void
void
yyerror(const char *fmt, ...)
{
va_list args;
@@ -243,7 +241,7 @@ yyerror(const char *fmt, ...)
va_end(args);
}
void
void
fatalerror(const char *fmt, ...)
{
va_list args;
@@ -253,7 +251,25 @@ fatalerror(const char *fmt, ...)
exit(5);
}
static void
void
warning(const char *fmt, ...)
{
if (!CurrentOptions.warnings)
return;
va_list args;
va_start(args, fmt);
fprintf(stderr, "warning: ");
fstk_Dump();
fprintf(stderr, ":\n\t");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
}
static void
usage(void)
{
printf(
@@ -262,7 +278,7 @@ usage(void)
exit(1);
}
int
int
main(int argc, char *argv[])
{
int ch;
@@ -283,8 +299,6 @@ main(int argc, char *argv[])
if (argc == 1)
usage();
progname = argv[0];
/* yydebug=1; */
DefaultOptions.gbgfx[0] = '0';
@@ -297,12 +311,13 @@ main(int argc, char *argv[])
DefaultOptions.verbose = false;
DefaultOptions.haltnop = true;
DefaultOptions.exportall = false;
DefaultOptions.warnings = true;
opt_SetCurrentOptions(&DefaultOptions);
newopt = CurrentOptions;
while ((ch = getopt(argc, argv, "b:D:g:hi:o:p:vE")) != -1) {
while ((ch = getopt(argc, argv, "b:D:g:hi:o:p:vEw")) != -1) {
switch (ch) {
case 'b':
if (strlen(optarg) == 2) {
@@ -352,6 +367,9 @@ main(int argc, char *argv[])
case 'E':
newopt.exportall = true;
break;
case 'w':
newopt.warnings = false;
break;
default:
usage();
}

View File

@@ -18,7 +18,7 @@
/*
* Define the _PI symbol
*/
void
void
math_DefinePI(void)
{
sym_AddEqu("_PI", double2fix(PI));
@@ -27,7 +27,7 @@ math_DefinePI(void)
/*
* Print a fixed point value
*/
void
void
math_Print(SLONG i)
{
if (i >= 0)
@@ -41,7 +41,7 @@ math_Print(SLONG i)
/*
* Calculate sine
*/
SLONG
SLONG
math_Sin(SLONG i)
{
return (double2fix(sin(fix2double(i) * 2 * PI / 65536)));
@@ -50,7 +50,7 @@ math_Sin(SLONG i)
/*
* Calculate cosine
*/
SLONG
SLONG
math_Cos(SLONG i)
{
return (double2fix(cos(fix2double(i) * 2 * PI / 65536)));
@@ -59,7 +59,7 @@ math_Cos(SLONG i)
/*
* Calculate tangent
*/
SLONG
SLONG
math_Tan(SLONG i)
{
return (double2fix(tan(fix2double(i) * 2 * PI / 65536)));
@@ -68,7 +68,7 @@ math_Tan(SLONG i)
/*
* Calculate arcsine
*/
SLONG
SLONG
math_ASin(SLONG i)
{
return (double2fix(asin(fix2double(i)) / 2 / PI * 65536));
@@ -77,7 +77,7 @@ math_ASin(SLONG i)
/*
* Calculate arccosine
*/
SLONG
SLONG
math_ACos(SLONG i)
{
return (double2fix(acos(fix2double(i)) / 2 / PI * 65536));
@@ -86,7 +86,7 @@ math_ACos(SLONG i)
/*
* Calculate arctangent
*/
SLONG
SLONG
math_ATan(SLONG i)
{
return (double2fix(atan(fix2double(i)) / 2 / PI * 65536));
@@ -95,7 +95,7 @@ math_ATan(SLONG i)
/*
* Calculate atan2
*/
SLONG
SLONG
math_ATan2(SLONG i, SLONG j)
{
return (double2fix
@@ -105,7 +105,7 @@ math_ATan2(SLONG i, SLONG j)
/*
* Multiplication
*/
SLONG
SLONG
math_Mul(SLONG i, SLONG j)
{
return (double2fix(fix2double(i) * fix2double(j)));
@@ -114,7 +114,7 @@ math_Mul(SLONG i, SLONG j)
/*
* Division
*/
SLONG
SLONG
math_Div(SLONG i, SLONG j)
{
return (double2fix(fix2double(i) / fix2double(j)));
@@ -123,7 +123,7 @@ math_Div(SLONG i, SLONG j)
/*
* Round
*/
SLONG
SLONG
math_Round(SLONG i)
{
return double2fix(round(fix2double(i)));
@@ -132,7 +132,7 @@ math_Round(SLONG i)
/*
* Ceil
*/
SLONG
SLONG
math_Ceil(SLONG i)
{
return double2fix(ceil(fix2double(i)));
@@ -141,7 +141,7 @@ math_Ceil(SLONG i)
/*
* Floor
*/
SLONG
SLONG
math_Floor(SLONG i)
{
return double2fix(floor(fix2double(i)));

View File

@@ -53,7 +53,7 @@ struct SectionStackEntry *pSectionStack = NULL;
/*
* Section stack routines
*/
void
void
out_PushSection(void)
{
struct SectionStackEntry *pSect;
@@ -66,7 +66,7 @@ out_PushSection(void)
fatalerror("No memory for section stack");
}
void
void
out_PopSection(void)
{
if (pSectionStack) {
@@ -83,7 +83,7 @@ out_PopSection(void)
/*
* Count the number of symbols used in this object
*/
ULONG
ULONG
countsymbols(void)
{
struct PatchSymbol *pSym;
@@ -102,7 +102,7 @@ countsymbols(void)
/*
* Count the number of sections used in this object
*/
ULONG
ULONG
countsections(void)
{
struct Section *pSect;
@@ -121,7 +121,7 @@ countsections(void)
/*
* Count the number of patches used in this object
*/
ULONG
ULONG
countpatches(struct Section * pSect)
{
struct Patch *pPatch;
@@ -139,7 +139,7 @@ countpatches(struct Section * pSect)
/*
* Write a long to a file (little-endian)
*/
void
void
fputlong(ULONG i, FILE * f)
{
fputc(i, f);
@@ -151,7 +151,7 @@ fputlong(ULONG i, FILE * f)
/*
* Write a NULL-terminated string to a file
*/
void
void
fputstring(char *s, FILE * f)
{
while (*s)
@@ -162,7 +162,7 @@ fputstring(char *s, FILE * f)
/*
* Return a section's ID
*/
ULONG
ULONG
getsectid(struct Section * pSect)
{
struct Section *sec;
@@ -184,7 +184,7 @@ getsectid(struct Section * pSect)
/*
* Write a patch to a file
*/
void
void
writepatch(struct Patch * pPatch, FILE * f)
{
fputstring(pPatch->tzFilename, f);
@@ -198,20 +198,20 @@ writepatch(struct Patch * pPatch, FILE * f)
/*
* Write a section to a file
*/
void
void
writesection(struct Section * pSect, FILE * f)
{
//printf("SECTION: %s, ID: %d\n", pSect->pzName, getsectid(pSect));
fputstring(pSect->pzName, f);
fputlong(pSect->nPC, f);
fputc(pSect->nType, f);
fputlong(pSect->nOrg, f);
//RGB1 addition
fputlong(pSect->nBank, f);
fputlong(pSect->nAlign, f);
fputlong(pSect->nBank, f);
//RGB1 addition
if ((pSect->nType == SECT_ROM0)
if ((pSect->nType == SECT_ROM0)
|| (pSect->nType == SECT_ROMX)) {
struct Patch *pPatch;
@@ -229,7 +229,7 @@ writesection(struct Section * pSect, FILE * f)
/*
* Write a symbol to a file
*/
void
void
writesymbol(struct sSymbol * pSym, FILE * f)
{
char symname[MAXSYMLEN * 2 + 1];
@@ -249,7 +249,7 @@ writesymbol(struct sSymbol * pSym, FILE * f)
strcat(symname, pSym->tzName);
} else
strcpy(symname, pSym->tzName);
if (pSym->nType & SYMF_EXPORT) {
/* Symbol should be exported */
type = SYM_EXPORT;
@@ -278,13 +278,12 @@ writesymbol(struct sSymbol * pSym, FILE * f)
/*
* Add a symbol to the object
*/
ULONG
ULONG
addsymbol(struct sSymbol * pSym)
{
struct PatchSymbol *pPSym, **ppPSym;
static ULONG nextID = 0;
ULONG hash;
hash = calchash(pSym->tzName);
ppPSym = &(tHashedPatchSymbols[hash]);
@@ -312,7 +311,7 @@ addsymbol(struct sSymbol * pSym)
/*
* Add all exported symbols to the object
*/
void
void
addexports(void)
{
int i;
@@ -352,7 +351,7 @@ allocpatch(void)
/*
* Create a new patch (includes the rpn expr)
*/
void
void
createpatch(ULONG type, struct Expression * expr)
{
struct Patch *pPatch;
@@ -428,7 +427,7 @@ createpatch(ULONG type, struct Expression * expr)
/*
* A quick check to see if we have an initialized section
*/
void
void
checksection(void)
{
if (pCurrentSection)
@@ -441,7 +440,7 @@ checksection(void)
* A quick check to see if we have an initialized section that can contain
* this much initialized data
*/
void
void
checkcodesection(SLONG size)
{
checksection();
@@ -479,7 +478,7 @@ checkcodesection(SLONG size)
/*
* Write an objectfile
*/
void
void
out_WriteObject(void)
{
FILE *f;
@@ -490,7 +489,7 @@ out_WriteObject(void)
struct PatchSymbol *pSym;
struct Section *pSect;
fwrite("RGB2", 1, 4, f);
fwrite("RGB4", 1, 4, f);
fputlong(countsymbols(), f);
fputlong(countsections(), f);
@@ -513,7 +512,7 @@ out_WriteObject(void)
/*
* Prepare for pass #2
*/
void
void
out_PrepPass2(void)
{
struct Section *pSect;
@@ -530,7 +529,7 @@ out_PrepPass2(void)
/*
* Set the objectfilename
*/
void
void
out_SetFileName(char *s)
{
tzObjectname = s;
@@ -546,7 +545,7 @@ out_SetFileName(char *s)
* Find a section by name and type. If it doesn't exist, create it
*/
struct Section *
out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG alignment)
{
struct Section *pSect, **ppSect;
@@ -557,7 +556,8 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
if (strcmp(pzName, pSect->pzName) == 0) {
if (secttype == pSect->nType
&& ((ULONG) org) == pSect->nOrg
&& ((ULONG) bank) == pSect->nBank) {
&& ((ULONG) bank) == pSect->nBank
&& ((ULONG) alignment == pSect->nAlign)) {
return (pSect);
} else
fatalerror
@@ -574,6 +574,7 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
pSect->nPC = 0;
pSect->nOrg = org;
pSect->nBank = bank;
pSect->nAlign = alignment;
pSect->pNext = NULL;
pSect->pPatches = NULL;
pSect->charmap = NULL;
@@ -594,7 +595,7 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
/*
* Set the current section
*/
void
void
out_SetCurrentSection(struct Section * pSect)
{
pCurrentSection = pSect;
@@ -607,25 +608,37 @@ out_SetCurrentSection(struct Section * pSect)
/*
* Set the current section by name and type
*/
void
void
out_NewSection(char *pzName, ULONG secttype)
{
out_SetCurrentSection(out_FindSection(pzName, secttype, -1, -1));
out_SetCurrentSection(out_FindSection(pzName, secttype, -1, -1, 1));
}
/*
* Set the current section by name and type
*/
void
void
out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank)
{
out_SetCurrentSection(out_FindSection(pzName, secttype, org, bank));
out_SetCurrentSection(out_FindSection(pzName, secttype, org, bank, 1));
}
/*
* Set the current section by name and type, using a given byte alignment
*/
void
out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank)
{
if (alignment < 0 || alignment > 16) {
yyerror("Alignment must be between 0-16 bits.");
}
out_SetCurrentSection(out_FindSection(pzName, secttype, -1, bank, 1 << alignment));
}
/*
* Output an absolute byte
*/
void
void
out_AbsByte(int b)
{
checkcodesection(1);
@@ -638,7 +651,7 @@ out_AbsByte(int b)
pPCSymbol->nValue += 1;
}
void
void
out_AbsByteGroup(char *s, int length)
{
checkcodesection(length);
@@ -649,7 +662,7 @@ out_AbsByteGroup(char *s, int length)
/*
* Skip this many bytes
*/
void
void
out_Skip(int skip)
{
checksection();
@@ -668,7 +681,7 @@ out_Skip(int skip)
/*
* Output a NULL terminated string (excluding the NULL-character)
*/
void
void
out_String(char *s)
{
checkcodesection(strlen(s));
@@ -681,7 +694,7 @@ out_String(char *s)
* is an absolute value in disguise.
*/
void
void
out_RelByte(struct Expression * expr)
{
checkcodesection(1);
@@ -702,7 +715,7 @@ out_RelByte(struct Expression * expr)
/*
* Output an absolute word
*/
void
void
out_AbsWord(int b)
{
checkcodesection(2);
@@ -720,7 +733,7 @@ out_AbsWord(int b)
* Output a relocatable word. Checking will be done to see if
* it's an absolute value in disguise.
*/
void
void
out_RelWord(struct Expression * expr)
{
ULONG b;
@@ -744,7 +757,7 @@ out_RelWord(struct Expression * expr)
/*
* Output an absolute longword
*/
void
void
out_AbsLong(SLONG b)
{
checkcodesection(sizeof(SLONG));
@@ -763,7 +776,7 @@ out_AbsLong(SLONG b)
* Output a relocatable longword. Checking will be done to see if
* is an absolute value in disguise.
*/
void
void
out_RelLong(struct Expression * expr)
{
SLONG b;
@@ -789,7 +802,7 @@ out_RelLong(struct Expression * expr)
/*
* Output a PC-relative byte
*/
void
void
out_PCRelByte(struct Expression * expr)
{
SLONG b = expr->nVal;
@@ -806,7 +819,7 @@ out_PCRelByte(struct Expression * expr)
/*
* Output a binary file
*/
void
void
out_BinaryFile(char *s)
{
FILE *f;
@@ -837,7 +850,7 @@ out_BinaryFile(char *s)
fclose(f);
}
void
void
out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length)
{
FILE *f;

View File

@@ -1,4 +1,18 @@
.Dd February 26, 2015
.\" Copyright © 2010 Anthony J. Bentley <anthony@anjbe.name>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 17, 2017
.Dt RGBASM 1
.Os RGBDS Manual
.Sh NAME
@@ -6,7 +20,7 @@
.Nd Game Boy assembler
.Sh SYNOPSIS
.Nm rgbasm
.Op Fl Ehv
.Op Fl Ehvw
.Op Fl b Ar chars
.Op Fl D Ar name Ns Op = Ns Ar value
.Op Fl g Ar chars
@@ -54,6 +68,8 @@ When padding an image, pad with this value.
The default is 0x00.
.It Fl v
Be verbose.
.It Fl w
Disable warning output.
.El
.Sh EXAMPLES
Assembling a basic source file is simple:
@@ -66,12 +82,16 @@ run through
and
.Xr rgbfix 1 .
.Sh SEE ALSO
.Xr rgbasm 5 ,
.Xr rgbfix 1 ,
.Xr rgblink 1 ,
.Xr rgbds 7
.Xr rgbds 5 ,
.Xr rgbds 7 ,
.Xr gbz80 7
.Pp
.Lk https://rednex.github.io/rgbds/asm.htm rgbasm assembly commands
.Sh HISTORY
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd.
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
number of contributors at https://github.com/rednex/rgbds.

1008
src/asm/rgbasm.5 Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,7 @@
#include "asm/main.h"
#include "asm/rpn.h"
void
void
mergetwoexpressions(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -28,7 +28,7 @@ mergetwoexpressions(struct Expression * expr, struct Expression * src1,
/*
* Add a byte to the RPN expression
*/
void
void
pushbyte(struct Expression * expr, int b)
{
expr->tRPN[expr->nRPNLength++] = b & 0xFF;
@@ -37,7 +37,7 @@ pushbyte(struct Expression * expr, int b)
/*
* Reset the RPN module
*/
void
void
rpn_Reset(struct Expression * expr)
{
expr->nRPNLength = expr->nRPNOut = expr->isReloc = expr->isPCRel = 0;
@@ -46,7 +46,7 @@ rpn_Reset(struct Expression * expr)
/*
* Returns the next rpn byte in expression
*/
UWORD
UWORD
rpn_PopByte(struct Expression * expr)
{
if (expr->nRPNOut == expr->nRPNLength) {
@@ -58,7 +58,7 @@ rpn_PopByte(struct Expression * expr)
/*
* Determine if the current expression is relocatable
*/
ULONG
ULONG
rpn_isReloc(struct Expression * expr)
{
return (expr->isReloc);
@@ -67,7 +67,7 @@ rpn_isReloc(struct Expression * expr)
/*
* Determine if the current expression can be pc-relative
*/
ULONG
ULONG
rpn_isPCRelative(struct Expression * expr)
{
return (expr->isPCRel);
@@ -76,7 +76,7 @@ rpn_isPCRelative(struct Expression * expr)
/*
* Add symbols, constants and operators to expression
*/
void
void
rpn_Number(struct Expression * expr, ULONG i)
{
rpn_Reset(expr);
@@ -88,7 +88,7 @@ rpn_Number(struct Expression * expr, ULONG i)
expr->nVal = i;
}
void
void
rpn_Symbol(struct Expression * expr, char *tzSym)
{
if (!sym_isConstant(tzSym)) {
@@ -110,7 +110,7 @@ rpn_Symbol(struct Expression * expr, char *tzSym)
rpn_Number(expr, sym_GetConstantValue(tzSym));
}
void
void
rpn_Bank(struct Expression * expr, char *tzSym)
{
if (!sym_isConstant(tzSym)) {
@@ -128,43 +128,21 @@ rpn_Bank(struct Expression * expr, char *tzSym)
yyerror("BANK argument must be a relocatable identifier");
}
int
rpn_RangeCheck(struct Expression * expr, struct Expression * src, SLONG low,
SLONG high)
{
*expr = *src;
if (rpn_isReloc(src)) {
pushbyte(expr, RPN_RANGECHECK);
pushbyte(expr, low);
pushbyte(expr, low >> 8);
pushbyte(expr, low >> 16);
pushbyte(expr, low >> 24);
pushbyte(expr, high);
pushbyte(expr, high >> 8);
pushbyte(expr, high >> 16);
pushbyte(expr, high >> 24);
return (1);
} else {
return (expr->nVal >= low && expr->nVal <= high);
}
}
void
void
rpn_CheckHRAM(struct Expression * expr, struct Expression * src)
{
*expr = *src;
pushbyte(expr, RPN_HRAM);
}
void
void
rpn_LOGNOT(struct Expression * expr, struct Expression * src)
{
*expr = *src;
pushbyte(expr, RPN_LOGUNNOT);
}
void
void
rpn_LOGOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -173,7 +151,7 @@ rpn_LOGOR(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGOR);
}
void
void
rpn_LOGAND(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -182,7 +160,47 @@ rpn_LOGAND(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGAND);
}
void
void
rpn_HIGH(struct Expression * expr, struct Expression * src)
{
*expr = *src;
expr->nVal = (expr->nVal >> 8) & 0xFF;
pushbyte(expr, RPN_CONST);
pushbyte(expr, 8);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_SHR);
pushbyte(expr, RPN_CONST);
pushbyte(expr, 0xFF);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_AND);
}
void
rpn_LOW(struct Expression * expr, struct Expression * src)
{
*expr = *src;
expr->nVal = expr->nVal & 0xFF;
pushbyte(expr, RPN_CONST);
pushbyte(expr, 0xFF);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, 0);
pushbyte(expr, RPN_AND);
}
void
rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -191,7 +209,7 @@ rpn_LOGEQU(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGEQ);
}
void
void
rpn_LOGGT(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -200,7 +218,7 @@ rpn_LOGGT(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGGT);
}
void
void
rpn_LOGLT(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -209,7 +227,7 @@ rpn_LOGLT(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGLT);
}
void
void
rpn_LOGGE(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -218,7 +236,7 @@ rpn_LOGGE(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGGE);
}
void
void
rpn_LOGLE(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -227,7 +245,7 @@ rpn_LOGLE(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGLE);
}
void
void
rpn_LOGNE(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -236,7 +254,7 @@ rpn_LOGNE(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_LOGNE);
}
void
void
rpn_ADD(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -245,7 +263,7 @@ rpn_ADD(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_ADD);
}
void
void
rpn_SUB(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -254,7 +272,7 @@ rpn_SUB(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_SUB);
}
void
void
rpn_XOR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -263,7 +281,7 @@ rpn_XOR(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_XOR);
}
void
void
rpn_OR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -272,7 +290,7 @@ rpn_OR(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_OR);
}
void
void
rpn_AND(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -281,7 +299,7 @@ rpn_AND(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_AND);
}
void
void
rpn_SHL(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -290,7 +308,7 @@ rpn_SHL(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_SHL);
}
void
void
rpn_SHR(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -299,7 +317,7 @@ rpn_SHR(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_SHR);
}
void
void
rpn_MUL(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -308,7 +326,7 @@ rpn_MUL(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_MUL);
}
void
void
rpn_DIV(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -320,7 +338,7 @@ rpn_DIV(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_DIV);
}
void
void
rpn_MOD(struct Expression * expr, struct Expression * src1,
struct Expression * src2)
{
@@ -332,7 +350,7 @@ rpn_MOD(struct Expression * expr, struct Expression * src1,
pushbyte(expr, RPN_MOD);
}
void
void
rpn_UNNEG(struct Expression * expr, struct Expression * src)
{
*expr = *src;
@@ -340,7 +358,7 @@ rpn_UNNEG(struct Expression * expr, struct Expression * src)
pushbyte(expr, RPN_UNSUB);
}
void
void
rpn_UNNOT(struct Expression * expr, struct Expression * src)
{
*expr = *src;

View File

@@ -12,6 +12,7 @@
#include "asm/main.h"
#include "asm/mymath.h"
#include "asm/output.h"
#include "extern/err.h"
struct sSymbol *tHashedSymbols[HASHSIZE];
struct sSymbol *pScope = NULL;
@@ -21,9 +22,11 @@ char *currentmacroargs[MAXMACROARGS + 1];
char *newmacroargs[MAXMACROARGS + 1];
char SavedTIME[256];
char SavedDATE[256];
char SavedTIMESTAMP_ISO8601_LOCAL[256];
char SavedTIMESTAMP_ISO8601_UTC[256];
bool exportall;
SLONG
SLONG
Callback_NARG(struct sSymbol * sym)
{
ULONG i = 0;
@@ -37,7 +40,7 @@ Callback_NARG(struct sSymbol * sym)
/*
* Get the nValue field of a symbol
*/
SLONG
SLONG
getvaluefield(struct sSymbol * sym)
{
if (sym->Callback) {
@@ -49,7 +52,7 @@ getvaluefield(struct sSymbol * sym)
/*
* Calculate the hash value for a string
*/
ULONG
ULONG
calchash(char *s)
{
ULONG hash = 5381;
@@ -153,7 +156,7 @@ sym_FindSymbol(char *tzName)
/*
* Purge a symbol
*/
void
void
sym_Purge(char *tzName)
{
struct sSymbol **ppSym;
@@ -184,7 +187,7 @@ sym_Purge(char *tzName)
/*
* Determine if a symbol has been defined
*/
ULONG
ULONG
sym_isConstDefined(char *tzName)
{
struct sSymbol *psym, *pscope;
@@ -208,7 +211,7 @@ sym_isConstDefined(char *tzName)
return (0);
}
ULONG
ULONG
sym_isDefined(char *tzName)
{
struct sSymbol *psym, *pscope;
@@ -229,7 +232,7 @@ sym_isDefined(char *tzName)
/*
* Determine if the symbol is a constant
*/
ULONG
ULONG
sym_isConstant(char *s)
{
struct sSymbol *psym, *pscope;
@@ -266,7 +269,7 @@ sym_GetStringValue(char *tzSym)
/*
* Return a constant symbols value
*/
ULONG
ULONG
sym_GetConstantValue(char *s)
{
struct sSymbol *psym, *pscope;
@@ -292,7 +295,7 @@ sym_GetConstantValue(char *s)
/*
* Return a symbols value... "estimated" if not defined yet
*/
ULONG
ULONG
sym_GetValue(char *s)
{
struct sSymbol *psym, *pscope;
@@ -331,7 +334,7 @@ sym_GetValue(char *s)
/*
* Return a defined symbols value... aborts if not defined yet
*/
ULONG
ULONG
sym_GetDefinedValue(char *s)
{
struct sSymbol *psym, *pscope;
@@ -360,7 +363,7 @@ sym_GetDefinedValue(char *s)
/*
* Macro argument stuff
*/
void
void
sym_ShiftCurrentMacroArgs(void)
{
SLONG i;
@@ -378,12 +381,13 @@ sym_FindMacroArg(SLONG i)
if (i == -1)
i = MAXMACROARGS + 1;
assert(i-1 >= 0 &&
i-1 < sizeof currentmacroargs / sizeof *currentmacroargs);
assert(i-1 >= 0);
assert((size_t)(i-1) < sizeof(currentmacroargs)/sizeof(*currentmacroargs));
return (currentmacroargs[i - 1]);
}
void
void
sym_UseNewMacroArgs(void)
{
SLONG i;
@@ -394,7 +398,7 @@ sym_UseNewMacroArgs(void)
}
}
void
void
sym_SaveCurrentMacroArgs(char *save[])
{
SLONG i;
@@ -403,7 +407,7 @@ sym_SaveCurrentMacroArgs(char *save[])
save[i] = currentmacroargs[i];
}
void
void
sym_RestoreCurrentMacroArgs(char *save[])
{
SLONG i;
@@ -412,7 +416,7 @@ sym_RestoreCurrentMacroArgs(char *save[])
currentmacroargs[i] = save[i];
}
void
void
sym_FreeCurrentMacroArgs(void)
{
SLONG i;
@@ -423,7 +427,7 @@ sym_FreeCurrentMacroArgs(void)
}
}
void
void
sym_AddNewMacroArg(char *s)
{
SLONG i = 0;
@@ -440,7 +444,7 @@ sym_AddNewMacroArg(char *s)
yyerror("A maximum of %d arguments allowed", MAXMACROARGS);
}
void
void
sym_SetMacroArgID(ULONG nMacroCount)
{
char s[256];
@@ -449,7 +453,7 @@ sym_SetMacroArgID(ULONG nMacroCount)
newmacroargs[MAXMACROARGS] = strdup(s);
}
void
void
sym_UseCurrentMacroArgs(void)
{
SLONG i;
@@ -470,7 +474,7 @@ sym_FindMacro(char *s)
/*
* Add an equated symbol
*/
void
void
sym_AddEqu(char *tzSym, SLONG value)
{
if ((nPass == 1)
@@ -494,9 +498,18 @@ sym_AddEqu(char *tzSym, SLONG value)
}
/*
* Add a string equated symbol
* Add a string equated symbol.
*
* If the desired symbol is a string it needs to be passed to this function with
* quotes inside the string, like sym_AddString("name", "\"test\"), or the
* assembler won't be able to use it with DB and similar. This is equivalent as
* ``` name EQUS "\"test\"" ```
*
* If the desired symbol is a register or a number, just the terminator quotes
* of the string are enough: sym_AddString("M_PI", "3.1415"). This is the same
* as ``` M_PI EQUS "3.1415" ```
*/
void
void
sym_AddString(char *tzSym, char *tzValue)
{
struct sSymbol *nsym;
@@ -522,7 +535,7 @@ sym_AddString(char *tzSym, char *tzValue)
/*
* check if symbol is a string equated symbol
*/
ULONG
ULONG
sym_isString(char *tzSym)
{
struct sSymbol *pSym;
@@ -537,7 +550,7 @@ sym_isString(char *tzSym)
/*
* Alter a SET symbols value
*/
void
void
sym_AddSet(char *tzSym, SLONG value)
{
struct sSymbol *nsym;
@@ -556,7 +569,7 @@ sym_AddSet(char *tzSym, SLONG value)
/*
* Add a local (.name) relocatable symbol
*/
void
void
sym_AddLocalReloc(char *tzSym)
{
if ((nPass == 1)
@@ -590,7 +603,7 @@ sym_AddLocalReloc(char *tzSym)
/*
* Add a relocatable symbol
*/
void
void
sym_AddReloc(char *tzSym)
{
if ((nPass == 1)
@@ -618,10 +631,53 @@ sym_AddReloc(char *tzSym)
pScope = findsymbol(tzSym, NULL);
}
/*
* Check if the subtraction of two symbols is defined. That is, either both
* symbols are defined and the result is a constant, or both symbols are
* relocatable and belong to the same section.
*
* It returns 1 if the difference is defined, 0 if not.
*/
int
sym_IsRelocDiffDefined(char *tzSym1, char *tzSym2)
{
/* Do nothing the first pass. */
if (nPass != 2)
return 1;
struct sSymbol *nsym1, *nsym2;
/* Do the symbols exist? */
if ((nsym1 = sym_FindSymbol(tzSym1)) == NULL)
fatalerror("Symbol \"%s\" isn't defined.", tzSym1);
if ((nsym2 = sym_FindSymbol(tzSym2)) == NULL)
fatalerror("Symbol \"%s\" isn't defined.", tzSym2);
int s1reloc = (nsym1->nType & SYMF_RELOC) != 0;
int s2reloc = (nsym2->nType & SYMF_RELOC) != 0;
/* Both are non-relocatable */
if (!s1reloc && !s2reloc) return 1;
/* One of them relocatable, the other one not. */
if (s1reloc ^ s2reloc) return 0;
/* Both of them are relocatable. Make sure they are defined (internal
* coherency with sym_AddReloc and sym_AddLocalReloc). */
if (!(nsym1->nType & SYMF_DEFINED))
fatalerror("Relocatable symbol \"%s\" isn't defined.", tzSym1);
if (!(nsym2->nType & SYMF_DEFINED))
fatalerror("Relocatable symbol \"%s\" isn't defined.", tzSym2);
/* Both of them must be in the same section for the difference to be
* defined. */
return nsym1->pSection == nsym2->pSection;
}
/*
* Export a symbol
*/
void
void
sym_Export(char *tzSym)
{
if (nPass == 1) {
@@ -645,28 +701,10 @@ sym_Export(char *tzSym)
}
/*
* Import a symbol
*/
void
sym_Import(char *tzSym)
{
if (nPass == 1) {
/* only import symbols in pass 1 */
struct sSymbol *nsym;
if (findsymbol(tzSym, NULL)) {
yyerror("'%s' already defined", tzSym);
}
if ((nsym = createsymbol(tzSym)) != NULL)
nsym->nType |= SYMF_IMPORT;
}
}
/*
* Globalize a symbol (export if defined, import if not)
*/
void
void
sym_Global(char *tzSym)
{
if (nPass == 2) {
@@ -691,7 +729,7 @@ sym_Global(char *tzSym)
/*
* Add a macro definition
*/
void
void
sym_AddMacro(char *tzSym)
{
if ((nPass == 1)
@@ -716,7 +754,7 @@ sym_AddMacro(char *tzSym)
}
}
/*
/*
* Set whether to export all relocable symbols by default
*/
void sym_SetExportAll(BBOOL set) {
@@ -726,7 +764,7 @@ void sym_SetExportAll(BBOOL set) {
/*
* Prepare for pass #1
*/
void
void
sym_PrepPass1(void)
{
sym_Init();
@@ -735,7 +773,7 @@ sym_PrepPass1(void)
/*
* Prepare for pass #2
*/
void
void
sym_PrepPass2(void)
{
SLONG i;
@@ -760,23 +798,25 @@ sym_PrepPass2(void)
sym_AddString("__TIME__", SavedTIME);
sym_AddString("__DATE__", SavedDATE);
sym_AddString("__ISO_8601_LOCAL__", SavedTIMESTAMP_ISO8601_LOCAL);
sym_AddString("__ISO_8601_UTC__", SavedTIMESTAMP_ISO8601_UTC);
sym_AddSet("_RS", 0);
sym_AddEqu("_NARG", 0);
p_NARGSymbol = findsymbol("_NARG", NULL);
p_NARGSymbol->Callback = Callback_NARG;
math_DefinePI();
}
/*
* Initialize the symboltable
*/
void
void
sym_Init(void)
{
SLONG i;
time_t tod;
time_t now;
for (i = 0; i < MAXMACROARGS; i += 1) {
currentmacroargs[i] = NULL;
@@ -794,15 +834,32 @@ sym_Init(void)
sym_AddSet("_RS", 0);
if (time(&tod) != -1) {
struct tm *tptr;
if (time(&now) != -1) {
struct tm *time_local = localtime(&now);
tptr = localtime(&tod);
strftime(SavedTIME, sizeof(SavedTIME), "%H:%M:%S", tptr);
strftime(SavedDATE, sizeof(SavedDATE), "%d %B %Y", tptr);
sym_AddString("__TIME__", SavedTIME);
sym_AddString("__DATE__", SavedDATE);
strftime(SavedTIME, sizeof(SavedTIME), "\"%H:%M:%S\"", time_local);
strftime(SavedDATE, sizeof(SavedDATE), "\"%d %B %Y\"", time_local);
strftime(SavedTIMESTAMP_ISO8601_LOCAL,
sizeof(SavedTIMESTAMP_ISO8601_LOCAL), "\"%FT%T%z\"", time_local);
struct tm *time_utc = gmtime(&now);
strftime(SavedTIMESTAMP_ISO8601_UTC,
sizeof(SavedTIMESTAMP_ISO8601_UTC), "\"%FT%TZ\"", time_utc);
} else {
warnx("Couldn't determine current time.");
/* The '?' have to be escaped or they will be treated as
* trigraphs... */
strcpy(SavedTIME, "\"\?\?:\?\?:\?\?\"");
strcpy(SavedDATE, "\"\?\? \?\?\? \?\?\?\?\"");
strcpy(SavedTIMESTAMP_ISO8601_LOCAL, "\"\?\?\?\?-\?\?-\?\?T\?\?:\?\?:\?\?+\?\?\?\?\"");
strcpy(SavedTIMESTAMP_ISO8601_UTC, "\"\?\?\?\?-\?\?-\?\?T\?\?:\?\?:\?\?Z\"");
}
sym_AddString("__TIME__", SavedTIME);
sym_AddString("__DATE__", SavedDATE);
sym_AddString("__ISO_8601_LOCAL__", SavedTIMESTAMP_ISO8601_LOCAL);
sym_AddString("__ISO_8601_UTC__", SavedTIMESTAMP_ISO8601_UTC);
pScope = NULL;
math_DefinePI();

28
src/extern/err.c vendored
View File

@@ -26,34 +26,46 @@
#include <stdlib.h>
#include "extern/err.h"
extern char *progname;
void rgbds_vwarn(const char *fmt, va_list ap)
{
fprintf (stderr, "%s: ", progname);
fprintf (stderr, "warning");
if (fmt) {
vfprintf(stderr, fmt, ap);
fputs (": ", stderr);
vfprintf(stderr, fmt, ap);
}
putc('\n', stderr);
perror(0);
}
void rgbds_vwarnx(const char *fmt, va_list ap)
{
fprintf (stderr, "%s: ", progname);
if (fmt) vfprintf(stderr, fmt, ap);
fprintf (stderr, "warning");
if (fmt) {
fputs (": ", stderr);
vfprintf(stderr, fmt, ap);
}
putc('\n', stderr);
}
noreturn void rgbds_verr(int status, const char *fmt, va_list ap)
{
vwarn(fmt, ap);
fprintf (stderr, "error");
if (fmt) {
fputs (": ", stderr);
vfprintf(stderr, fmt, ap);
}
putc('\n', stderr);
exit(status);
}
noreturn void rgbds_verrx(int status, const char *fmt, va_list ap)
{
vwarnx(fmt, ap);
fprintf (stderr, "error");
if (fmt) {
fputs (": ", stderr);
vfprintf(stderr, fmt, ap);
}
putc('\n', stderr);
exit(status);
}

View File

@@ -23,8 +23,6 @@
#include "extern/err.h"
char *progname;
static void
usage(void)
{
@@ -71,8 +69,6 @@ main(int argc, char *argv[])
int version; /* mask ROM version number */
int padvalue; /* to pad the rom with if it changes size */
progname = argv[0];
while ((ch = getopt(argc, argv, "Cci:jk:l:m:n:p:sr:t:v")) != -1) {
switch (ch) {
case 'C':

View File

@@ -1,4 +1,18 @@
.Dd February 26, 2015
.\" Copyright © 2010 Anthony J. Bentley <anthony@anjbe.name>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 16, 2017
.Dt RGBFIX 1
.Os RGBDS Manual
.Sh NAME
@@ -88,7 +102,10 @@ Set the title string
to a given string, truncated to at most 16 characters.
It is recommended to use 15 characters instead, to avoid clashing with the CGB
flag
.Pq Fl c No or Fl C .
.Po Fl c
or
.Fl C
.Pc .
If both this and the game ID are set, the game ID will overwrite the
overlapping portion of the title.
.It Fl v
@@ -135,5 +152,5 @@ SurvivalKids.gbc
.Sh HISTORY
.Nm
was originally released by Carsten S\(/orensen as a standalone program called
gbfix.
It was later integrated with the ASMotor package, which became RGBDS.
gbfix, and was later packaged in RGBDS by Justin Lloyd. It is now maintained by
a number of contributors at https://github.com/rednex/rgbds.

1824
src/gbz80.7 Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -19,8 +19,6 @@
#include <string.h>
#include "gfx/main.h"
char *progname;
static void
usage(void)
{
@@ -41,8 +39,6 @@ main(int argc, char *argv[])
char *ext;
const char *errmsg = "Warning: The PNG's %s setting is not the same as the setting defined on the command line.";
progname = argv[0];
if (argc == 1) {
usage();
}

View File

@@ -316,7 +316,7 @@ output_png_file(struct Options opts, struct PNGImage *png)
png_init_io(img, f);
png_write_info(img, png->info);
png_write_image(img, png->data);
png_write_end(img, NULL);

View File

@@ -1,4 +1,18 @@
.Dd $Mdocdate$
.\" Copyright © 2013 stag019 <stag019@gmail.com>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 8, 2017
.Dt RGBGFX 1
.Os RGBDS Manual
.Sh NAME
@@ -88,3 +102,5 @@ The following will do nothing:
was created by
.An stag019
to be included in RGBDS.
It is now maintained by a number of contributors at
https://github.com/rednex/rgbds.

2
src/link/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
parser.c
parser.h

View File

@@ -1,12 +1,14 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "extern/err.h"
#include "link/assign.h"
#include "link/mylink.h"
#include "link/main.h"
#include "link/script.h"
#include "link/symbol.h"
#include "link/assign.h"
struct sFreeArea {
SLONG nOrg;
@@ -30,7 +32,7 @@ SLONG MaxSBankUsed;
SLONG MaxVBankUsed;
const enum eSectionType SECT_MIN = SECT_WRAM0;
const enum eSectionType SECT_MAX = SECT_SRAM;
const enum eSectionType SECT_MAX = SECT_OAM;
const struct sSectionAttributes SECT_ATTRIBUTES[] = {
{"WRAM0", BANK_WRAM0, 0, 0, BANK_COUNT_WRAM0},
{"VRAM", BANK_VRAM, 0, 0, BANK_COUNT_VRAM},
@@ -38,7 +40,8 @@ const struct sSectionAttributes SECT_ATTRIBUTES[] = {
{"ROM0", BANK_ROM0, 0, 0, BANK_COUNT_ROM0},
{"HRAM", BANK_HRAM, 0, 0, BANK_COUNT_HRAM},
{"WRAMX", BANK_WRAMX, 0, 0, BANK_COUNT_WRAMX},
{"SRAM", BANK_SRAM, 0, 0, BANK_COUNT_SRAM}
{"SRAM", BANK_SRAM, 0, 0, BANK_COUNT_SRAM},
{"OAM", BANK_OAM, 0, 0, BANK_COUNT_OAM}
};
#define DOMAXBANK(x, y) {switch (x) { \
@@ -46,7 +49,7 @@ const struct sSectionAttributes SECT_ATTRIBUTES[] = {
case SECT_WRAMX: DOMAXWBANK(y); break; \
case SECT_SRAM: DOMAXSBANK(y); break; \
case SECT_VRAM: DOMAXVBANK(y); break; \
default: errx(1, "DOMAXBANK used with invalid parameters"); break; }}
default: break; }}
#define DOMAXRBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
#define DOMAXWBANK(x) {if( (x)>MaxWBankUsed ) MaxWBankUsed=(x);}
#define DOMAXSBANK(x) {if( (x)>MaxSBankUsed ) MaxSBankUsed=(x);}
@@ -60,7 +63,7 @@ ensureSectionTypeIsValid(enum eSectionType type)
}
}
SLONG
SLONG
area_Avail(SLONG bank)
{
SLONG r;
@@ -77,6 +80,40 @@ area_Avail(SLONG bank)
return (r);
}
SLONG
area_doAlloc(struct sFreeArea *pArea, SLONG org, SLONG size)
{
if (org >= pArea->nOrg && (org + size) <= (pArea->nOrg + pArea->nSize)) {
if (org == pArea->nOrg) {
pArea->nOrg += size;
pArea->nSize -= size;
return org;
} else {
if ((org + size) == (pArea->nOrg + pArea->nSize)) {
pArea->nSize -= size;
return org;
} else {
struct sFreeArea *pNewArea;
if ((pNewArea = malloc(sizeof(struct sFreeArea))) != NULL) {
*pNewArea = *pArea;
pNewArea->pPrev = pArea;
pArea->pNext = pNewArea;
pArea->nSize = org - pArea->nOrg;
pNewArea->nOrg = org + size;
pNewArea->nSize -= size + pArea->nSize;
return org;
} else {
err(1, NULL);
}
}
}
}
return -1;
}
SLONG
area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
{
@@ -84,39 +121,11 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
pArea = *ppArea;
while (pArea) {
if (org >= pArea->nOrg
&& (org + size - 1) <= (pArea->nOrg + pArea->nSize - 1)) {
if (org == pArea->nOrg) {
pArea->nOrg += size;
pArea->nSize -= size;
return 0;
} else {
if ((org + size - 1) ==
(pArea->nOrg + pArea->nSize - 1)) {
pArea->nSize -= size;
return 0;
} else {
struct sFreeArea *pNewArea;
if ((pNewArea =
malloc(sizeof(struct sFreeArea)))
!= NULL) {
*pNewArea = *pArea;
pNewArea->pPrev = pArea;
pArea->pNext = pNewArea;
pArea->nSize =
org - pArea->nOrg;
pNewArea->nOrg = org + size;
pNewArea->nSize -=
size + pArea->nSize;
return 0;
} else {
err(1, NULL);
}
}
}
SLONG result = area_doAlloc(pArea, org, size);
if (result != -1) {
return result;
}
ppArea = &(pArea->pNext);
pArea = *ppArea;
}
@@ -131,7 +140,7 @@ area_AllocAbsAnyBank(SLONG org, SLONG size, enum eSectionType type)
SLONG startBank = SECT_ATTRIBUTES[type].bank;
SLONG bankCount = SECT_ATTRIBUTES[type].bankCount;
for (int i = 0; i < bankCount; i++) {
if (area_AllocAbs(&BankFree[startBank + i], org, size) != -1) {
return startBank + i;
@@ -141,38 +150,42 @@ area_AllocAbsAnyBank(SLONG org, SLONG size, enum eSectionType type)
return -1;
}
SLONG
area_Alloc(struct sFreeArea ** ppArea, SLONG size)
{
SLONG
area_Alloc(struct sFreeArea ** ppArea, SLONG size, SLONG alignment) {
struct sFreeArea *pArea;
if (alignment < 1) {
alignment = 1;
}
pArea = *ppArea;
while (pArea) {
if (size <= pArea->nSize) {
SLONG r;
r = pArea->nOrg;
pArea->nOrg += size;
pArea->nSize -= size;
return (r);
SLONG org = pArea->nOrg;
if (org % alignment) {
org += alignment;
}
org -= org % alignment;
SLONG result = area_doAlloc(pArea, org, size);
if (result != -1) {
return result;
}
ppArea = &(pArea->pNext);
pArea = *ppArea;
}
return (-1);
return -1;
}
SLONG
area_AllocAnyBank(SLONG size, enum eSectionType type) {
area_AllocAnyBank(SLONG size, SLONG alignment, enum eSectionType type) {
ensureSectionTypeIsValid(type);
SLONG startBank = SECT_ATTRIBUTES[type].bank;
SLONG bankCount = SECT_ATTRIBUTES[type].bankCount;
for (int i = 0; i < bankCount; i++) {
SLONG org = area_Alloc(&BankFree[startBank + i], size);
SLONG org = area_Alloc(&BankFree[startBank + i], size, alignment);
if (org != -1) {
return ((startBank + i) << 16) | org;
}
@@ -182,44 +195,94 @@ area_AllocAnyBank(SLONG size, enum eSectionType type) {
}
struct sSection *
FindLargestSection(enum eSectionType type)
FindLargestSection(enum eSectionType type, bool bankFixed)
{
struct sSection *pSection, *r = NULL;
SLONG nLargest = 0;
SLONG nLargestAlignment = 0;
pSection = pSections;
while (pSection) {
if (pSection->oAssigned == 0 && pSection->Type == type) {
if (pSection->nByteSize > nLargest) {
if (pSection->oAssigned == 0 && pSection->Type == type && (bankFixed ^ (pSection->nBank == -1))) {
if (pSection->nAlign > nLargestAlignment || (pSection->nAlign == nLargestAlignment && pSection->nByteSize > nLargest)) {
nLargest = pSection->nByteSize;
nLargestAlignment = pSection->nAlign;
r = pSection;
}
}
pSection = pSection->pNext;
}
return r;
}
void
AssignBankedSections(enum eSectionType type)
int
IsSectionNameInUse(const char *name)
{
ensureSectionTypeIsValid(type);
struct sSection *pSection;
while ((pSection = FindLargestSection(type))) {
SLONG org;
pSection = pSections;
while (pSection) {
if (strcmp(pSection->pzName, name) == 0)
return 1;
if ((org = area_AllocAnyBank(pSection->nByteSize, type)) != -1) {
pSection->nOrg = org & 0xFFFF;
pSection->nBank = org >> 16;
pSection->oAssigned = 1;
DOMAXBANK(pSection->Type, pSection->nBank);
} else {
errx(1, "Unable to place %s section anywhere",
SECT_ATTRIBUTES[type].name);
}
pSection = pSection->pNext;
}
return 0;
}
int
IsSectionSameTypeBankAndFloating(const char *name, enum eSectionType type, int bank)
{
struct sSection *pSection;
pSection = pSections;
while (pSection) {
if (pSection->oAssigned == 0) {
if (strcmp(pSection->pzName, name) == 0) {
/* Section must be floating in source */
if (pSection->nOrg != -1 || pSection->nAlign != 1)
return 0;
/* It must have the same type in source and linkerscript */
if (pSection->Type != type)
return 0;
/* Bank number must be unassigned in source or equal */
if (pSection->nBank != -1 && pSection->nBank != bank)
return 0;
return 1;
}
}
pSection = pSection->pNext;
}
errx(1, "Section \"%s\" not found (or already used).\n", name);
}
unsigned int
AssignSectionAddressAndBankByName(const char *name, unsigned int address, int bank)
{
struct sSection *pSection;
pSection = pSections;
while (pSection) {
if (pSection->oAssigned == 0) {
if (strcmp(pSection->pzName, name) == 0) {
if (pSection->nOrg != -1 || pSection->nAlign != 1)
errx(1, "Section \"%s\" from linkerscript isn't floating.\n", name);
if (pSection->nBank != -1 && pSection->nBank != bank)
errx(1, "Section \"%s\" from linkerscript has different bank number than in the source.\n", name);
pSection->nOrg = address;
pSection->nBank = bank;
pSection->nAlign = -1;
return pSection->nByteSize;
}
}
pSection = pSection->pNext;
}
errx(1, "Section \"%s\" not found (or already used).\n", name);
}
bool
@@ -231,12 +294,79 @@ VerifyAndSetBank(struct sSection *pSection)
&& pSection->nBank < SECT_ATTRIBUTES[pSection->Type].minBank + SECT_ATTRIBUTES[pSection->Type].bankCount) {
pSection->nBank += SECT_ATTRIBUTES[pSection->Type].bank + SECT_ATTRIBUTES[pSection->Type].offset;
return true;
} else {
return false;
}
}
void
AssignFixedBankSections(enum eSectionType type)
{
ensureSectionTypeIsValid(type);
struct sSection *pSection;
while ((pSection = FindLargestSection(type, true))) {
if (VerifyAndSetBank(pSection) &&
(pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize, pSection->nAlign)) != -1) {
pSection->oAssigned = 1;
DOMAXBANK(pSection->Type, pSection->nBank);
} else {
if (pSection->nAlign <= 1) {
errx(1, "Unable to place '%s' (%s section) in bank $%02lX",
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank);
} else {
errx(1, "Unable to place '%s' (%s section) in bank $%02lX (with $%lX-byte alignment)",
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank, pSection->nAlign);
}
}
}
}
void
AssignFloatingBankSections(enum eSectionType type)
{
ensureSectionTypeIsValid(type);
struct sSection *pSection;
while ((pSection = FindLargestSection(type, false))) {
SLONG org;
if ((org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign, type)) != -1) {
if (options & OPT_OVERLAY) {
errx(1, "All sections must be fixed when using overlay");
}
pSection->nOrg = org & 0xFFFF;
pSection->nBank = org >> 16;
pSection->oAssigned = 1;
DOMAXBANK(pSection->Type, pSection->nBank);
} else {
const char *locality = "anywhere";
if (SECT_ATTRIBUTES[pSection->Type].bankCount > 1) {
locality = "in any bank";
}
if (pSection->nAlign <= 1) {
errx(1, "Unable to place '%s' (%s section) %s",
pSection->pzName, SECT_ATTRIBUTES[type].name, locality);
} else {
errx(1, "Unable to place '%s' (%s section) %s (with $%lX-byte alignment)",
pSection->pzName, SECT_ATTRIBUTES[type].name, locality, pSection->nAlign);
}
}
}
}
char *tzLinkerscriptName = NULL;
void
SetLinkerscriptName(char *tzLinkerscriptFile)
{
tzLinkerscriptName = tzLinkerscriptFile;
}
void
AssignSections(void)
{
@@ -260,7 +390,7 @@ AssignSections(void)
if (i == BANK_ROM0) {
/* ROM0 bank */
BankFree[i]->nOrg = 0x0000;
if (options & OPT_SMALL) {
if (options & OPT_TINY) {
BankFree[i]->nSize = 0x8000;
} else {
BankFree[i]->nSize = 0x4000;
@@ -268,19 +398,15 @@ AssignSections(void)
} else if (i >= BANK_ROMX && i < BANK_ROMX + BANK_COUNT_ROMX) {
/* Swappable ROM bank */
BankFree[i]->nOrg = 0x4000;
/*
* Now, this shouldn't really be necessary... but for
* good measure we'll do it anyway.
*/
if (options & OPT_SMALL) {
BankFree[i]->nSize = 0;
} else {
BankFree[i]->nSize = 0x4000;
}
BankFree[i]->nSize = 0x4000;
} else if (i == BANK_WRAM0) {
/* WRAM */
BankFree[i]->nOrg = 0xC000;
BankFree[i]->nSize = 0x1000;
if (options & OPT_CONTWRAM) {
BankFree[i]->nSize = 0x2000;
} else {
BankFree[i]->nSize = 0x1000;
}
} else if (i >= BANK_SRAM && i < BANK_SRAM + BANK_COUNT_SRAM) {
/* Swappable SRAM bank */
BankFree[i]->nOrg = 0xA000;
@@ -292,7 +418,14 @@ AssignSections(void)
} else if (i >= BANK_VRAM && i < BANK_VRAM + BANK_COUNT_VRAM) {
/* Swappable VRAM bank */
BankFree[i]->nOrg = 0x8000;
BankFree[i]->nSize = 0x2000;
if (options & OPT_DMG_MODE && i != BANK_VRAM) {
BankFree[i]->nSize = 0;
} else {
BankFree[i]->nSize = 0x2000;
}
} else if (i == BANK_OAM) {
BankFree[i]->nOrg = 0xFE00;
BankFree[i]->nSize = 0x00A0;
} else if (i == BANK_HRAM) {
/* HRAM */
BankFree[i]->nOrg = 0xFF80;
@@ -300,15 +433,24 @@ AssignSections(void)
} else {
errx(1, "(INTERNAL) Unknown bank type!");
}
MaxAvail[i] = BankFree[i]->nSize;
BankFree[i]->pPrev = NULL;
BankFree[i]->pNext = NULL;
}
/*
* First, let's assign all the fixed sections...
* And all because of that Jens Restemeier character ;)
* First, let's parse the linkerscript.
*
*/
if (tzLinkerscriptName) {
script_InitSections();
script_Parse(tzLinkerscriptName);
}
/*
* Second, let's assign all the fixed sections...
*
*/
@@ -322,12 +464,12 @@ AssignSections(void)
case SECT_WRAM0:
case SECT_HRAM:
case SECT_ROM0:
case SECT_OAM:
pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank;
if (area_AllocAbs(&BankFree[pSection->nBank], pSection->nOrg,
pSection->nByteSize) == -1) {
errx(1, "Unable to load fixed %s section at $%lX",
SECT_ATTRIBUTES[pSection->Type].name,
pSection->nOrg);
errx(1, "Unable to place '%s' (%s section) at $%lX",
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg);
}
pSection->oAssigned = 1;
break;
@@ -342,8 +484,8 @@ AssignSections(void)
DOMAXBANK(pSection->Type, pSection->nBank);
pSection->oAssigned = 1;
} else {
errx(1,
"Unable to load fixed %s section at $%lX in bank $%02lX", SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg, pSection->nBank);
errx(1, "Unable to place '%s' (%s section) at $%lX in bank $%02lX",
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg, pSection->nBank);
}
}
break;
@@ -353,35 +495,11 @@ AssignSections(void)
}
/*
* Next, let's assign all the bankfixed ONLY ROMX sections...
* Next, let's assign all the bankfixed ONLY sections...
*
*/
pSection = pSections;
while (pSection) {
if (pSection->oAssigned == 0
&& pSection->nOrg == -1 && pSection->nBank != -1) {
switch (pSection->Type) {
case SECT_ROMX:
case SECT_SRAM:
case SECT_VRAM:
case SECT_WRAMX:
if (VerifyAndSetBank(pSection) &&
(pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) != -1) {
pSection->oAssigned = 1;
DOMAXBANK(pSection->Type, pSection->nBank);
} else {
errx(1, "Unable to load fixed %s section into bank $%02lX",
SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank);
}
break;
default: // Handle other sections later
break;
}
}
pSection = pSection->pNext;
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) {
AssignFixedBankSections(i);
}
/*
@@ -393,6 +511,9 @@ AssignSections(void)
while (pSection) {
if (pSection->oAssigned == 0
&& pSection->nOrg != -1 && pSection->nBank == -1) {
if (options & OPT_OVERLAY) {
errx(1, "All sections must be fixed when using overlay");
}
switch (pSection->Type) {
case SECT_ROMX:
case SECT_VRAM:
@@ -401,13 +522,13 @@ AssignSections(void)
if ((pSection->nBank =
area_AllocAbsAnyBank(pSection->nOrg, pSection->nByteSize,
pSection->Type)) == -1) {
errx(1, "Unable to load fixed %s section at $%lX into any bank",
SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg);
errx(1, "Unable to place '%s' (%s section) at $%lX in any bank",
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg);
}
pSection->oAssigned = 1;
DOMAXBANK(pSection->Type, pSection->nBank);
break;
default: // Handle other sections later
break;
}
@@ -421,44 +542,12 @@ AssignSections(void)
* sections
*
*/
pSection = pSections;
while (pSection) {
if (pSection->oAssigned == 0) {
switch (pSection->Type) {
case SECT_WRAM0:
case SECT_HRAM:
case SECT_ROM0:
pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank;
if ((pSection->nOrg =
area_Alloc(&BankFree[pSection->nBank],
pSection->nByteSize)) == -1) {
errx(1, "%s section too large", SECT_ATTRIBUTES[pSection->Type].name);
}
pSection->oAssigned = 1;
break;
case SECT_SRAM:
case SECT_VRAM:
case SECT_WRAMX:
case SECT_ROMX:
break;
default:
errx(1, "(INTERNAL) Unknown section type!");
break;
}
}
pSection = pSection->pNext;
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) {
AssignFloatingBankSections(i);
}
AssignBankedSections(SECT_ROMX);
AssignBankedSections(SECT_VRAM);
AssignBankedSections(SECT_WRAMX);
AssignBankedSections(SECT_SRAM);
}
void
void
CreateSymbolTable(void)
{
struct sSection *pSect;

192
src/link/lexer.l Normal file
View File

@@ -0,0 +1,192 @@
/*
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
%option noinput
%option yylineno
%{
#include <stdarg.h>
#include <unistd.h>
#include "extern/err.h"
#include "link/mylink.h"
#include "link/script.h"
#include "parser.h"
extern int yyparse();
/* File include stack. */
#define MAX_INCLUDE_DEPTH 8
static int include_stack_ptr = 0;
static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
static char include_path[MAX_INCLUDE_DEPTH][_MAX_PATH + 1];
static int include_line[MAX_INCLUDE_DEPTH];
static char linkerscript_path[_MAX_PATH + 1]; /* Base file */
%}
%%
\"([^\\\"]|\\.)*\" {
if (strlen(yytext) > sizeof(yylval.s) - 1)
script_fatalerror("String is too long: %s\n.", yytext);
if (strlen(yytext) < 3) /* 2 quotes + 1 character */
script_fatalerror("String %s is invalid\n.", yytext);
yytext++; /* ignore first quote */
strcpy(yylval.s, yytext);
yylval.s[strlen(yylval.s)-1] = '\0'; /* remove end quote */
return STRING;
}
\$[a-fA-F0-9]+ {
yytext++; /* Skip prefix */
yylval.i = strtol(yytext, NULL, 16);
return INTEGER;
}
[0-9]+ {
yylval.i = strtol(yytext, NULL, 10);
return INTEGER;
}
(?i:ROM0) { strcpy(yylval.s, "ROM0"); return SECTION_NONBANKED; }
(?i:ROMX) { strcpy(yylval.s, "ROMX"); return SECTION_BANKED; }
(?i:VRAM) { strcpy(yylval.s, "VRAM"); return SECTION_BANKED; }
(?i:WRAM0) { strcpy(yylval.s, "WRAM0"); return SECTION_NONBANKED; }
(?i:WRAMX) { strcpy(yylval.s, "WRAMX"); return SECTION_BANKED; }
(?i:SRAM) { strcpy(yylval.s, "SRAM"); return SECTION_BANKED; }
(?i:OAM) { strcpy(yylval.s, "OAM"); return SECTION_NONBANKED; }
(?i:HRAM) { strcpy(yylval.s, "HRAM"); return SECTION_NONBANKED; }
(?i:ALIGN) { return COMMAND_ALIGN; }
(?i:ORG) { return COMMAND_ORG; }
(?i:INCLUDE) { return COMMAND_INCLUDE; }
"\n" { return NEWLINE; }
;.* { /* Ignore comments. A dot doesn't match newline. */ }
[[:space:]] { /* Ignore whitespace. */ }
. { script_fatalerror("Invalid character [%s]\n.", yytext); }
%%
extern FILE *yyin;
void script_Parse(const char * path)
{
yyin = fopen(path, "r");
if (!yyin)
errx(1, "Error opening file! \"%s\"\n", path);
strncpy(linkerscript_path, path, sizeof(linkerscript_path));
linkerscript_path[sizeof(linkerscript_path) - 1] = '\0';
do {
yyparse();
} while (!feof(yyin));
fclose(yyin);
}
void script_IncludeFile(const char * path)
{
if (include_stack_ptr == (MAX_INCLUDE_DEPTH-1))
script_fatalerror("Includes nested too deeply.");
include_line[include_stack_ptr] = yylineno;
include_stack[include_stack_ptr] = YY_CURRENT_BUFFER;
include_stack_ptr++;
yyin = fopen(path, "r" );
if (!yyin)
script_fatalerror("Couldn't open file \"%s\"", path);
strncpy(include_path[include_stack_ptr], path, sizeof(include_path[0]));
include_path[include_stack_ptr][sizeof(include_path[0])-1] = '\0';
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
yylineno = 1;
/*
* The INCLUDE keyword is handled before reaching a newline token, it's
* handled right after parsing the string with the file name that has to
* be included. It isn't actually needed to include a newline after the
* path, the last line of the linkerscript doesn't need to have a
* newline character but it can have a command.
*
* This means that, when opening a new file, we must tell the parser
* that what it is going to start at a new line or it will think that
* the first line of the included script is the continuation of the
* INCLUDE line of the parent script. If this is not done, the first
* line of an included linkerscript can only be a comment (or empty).
*/
unput('\n');
}
int script_IncludeDepthGet(void)
{
return include_stack_ptr;
}
void script_IncludePop(void)
{
fclose(yyin);
include_stack_ptr--;
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(include_stack[include_stack_ptr]);
yylineno = include_line[include_stack_ptr];
}
void script_PrintFileStack(void)
{
int i = include_stack_ptr;
include_line[i] = yylineno;
while (i > 0) {
fprintf(stderr, "%s(%d) -> ", include_path[i], include_line[i]);
i--;
}
fprintf(stderr, "%s(%d)", linkerscript_path, include_line[i]);
}
noreturn void script_fatalerror(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
fprintf(stderr, "error: ");
script_PrintFileStack();
fprintf(stderr, ":\n\t");
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
exit(1);
}

View File

@@ -7,7 +7,7 @@
#include "link/mylink.h"
#include "link/main.h"
static BBOOL
static BBOOL
symboldefined(char *name)
{
struct sSection *pSect;
@@ -15,7 +15,7 @@ symboldefined(char *name)
pSect = pSections;
while (pSect) {
ULONG i;
int i;
for (i = 0; i < pSect->nNumberOfSymbols; i += 1) {
if ((pSect->tSymbols[i]->Type == SYM_EXPORT)
@@ -31,7 +31,7 @@ symboldefined(char *name)
return (0);
}
static BBOOL
static BBOOL
addmodulecontaining(char *name)
{
struct sSection **ppLSect;
@@ -39,7 +39,7 @@ addmodulecontaining(char *name)
ppLSect = &pLibSections;
while (*ppLSect) {
ULONG i;
int i;
for (i = 0; i < (*ppLSect)->nNumberOfSymbols; i += 1) {
if (((*ppLSect)->tSymbols[i]->Type == SYM_EXPORT)
@@ -66,7 +66,7 @@ addmodulecontaining(char *name)
return (0);
}
void
void
AddNeededModules(void)
{
struct sSection *pSect;
@@ -101,7 +101,7 @@ AddNeededModules(void)
pSect = pSections;
while (pSect) {
ULONG i;
int i;
for (i = 0; i < pSect->nNumberOfSymbols; i += 1) {
if ((pSect->tSymbols[i]->Type == SYM_IMPORT)

View File

@@ -24,19 +24,17 @@ SLONG options = 0;
SLONG fillchar = 0;
char *smartlinkstartsymbol;
char *progname;
/*
* Print the usagescreen
*
*/
static void
static void
usage(void)
{
printf(
"usage: rgblink [-t] [-m mapfile] [-n symfile] [-o outfile] [-p pad_value]\n"
" [-s symbol] file [...]\n");
"usage: rgblink [-twd] [-l linkerscript] [-m mapfile] [-n symfile] [-O overlay]\n"
" [-o outfile] [-p pad_value] [-s symbol] file [...]\n");
exit(1);
}
@@ -45,7 +43,7 @@ usage(void)
*
*/
int
int
main(int argc, char *argv[])
{
int ch;
@@ -54,10 +52,11 @@ main(int argc, char *argv[])
if (argc == 1)
usage();
progname = argv[0];
while ((ch = getopt(argc, argv, "m:n:o:p:s:t")) != -1) {
while ((ch = getopt(argc, argv, "l:m:n:o:O:p:s:twd")) != -1) {
switch (ch) {
case 'l':
SetLinkerscriptName(optarg);
break;
case 'm':
SetMapfileName(optarg);
break;
@@ -67,6 +66,10 @@ main(int argc, char *argv[])
case 'o':
out_Setname(optarg);
break;
case 'O':
out_SetOverlayname(optarg);
options |= OPT_OVERLAY;
break;
case 'p':
fillchar = strtoul(optarg, &ep, 0);
if (optarg[0] == '\0' || *ep != '\0') {
@@ -82,7 +85,26 @@ main(int argc, char *argv[])
smartlinkstartsymbol = optarg;
break;
case 't':
options |= OPT_SMALL;
options |= OPT_TINY;
break;
case 'd':
/*
* Set to set WRAM as a single continuous block as on
* DMG. All WRAM sections must be WRAM0 as bankable WRAM
* sections do not exist in this mode. A WRAMX section
* will raise an error. VRAM bank 1 can't be used if
* this option is enabled either.
*
* This option implies OPT_CONTWRAM.
*/
options |= OPT_DMG_MODE;
/* fallthrough */
case 'w':
/* Set to set WRAM as a single continuous block as on
* DMG. All WRAM sections must be WRAM0 as bankable WRAM
* sections do not exist in this mode. A WRAMX section
* will raise an error. */
options |= OPT_CONTWRAM;
break;
default:
usage();

View File

@@ -13,7 +13,7 @@ FILE *sf = NULL;
SLONG currentbank = 0;
SLONG sfbank;
void
void
SetMapfileName(char *name)
{
mf = fopen(name, "w");
@@ -23,7 +23,7 @@ SetMapfileName(char *name)
}
}
void
void
SetSymfileName(char *name)
{
sf = fopen(name, "w");
@@ -35,7 +35,7 @@ SetSymfileName(char *name)
fprintf(sf, ";File generated by rgblink\n\n");
}
void
void
CloseMapfile(void)
{
if (mf) {
@@ -48,7 +48,7 @@ CloseMapfile(void)
}
}
void
void
MapfileInitBank(SLONG bank)
{
if (mf) {
@@ -65,6 +65,8 @@ MapfileInitBank(SLONG bank)
fprintf(mf, "HRAM:\n");
else if (bank == BANK_VRAM || bank == BANK_VRAM + 1)
fprintf(mf, "VRAM Bank #%ld:\n", bank - BANK_VRAM);
else if (bank == BANK_OAM)
fprintf(mf, "OAM:\n");
else if (bank < MAXBANKS)
fprintf(mf, "SRAM Bank #%ld:\n", bank - BANK_SRAM);
}
@@ -79,6 +81,8 @@ MapfileInitBank(SLONG bank)
sfbank = 0;
else if (bank == BANK_VRAM || bank == BANK_VRAM + 1)
sfbank = bank - BANK_VRAM;
else if (bank == BANK_OAM)
sfbank = 0;
else if (bank < MAXBANKS)
sfbank = bank - BANK_SRAM;
else
@@ -86,15 +90,20 @@ MapfileInitBank(SLONG bank)
}
}
void
void
MapfileWriteSection(struct sSection * pSect)
{
SLONG i;
if (mf) {
fprintf(mf, " SECTION: $%04lX-$%04lX ($%04lX bytes)\n",
pSect->nOrg, pSect->nOrg + pSect->nByteSize - 1,
pSect->nByteSize);
if (pSect->nByteSize > 0) {
fprintf(mf, " SECTION: $%04lX-$%04lX ($%04lX bytes) [\"%s\"]\n",
pSect->nOrg, pSect->nOrg + pSect->nByteSize - 1,
pSect->nByteSize, pSect->pzName);
} else {
fprintf(mf, " SECTION: $%04lX ($0 bytes) [\"%s\"]\n",
pSect->nOrg, pSect->pzName);
}
}
for (i = 0; i < pSect->nNumberOfSymbols; i += 1) {
@@ -116,7 +125,7 @@ MapfileWriteSection(struct sSection * pSect)
}
}
void
void
MapfileCloseBank(SLONG slack)
{
if (!mf)

View File

@@ -9,6 +9,7 @@
#include <string.h>
#include "extern/err.h"
#include "link/assign.h"
#include "link/mylink.h"
#include "link/main.h"
@@ -23,7 +24,7 @@ BBOOL oReadLib = 0;
*
*/
SLONG
SLONG
readlong(FILE * f)
{
SLONG r;
@@ -36,7 +37,7 @@ readlong(FILE * f)
return (r);
}
UWORD
UWORD
readword(FILE * f)
{
UWORD r;
@@ -46,21 +47,41 @@ readword(FILE * f)
return (r);
}
/*
* Read a NULL terminated string from a file
*
*/
SLONG
readasciiz(char *s, FILE * f)
SLONG
readasciiz(char **dest, FILE *f)
{
SLONG r = 0;
size_t r = 0;
while (((*s++) = fgetc(f)) != 0)
size_t bufferLength = 16;
char *start = malloc(bufferLength);
char *s = start;
if (!s) {
err(1, NULL);
}
while (((*s++) = fgetc(f)) != 0) {
r += 1;
if (r >= bufferLength) {
bufferLength *= 2;
start = realloc(start, bufferLength);
if (!start) {
err(1, NULL);
}
s = start + r;
}
}
*dest = start;
return (r + 1);
}
/*
* Allocate a new section and link it into the list
*
@@ -97,7 +118,6 @@ AllocSection(void)
struct sSymbol *
obj_ReadSymbol(FILE * f)
{
char s[256];
struct sSymbol *pSym;
pSym = malloc(sizeof *pSym);
@@ -105,194 +125,50 @@ obj_ReadSymbol(FILE * f)
err(1, NULL);
}
readasciiz(s, f);
pSym->pzName = malloc(strlen(s) + 1);
if (!pSym->pzName) {
err(1, NULL);
}
strcpy(pSym->pzName, s);
readasciiz(&pSym->pzName, f);
if ((pSym->Type = (enum eSymbolType) fgetc(f)) != SYM_IMPORT) {
pSym->nSectionID = readlong(f);
pSym->nOffset = readlong(f);
}
return pSym;
}
/*
* RGB0 object reader routines
* RGB object reader routines
*
*/
struct sSection *
obj_ReadRGB0Section(FILE * f)
obj_ReadRGBSection(FILE * f)
{
struct sSection *pSection;
char *pzName;
readasciiz(&pzName, f);
if (IsSectionNameInUse(pzName))
errx(1, "Section name \"%s\" is already in use.", pzName);
pSection = AllocSection();
pSection->pzName = pzName;
pSection->nByteSize = readlong(f);
pSection->Type = (enum eSectionType) fgetc(f);
pSection->nOrg = -1;
pSection->nBank = -1;
/* does the user want the -s mode? */
if ((options & OPT_SMALL) && (pSection->Type == SECT_ROMX)) {
pSection->Type = SECT_ROM0;
}
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
/*
* These sectiontypes contain data...
*
*/
if (pSection->nByteSize) {
pSection->pData = malloc(pSection->nByteSize);
if (!pSection->pData) {
err(1, NULL);
}
SLONG nNumberOfPatches;
struct sPatch **ppPatch, *pPatch;
char s[256];
fread(pSection->pData, sizeof(UBYTE),
pSection->nByteSize, f);
nNumberOfPatches = readlong(f);
ppPatch = &pSection->pPatches;
/*
* And patches...
*
*/
while (nNumberOfPatches--) {
pPatch = malloc(sizeof *pPatch);
if (!pPatch) {
err(1, NULL);
}
*ppPatch = pPatch;
readasciiz(s, f);
pPatch->pzFilename = malloc(strlen(s) + 1);
if (!pPatch->pzFilename) {
err(1, NULL);
}
strcpy(pPatch->pzFilename, s);
pPatch->nLineNo =
readlong(f);
pPatch->nOffset =
readlong(f);
pPatch->Type =
(enum ePatchType)
fgetc(f);
if ((pPatch->nRPNSize = readlong(f)) > 0) {
pPatch->pRPN = malloc(pPatch->nRPNSize);
if (!pPatch->pRPN) {
err(1, NULL);
}
fread(pPatch->pRPN, sizeof(UBYTE),
pPatch->nRPNSize, f);
} else
pPatch->pRPN = NULL;
pPatch->pNext = NULL;
ppPatch = &(pPatch->pNext);
}
} else {
/* Skip number of patches */
readlong(f);
pSection->pData = &dummymem;
}
}
return pSection;
}
void
obj_ReadRGB0(FILE * pObjfile)
{
struct sSection *pFirstSection;
SLONG nNumberOfSymbols, nNumberOfSections, i;
nNumberOfSymbols = readlong(pObjfile);
nNumberOfSections = readlong(pObjfile);
/* First comes the symbols */
if (nNumberOfSymbols) {
tSymbols = malloc(nNumberOfSymbols * sizeof(struct sSymbol *));
if (!tSymbols) {
err(1, NULL);
}
for (i = 0; i < nNumberOfSymbols; i += 1)
tSymbols[i] = obj_ReadSymbol(pObjfile);
} else
tSymbols = (struct sSymbol **) & dummymem;
/* Next we have the sections */
pFirstSection = NULL;
while (nNumberOfSections--) {
struct sSection *pNewSection;
pNewSection = obj_ReadRGB0Section(pObjfile);
pNewSection->nNumberOfSymbols = nNumberOfSymbols;
if (pFirstSection == NULL)
pFirstSection = pNewSection;
}
/*
* Fill in the pSection entry in the symbolstructure.
* This REALLY needs some cleaning up... but, hey, it works
*
*/
for (i = 0; i < nNumberOfSymbols; i += 1) {
struct sSection *pConvSect = pFirstSection;
if (tSymbols[i]->Type != SYM_IMPORT
&& tSymbols[i]->nSectionID != -1) {
SLONG j = 0;
while (j != tSymbols[i]->nSectionID) {
j += 1;
pConvSect = pConvSect->pNext;
}
tSymbols[i]->pSection = pConvSect;
} else
tSymbols[i]->pSection = NULL;
}
}
/*
* RGB1 object reader routines
*
*/
struct sSection *
obj_ReadRGB1Section(FILE * f)
{
struct sSection *pSection;
pSection = AllocSection();
pSection->nByteSize = readlong(f);
pSection->Type = (enum eSectionType) fgetc(f);
/*
* And because of THIS new feature I'll have to rewrite loads and
* loads of stuff... oh well it needed to be done anyway
*
*/
pSection->nOrg = readlong(f);
pSection->nBank = readlong(f);
pSection->nAlign = readlong(f);
/* does the user want the -s mode? */
if ((options & OPT_SMALL) && (pSection->Type == SECT_ROMX)) {
pSection->Type = SECT_ROM0;
if ((options & OPT_TINY) && (pSection->Type == SECT_ROMX)) {
errx(1, "ROMX sections can't be used with option -t.");
}
if ((options & OPT_CONTWRAM) && (pSection->Type == SECT_WRAMX)) {
errx(1, "WRAMX sections can't be used with option -w.");
}
if (options & OPT_DMG_MODE) {
/* WRAMX sections are checked for OPT_CONTWRAM */
if (pSection->Type == SECT_VRAM && pSection->nBank == 1) {
errx(1, "VRAM bank 1 can't be used with option -w.");
}
}
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
/*
* These sectiontypes contain data...
@@ -306,7 +182,6 @@ obj_ReadRGB1Section(FILE * f)
SLONG nNumberOfPatches;
struct sPatch **ppPatch, *pPatch;
char s[256];
fread(pSection->pData, sizeof(UBYTE),
pSection->nByteSize, f);
@@ -324,13 +199,7 @@ obj_ReadRGB1Section(FILE * f)
}
*ppPatch = pPatch;
readasciiz(s, f);
pPatch->pzFilename = malloc(strlen(s) + 1);
if (!pPatch->pzFilename) {
err(1, NULL);
}
strcpy(pPatch->pzFilename, s);
readasciiz(&pPatch->pzFilename, f);
pPatch->nLineNo = readlong(f);
pPatch->nOffset = readlong(f);
pPatch->Type = (enum ePatchType) fgetc(f);
@@ -357,8 +226,8 @@ obj_ReadRGB1Section(FILE * f)
return pSection;
}
void
obj_ReadRGB1(FILE * pObjfile)
void
obj_ReadRGB(FILE * pObjfile)
{
struct sSection *pFirstSection;
SLONG nNumberOfSymbols, nNumberOfSections, i;
@@ -385,7 +254,7 @@ obj_ReadRGB1(FILE * pObjfile)
while (nNumberOfSections--) {
struct sSection *pNewSection;
pNewSection = obj_ReadRGB1Section(pObjfile);
pNewSection = obj_ReadRGBSection(pObjfile);
pNewSection->nNumberOfSymbols = nNumberOfSymbols;
if (pFirstSection == NULL)
pFirstSection = pNewSection;
@@ -417,7 +286,7 @@ obj_ReadRGB1(FILE * pObjfile)
*
*/
void
void
obj_ReadOpenFile(FILE * pObjfile, char *tzObjectfile)
{
char tzHeader[8];
@@ -426,23 +295,19 @@ obj_ReadOpenFile(FILE * pObjfile, char *tzObjectfile)
tzHeader[4] = 0;
if (strncmp(tzHeader, "RGB", 3) == 0) {
switch (tzHeader[3]) {
case '0':
obj_ReadRGB0(pObjfile);
break;
case '1':
case '2':
//V2 is really the same but the are new patch types
obj_ReadRGB1(pObjfile);
case '3':
case '4': // V4 supports OAM sections, but is otherwise identical
obj_ReadRGB(pObjfile);
break;
default:
errx(1, "'%s' is an unsupported version", tzObjectfile);
errx(1, "'%s' uses an unsupported object file version (%s). Please reassemble it.", tzObjectfile, tzHeader);
}
} else {
errx(1, "'%s' is not a valid object", tzObjectfile);
}
}
void
void
obj_Readfile(char *tzObjectfile)
{
FILE *pObjfile;
@@ -462,7 +327,7 @@ obj_Readfile(char *tzObjectfile)
oReadLib = 0;
}
SLONG
SLONG
file_Length(FILE * f)
{
ULONG r, p;
@@ -475,16 +340,16 @@ file_Length(FILE * f)
return (r);
}
void
void
lib_ReadXLB0(FILE * f)
{
SLONG size;
size = file_Length(f) - 4;
while (size) {
char name[256];
char *name;
size -= readasciiz(name, f);
size -= readasciiz(&name, f);
readword(f);
size -= 2;
readword(f);
@@ -492,5 +357,6 @@ lib_ReadXLB0(FILE * f)
size -= readlong(f);
size -= 4;
obj_ReadOpenFile(f, name);
free(name);
}
}

View File

@@ -8,9 +8,12 @@
#include "link/assign.h"
char *tzOutname;
char *tzOverlayname = NULL;
void
writehome(FILE * f)
SLONG MaxOverlayBank;
void
writehome(FILE * f, FILE * f_overlay)
{
struct sSection *pSect;
UBYTE *mem;
@@ -19,14 +22,19 @@ writehome(FILE * f)
if (!mem)
return;
memset(mem, fillchar, MaxAvail[BANK_ROM0]);
if (f_overlay != NULL) {
fseek(f_overlay, 0L, SEEK_SET);
fread(mem, 1, MaxAvail[BANK_ROM0], f_overlay);
} else {
memset(mem, fillchar, MaxAvail[BANK_ROM0]);
}
MapfileInitBank(0);
pSect = pSections;
while (pSect) {
if (pSect->Type == SECT_ROM0) {
memcpy(mem + pSect->nOrg, pSect->pData,
pSect->nByteSize);
pSect->nByteSize);
MapfileWriteSection(pSect);
}
pSect = pSect->pNext;
@@ -38,8 +46,8 @@ writehome(FILE * f)
free(mem);
}
void
writebank(FILE * f, SLONG bank)
void
writebank(FILE * f, FILE * f_overlay, SLONG bank)
{
struct sSection *pSect;
UBYTE *mem;
@@ -48,14 +56,19 @@ writebank(FILE * f, SLONG bank)
if (!mem)
return;
memset(mem, fillchar, MaxAvail[bank]);
if (f_overlay != NULL && bank <= MaxOverlayBank) {
fseek(f_overlay, bank*0x4000, SEEK_SET);
fread(mem, 1, MaxAvail[bank], f_overlay);
} else {
memset(mem, fillchar, MaxAvail[bank]);
}
MapfileInitBank(bank);
pSect = pSections;
while (pSect) {
if (pSect->Type == SECT_ROMX && pSect->nBank == bank) {
memcpy(mem + pSect->nOrg - 0x4000, pSect->pData,
pSect->nByteSize);
pSect->nByteSize);
MapfileWriteSection(pSect);
}
pSect = pSect->pNext;
@@ -67,24 +80,57 @@ writebank(FILE * f, SLONG bank)
free(mem);
}
void
void
out_Setname(char *tzOutputfile)
{
tzOutname = tzOutputfile;
}
void
void
out_SetOverlayname(char *tzOverlayfile)
{
tzOverlayname = tzOverlayfile;
}
void
Output(void)
{
SLONG i;
FILE *f;
FILE *f_overlay = NULL;
if ((f = fopen(tzOutname, "wb"))) {
writehome(f);
if (tzOverlayname) {
f_overlay = fopen(tzOverlayname, "rb");
if (!f_overlay) {
fprintf(stderr, "Failed to open overlay file %s\n", tzOverlayname);
exit(1);
}
fseek(f_overlay, 0, SEEK_END);
if (ftell(f_overlay) % 0x4000 != 0) {
fprintf(stderr, "Overlay file must be aligned to 0x4000 bytes\n");
exit(1);
}
MaxOverlayBank = (ftell(f_overlay) / 0x4000) - 1;
if (MaxOverlayBank < 1) {
fprintf(stderr, "Overlay file be at least 0x8000 bytes\n");
exit(1);
}
if (MaxOverlayBank > MaxBankUsed) {
MaxBankUsed = MaxOverlayBank;
}
}
writehome(f, f_overlay);
for (i = 1; i <= MaxBankUsed; i += 1)
writebank(f, i);
writebank(f, f_overlay, i);
fclose(f);
if (tzOverlayname) {
fclose(f_overlay);
}
}
for (i = BANK_WRAM0; i < MAXBANKS; i++) {
struct sSection *pSect;

120
src/link/parser.y Normal file
View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
%{
#include <stdio.h>
#include "extern/err.h"
#include "link/script.h"
int yylex();
void yyerror(char *);
extern int yylineno;
%}
%union { int i; char s[512]; }
%token<i> INTEGER
%token<s> STRING
%token<s> SECTION_NONBANKED
%token<s> SECTION_BANKED
%token COMMAND_ALIGN
%token COMMAND_ORG
%token COMMAND_INCLUDE
%token NEWLINE
%start lines
%%
lines:
/* empty */
| lines line NEWLINE
;
line:
/* empty */
| statement
;
statement:
/* Statements to set the current section */
SECTION_NONBANKED {
script_SetCurrentSectionType($1, 0);
}
| SECTION_NONBANKED INTEGER {
script_fatalerror("Trying to assign a bank to a non-banked section.\n");
}
| SECTION_BANKED {
script_fatalerror("Banked section without assigned bank.\n");
}
| SECTION_BANKED INTEGER {
script_SetCurrentSectionType($1, $2);
}
/* Commands to adjust the address inside the current section */
| COMMAND_ALIGN INTEGER {
script_SetAlignment($2);
}
| COMMAND_ALIGN {
script_fatalerror("ALIGN keyword needs an argument.\n");
}
| COMMAND_ORG INTEGER {
script_SetAddress($2);
}
| COMMAND_ORG {
script_fatalerror("ORG keyword needs an argument.\n");
}
/* Section name */
| STRING {
script_OutputSection($1);
}
/* Include file */
| COMMAND_INCLUDE STRING {
script_IncludeFile($2);
}
/* End */
;
%%
extern int yylex();
extern int yyparse();
int yywrap(void)
{
if (script_IncludeDepthGet() == 0)
return 1;
script_IncludePop();
return 0;
}
void yyerror(char *s)
{
script_fatalerror("Linkerscript parse error: \"%s\"\n", s);
}

View File

@@ -13,19 +13,19 @@ SLONG rpnstack[256];
SLONG rpnp;
SLONG nPC;
void
void
rpnpush(SLONG i)
{
rpnstack[rpnp++] = i;
}
SLONG
SLONG
rpnpop(void)
{
return (rpnstack[--rpnp]);
}
SLONG
SLONG
getsymvalue(SLONG symid)
{
switch (pCurrentSection->tSymbols[symid]->Type) {
@@ -51,7 +51,7 @@ getsymvalue(SLONG symid)
errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
}
SLONG
SLONG
getsymbank(SLONG symid)
{
SLONG nBank;
@@ -68,18 +68,21 @@ getsymbank(SLONG symid)
errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
}
if (nBank == BANK_WRAM0) return 0;
if (nBank >= BANK_WRAMX && nBank <= (BANK_WRAMX+6))
if (nBank == BANK_WRAM0 || nBank == BANK_ROM0 || nBank == BANK_OAM ||
nBank == BANK_HRAM) {
return 0;
} else if (nBank >= BANK_WRAMX && nBank < (BANK_WRAMX + BANK_COUNT_WRAMX)) {
return nBank - BANK_WRAMX + 1;
if (nBank >= BANK_VRAM && nBank <= (BANK_VRAM+1))
} else if (nBank >= BANK_VRAM && nBank < (BANK_VRAM + BANK_COUNT_VRAM)) {
return nBank - BANK_VRAM;
if (nBank >= BANK_SRAM && nBank <= (BANK_SRAM+3))
} else if (nBank >= BANK_SRAM && nBank < (BANK_SRAM + BANK_COUNT_SRAM)) {
return nBank - BANK_SRAM;
}
return nBank;
}
SLONG
SLONG
calcrpn(struct sPatch * pPatch)
{
SLONG t, size;
@@ -175,15 +178,6 @@ calcrpn(struct sPatch * pPatch)
pPatch->pzFilename, pPatch->nLineNo);
}
break;
case RPN_PCEZP:
t = rpnpop();
rpnpush(t & 0xFF);
if (t < 0x2000 || t > 0x20FF) {
errx(1,
"%s(%ld) : Value must be in the ZP area",
pPatch->pzFilename, pPatch->nLineNo);
}
break;
case RPN_CONST:
/* constant */
t = (*rpn++);
@@ -212,35 +206,12 @@ calcrpn(struct sPatch * pPatch)
rpnpush(getsymbank(t));
size -= 4;
break;
case RPN_RANGECHECK:
{
SLONG low, high;
low = (*rpn++);
low |= (*rpn++) << 8;
low |= (*rpn++) << 16;
low |= (*rpn++) << 24;
high = (*rpn++);
high |= (*rpn++) << 8;
high |= (*rpn++) << 16;
high |= (*rpn++) << 24;
t = rpnpop();
if (t < low || t > high) {
errx(1,
"%s(%ld) : Value must be in the range [%ld;%ld]",
pPatch->pzFilename,
pPatch->nLineNo, low, high);
}
rpnpush(t);
size -= 8;
break;
}
}
}
return (rpnpop());
}
void
void
Patch(void)
{
struct sSection *pSect;
@@ -270,22 +241,12 @@ Patch(void)
}
break;
case PATCH_WORD_L:
case PATCH_WORD_B:
if (t >= -32768 && t <= 65535) {
t &= 0xFFFF;
if (pPatch->Type == PATCH_WORD_L) {
pSect->pData[pPatch->nOffset] =
t & 0xFF;
pSect->pData[pPatch->nOffset +
1] =
(t >> 8) & 0xFF;
} else {
//Assume big endian
pSect->pData[pPatch->nOffset] =
(t >> 8) & 0xFF;
pSect->pData[pPatch->nOffset +
1] = t & 0xFF;
}
pSect->pData[pPatch->nOffset] =
t & 0xFF;
pSect->pData[pPatch->nOffset + 1] =
(t >> 8) & 0xFF;
} else {
errx(1,
"%s(%ld) : Value must be 16-bit",
@@ -302,15 +263,6 @@ Patch(void)
pSect->pData[pPatch->nOffset + 3] =
(t >> 24) & 0xFF;
break;
case PATCH_LONG_B:
pSect->pData[pPatch->nOffset + 0] =
(t >> 24) & 0xFF;
pSect->pData[pPatch->nOffset + 1] =
(t >> 16) & 0xFF;
pSect->pData[pPatch->nOffset + 2] =
(t >> 8) & 0xFF;
pSect->pData[pPatch->nOffset + 3] = t & 0xFF;
break;
}
pPatch = pPatch->pNext;

View File

@@ -1,4 +1,18 @@
.Dd February 26, 2015
.\" Copyright © 2010 Anthony J. Bentley <anthony@anjbe.name>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 17, 2017
.Dt RGBLINK 1
.Os RGBDS Manual
.Sh NAME
@@ -7,11 +21,15 @@
.Sh SYNOPSIS
.Nm rgblink
.Op Fl t
.Op Fl w
.Op Fl d
.Op Fl m Ar mapfile
.Op Fl n Ar symfile
.Op Fl O Ar overlayfile
.Op Fl o Ar outfile
.Op Fl p Ar pad_value
.Op Fl s Ar symbol
.Op Fl l Ar linkerscript
.Ar
.Sh DESCRIPTION
The
@@ -26,12 +44,29 @@ If your ROM will only be 32KiB, you can use the
.Fl t
option to override this.
.Pp
Similarly, WRAM0 sections are placed in the first 4KiB of WRAM bank 0 and WRAMX
sections are placed in any bank except bank 0.
If your ROM doesn't use banked WRAM you can use option
.Fl w
option to override this.
.Pp
Also, if your ROM is designed for DMG, you can make sure that you don't use any
prohibited section by using the option
.Fl d ,
which implies
.Fl w
but also prohibits the use of VRAM bank 1.
.Pp
The arguments are as follows:
.Bl -tag -width Ds
.It Fl m Ar mapfile
Write a mapfile to the given filename.
.It Fl n Ar symfile
Write a symbol file to the given filename.
.It Fl O Ar overlayfile
The ROM image to overlay sections over.
When an overlay ROM is provided, all sections must be fixed.
This may be used to patch an existing binray.
.It Fl o Ar outfile
Write ROM image to the given filename.
.It Fl p Ar pad_value
@@ -39,12 +74,27 @@ When padding an image, pad with this value.
The default is 0x00.
.It Fl s Ar symbol
???
.It Fl w
Expand the WRAM0 section size from 4KiB to the full 8KiB assigned to WRAM and
prohibit the use of WRAMX sections.
.It Fl d
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
.Fl w .
.It Fl t
Write a tiny
.Pq 32KiB
ROM file.
This forces all ROMX sections to be of type ROM0, and increases the ROM0
section size from 16KiB to 32KiB.
Expand the ROM0 section size from 16KiB to the full 32KiB assigned to ROM and
prohibit the use of ROMX sections.
Useful for ROMs that fit in 32 KiB.
.It Fl l Ar linkerscript
Specify a linkerscript file that tells the linker how sections must be placed in
the ROM.
This file has priority over the attributes assigned in the source code, but they
have to be consistent.
See
.Xr rgblink 5
for more information about its format.
.El
.Sh EXAMPLES
All you need for a basic ROM is an object file, which can be made into a ROM
@@ -61,9 +111,12 @@ to fix these so that the program will actually run in a Game Boy:
.D1 $ rgbfix -v bar.gb
.Sh SEE ALSO
.Xr rgbasm 1 ,
.Xr rgblink 5 ,
.Xr rgbfix 1 ,
.Xr rgbds 5 ,
.Xr rgbds 7
.Sh HISTORY
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd.
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
number of contributors at https://github.com/rednex/rgbds.

101
src/link/rgblink.5 Normal file
View File

@@ -0,0 +1,101 @@
.\" Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 17, 2017
.Dt RGBLINK 5
.Os RGBDS Manual
.Sh NAME
.Nm rgblink
.Nd linkerscript file format
.Sh DESCRIPTION
The linkerscript is an external file that allows the user to specify the
order of sections without the need for doing so before assembling each object
file.
.Pp
The placement of sections specified in the linkerscript is done before the
sections whose placement is defined in the source code.
.Pp
A linkerscript 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
.Ql \&;
that ends at the end of the line:
.Pp
.Bd -literal -offset indent
ROMX $F ; This is a comment
"Functions to read array"
ALIGN 8
"Array aligned to 256 bytes"
WRAMX 2
"Some variables"
.Ed
.Pp
Numbers can be in decimal or hexadecimal format (the prefix is
.Ql $ ) .
It is an error if any bank or command is found before setting a bank.
.Pp
Files can be included by using the
.Ar INCLUDE
keyword followed by a string with the path of the file that has to be included.
.Pp
The possible bank types are:
.Sy ROM0 , ROMX , VRAM , WRAM0 , WRAMX , OAM
and
.Sy HRAM .
Types
.Sy ROMX , VRAM , WRAMX
and
.Sy SRAM
are banked, which means that it is needed to specify a bank after the type.
.Pp
When a new bank statement is found, sections found after it will be placed
right from the beginning of that bank.
If the linkerscript switches to a different bank and then it comes back to the
previous one it will continue from the last address that was used.
.Pp
The only two commands are
.Ar ORG
and
.Ar ALIGN :
.Bl -bullet
.It
.Ar ORG
sets the address in which new sections will be placed.
It can not be lower than the current address.
.It
.Ar ALIGN
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:
.Sy ALIGN 8
will align to $100).
.El
.Pp
Note: The bank, alignment, address and type of sections can be specified both
in the source code and in the linkerscript.
For a section to be able to be placed with the linkerscript the bank must be
left unassigned in the source code or be the same as the one specified in the
linkerscript. The address and alignment musn't be set.
.Sh SEE ALSO
.Xr rgbasm 1 ,
.Xr rgblink 1 ,
.Xr rgbfix 1 ,
.Xr rgbds 5 ,
.Xr rgbds 7
.Sh HISTORY
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
number of contributors at https://github.com/rednex/rgbds.

216
src/link/script.c Normal file
View File

@@ -0,0 +1,216 @@
/*
* Copyright (C) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <string.h>
#include "extern/err.h"
#include "link/assign.h"
#include "link/mylink.h"
static struct {
unsigned int address; /* current address to write sections to */
unsigned int top_address; /* not inclusive */
enum eSectionType type;
} bank[MAXBANKS];
static int current_bank = -1; /* Bank as seen by the bank array */
static int current_real_bank = -1; /* bank as seen by the GB */
void script_InitSections(void)
{
int i;
for (i = 0; i < MAXBANKS; i++) {
if (i == BANK_ROM0) {
/* ROM0 bank */
bank[i].address = 0x0000;
if (options & OPT_TINY) {
bank[i].top_address = 0x8000;
} else {
bank[i].top_address = 0x4000;
}
bank[i].type = SECT_ROM0;
} else if (i >= BANK_ROMX && i < BANK_ROMX + BANK_COUNT_ROMX) {
/* Swappable ROM bank */
bank[i].address = 0x4000;
bank[i].top_address = 0x8000;
bank[i].type = SECT_ROMX;
} else if (i == BANK_WRAM0) {
/* WRAM */
bank[i].address = 0xC000;
if (options & OPT_CONTWRAM) {
bank[i].top_address = 0xE000;
} else {
bank[i].top_address = 0xD000;
}
bank[i].type = SECT_WRAM0;
} else if (i >= BANK_SRAM && i < BANK_SRAM + BANK_COUNT_SRAM) {
/* Swappable SRAM bank */
bank[i].address = 0xA000;
bank[i].top_address = 0xC000;
bank[i].type = SECT_SRAM;
} else if (i >= BANK_WRAMX && i < BANK_WRAMX + BANK_COUNT_WRAMX) {
/* Swappable WRAM bank */
bank[i].address = 0xD000;
bank[i].top_address = 0xE000;
bank[i].type = SECT_WRAMX;
} else if (i >= BANK_VRAM && i < BANK_VRAM + BANK_COUNT_VRAM) {
/* Swappable VRAM bank */
bank[i].address = 0x8000;
bank[i].type = SECT_VRAM;
if (options & OPT_DMG_MODE && i != BANK_VRAM) {
/* In DMG the only available bank is bank 0. */
bank[i].top_address = 0x8000;
} else {
bank[i].top_address = 0xA000;
}
} else if (i == BANK_OAM) {
/* OAM */
bank[i].address = 0xFE00;
bank[i].top_address = 0xFEA0;
bank[i].type = SECT_OAM;
} else if (i == BANK_HRAM) {
/* HRAM */
bank[i].address = 0xFF80;
bank[i].top_address = 0xFFFF;
bank[i].type = SECT_HRAM;
} else {
errx(1, "(INTERNAL) Unknown bank type!");
}
}
}
void script_SetCurrentSectionType(const char *type, unsigned int bank)
{
if (strcmp(type, "ROM0") == 0) {
if (bank != 0)
errx(1, "(Internal) Trying to assign a bank number to ROM0.\n");
current_bank = BANK_ROM0;
current_real_bank = 0;
return;
} else if (strcmp(type, "ROMX") == 0) {
if (bank == 0)
errx(1, "ROMX index can't be 0.\n");
if (bank > BANK_COUNT_ROMX)
errx(1, "ROMX index too big (%d > %d).\n", bank, BANK_COUNT_ROMX);
current_bank = BANK_ROMX + bank - 1;
current_real_bank = bank;
return;
} else if (strcmp(type, "VRAM") == 0) {
if (bank >= BANK_COUNT_VRAM)
errx(1, "VRAM index too big (%d >= %d).\n", bank, BANK_COUNT_VRAM);
current_bank = BANK_VRAM + bank;
current_real_bank = bank;
return;
} else if (strcmp(type, "WRAM0") == 0) {
if (bank != 0)
errx(1, "(Internal) Trying to assign a bank number to WRAM0.\n");
current_bank = BANK_WRAM0;
current_real_bank = 0;
return;
} else if (strcmp(type, "WRAMX") == 0) {
if (bank == 0)
errx(1, "WRAMX index can't be 0.\n");
if (bank > BANK_COUNT_WRAMX)
errx(1, "WRAMX index too big (%d > %d).\n", bank, BANK_COUNT_WRAMX);
current_bank = BANK_WRAMX + bank - 1;
current_real_bank = bank - 1;
return;
} else if (strcmp(type, "SRAM") == 0) {
if (bank >= BANK_COUNT_SRAM)
errx(1, "SRAM index too big (%d >= %d).\n", bank, BANK_COUNT_SRAM);
current_bank = BANK_SRAM + bank;
current_real_bank = bank;
return;
} else if (strcmp(type, "OAM") == 0) {
if (bank != 0)
errx(1, "(Internal) Trying to assign a bank number to OAM.\n");
current_bank = BANK_OAM;
current_real_bank = 0;
return;
} else if (strcmp(type, "HRAM") == 0) {
if (bank != 0)
errx(1, "(Internal) Trying to assign a bank number to HRAM.\n");
current_bank = BANK_HRAM;
current_real_bank = 0;
return;
}
errx(1, "(Internal) Unknown section type \"%s\".\n", type);
}
void script_SetAddress(unsigned int addr)
{
if (current_bank == -1) {
errx(1, "Trying to set an address without assigned bank\n");
}
/* Make sure that we don't go back. */
if (bank[current_bank].address > addr) {
errx(1, "Trying to go to a previous address (0x%04X to 0x%04X)\n",
bank[current_bank].address, addr);
}
bank[current_bank].address = addr;
/* Make sure we don't overflow */
if (bank[current_bank].address >= bank[current_bank].top_address) {
errx(1, "Bank overflowed (0x%04X >= 0x%04X)\n",
bank[current_bank].address, bank[current_bank].top_address);
}
}
void script_SetAlignment(unsigned int alignment)
{
if (current_bank == -1) {
errx(1, "Trying to set an alignment without assigned bank\n");
}
if (alignment > 15) {
errx(1, "Trying to set an alignment too big: %d\n", alignment);
}
unsigned int size = 1 << alignment;
unsigned int mask = size - 1;
if (bank[current_bank].address & mask) {
bank[current_bank].address &= ~mask;
bank[current_bank].address += size;
}
/* Make sure we don't overflow */
if (bank[current_bank].address >= bank[current_bank].top_address) {
errx(1, "Bank overflowed (0x%04X >= 0x%04X)\n",
bank[current_bank].address, bank[current_bank].top_address);
}
}
void script_OutputSection(const char *section_name)
{
if (current_bank == -1) {
errx(1, "Trying to place section \"%s\" without assigned bank\n", section_name);
}
if (!IsSectionSameTypeBankAndFloating(section_name, bank[current_bank].type,
current_real_bank)) {
errx(1, "Different attributes for \"%s\" in source and linkerscript\n",
section_name);
}
/* Move section to its place. */
bank[current_bank].address +=
AssignSectionAddressAndBankByName(section_name,
bank[current_bank].address, current_real_bank);
}

View File

@@ -19,7 +19,7 @@ struct ISymbol {
struct ISymbol *tHash[HASHSIZE];
SLONG
SLONG
calchash(char *s)
{
SLONG r = 0;
@@ -29,7 +29,7 @@ calchash(char *s)
return (r % HASHSIZE);
}
void
void
sym_Init(void)
{
SLONG i;
@@ -37,7 +37,7 @@ sym_Init(void)
tHash[i] = NULL;
}
SLONG
SLONG
sym_GetValue(char *tzName)
{
if (strcmp(tzName, "@") == 0) {
@@ -58,7 +58,7 @@ sym_GetValue(char *tzName)
}
}
SLONG
SLONG
sym_GetBank(char *tzName)
{
struct ISymbol **ppSym;
@@ -75,7 +75,7 @@ sym_GetBank(char *tzName)
errx(1, "Unknown symbol '%s'", tzName);
}
void
void
sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank)
{
if (strcmp(tzName, "@") == 0)

190
src/rgbds.5 Normal file
View File

@@ -0,0 +1,190 @@
.\" Copyright (c) 2017 Antonio Nino Diaz <antonio_nd@outlook.com>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 17, 2017
.Dt RGBDS 5
.Os RGBDS Manual
.Sh NAME
.Nm rgbds
.Nd object file format documentation
.Sh DESCRIPTION
This is the description of the object files used by
.Xr rgbasm 1
and
.Xr rgblink 1 .
Please, note that the specifications may change.
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.
.Pp
.Sh FILE STRUCTURE
The following types are used:
.Pp
.Ar LONG
is a 32bit integer stored in littleendian format (Intel).
.Ar BYTE
is an 8bit integer.
.Ar STRING
is a 0terminated string of
.Ar BYTE .
.Pp
.Bd -literal
; Header
BYTE ID[4] ; "RGB4"
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 "Scope.Symbol".
BYTE Type ; 0 = LOCAL symbol only used in this file.
; 1 = IMPORT this symbol from elsewhere (unused).
; 2 = EXPORT this symbol to other objects.
IF Type != 1 ; If symbol is defined in this object file.
LONG SectionID ; The section number (of this object file) in which
; this symbol is defined.
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 number of low bits
; to leave as 0). -1 if not defined.
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 Line ; The line of the source file.
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.
LONG RPNSize ; Size of the buffer with the RPN.
; expression.
BYTE RPN[RPNSize] ; RPN expression. Definition below.
ENDR
ENDC
ENDR
.Ed
.Ss RPN DATA
Expressions in the object file are stored as RPN.
This is an expression of the form
.Do 2 5 + Dc .
This will first push the value
.Do 2 Dc to the stack.
Then
.Do 5 Dc .
The
.Do + Dc 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 BYTEs with some bytes being
special prefixes for integers and symbols.
.Pp
.Bl -column -offset indent ".Sy String" ".Sy String"
.It Sy Value Ta Sy Meaning
.It Li $00 Ta Li + operator
.It Li $01 Ta Li - operator
.It Li $02 Ta Li * operator
.It Li $03 Ta Li / operator
.It Li $04 Ta Li % operator
.It Li $05 Ta Li unary -
.It Li $06 Ta Li | operator
.It Li $07 Ta Li & operator
.It Li $08 Ta Li ^ operator
.It Li $09 Ta Li unary ~
.It Li $0A Ta Li && comparison
.It Li $0B Ta Li || comparison
.It Li $0C Ta Li unary !
.It Li $0D Ta Li == comparison
.It Li $0E Ta Li != comparison
.It Li $0F Ta Li > comparison
.It Li $10 Ta Li < comparison
.It Li $11 Ta Li >= comparison
.It Li $12 Ta Li <= comparison
.It Li $13 Ta Li << comparison
.It Li $14 Ta Li >> comparison
.It Li $15 Ta Li BANK()
function.
A symbol ID follows.
.It Li $16 Ta Li HRAMCheck.
Check if the value is in HRAM, AND it with 0xFF.
.It Li $80 Ta Ar LONG
integer follows.
.It Li $81 Ta Ar LONG
Symbol ID follows.
.El
.Pp
.Sh SEE ALSO
.Xr rgbasm 1 ,
.Xr rgblink 1 ,
.Xr rgbds 7 ,
.Xr gbz80 7
.Sh HISTORY
.Nm rgbds
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
https://github.com/rednex/rgbds.

View File

@@ -1,4 +1,18 @@
.Dd $Mdocdate$
.\" Copyright © 2010 Anthony J. Bentley <anthony@anjbe.name>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 17, 2017
.Dt RGBDS 7
.Os RGBDS Manual
.Sh NAME
@@ -14,8 +28,24 @@ To get a working ROM image from a single assembly source file:
.Xr rgbasm 1 ,
.Xr rgbfix 1 ,
.Xr rgblink 1 ,
.Xr rgbds 5 ,
.Xr gbz80 7
.Sh HISTORY
.Nm
grew out of the ASMotor package released by Carsten S\(/orensen.
It was first released as a Game Boy software package by Justin Lloyd.
.Bl -ohang
.It
1997, Carsten S\(/orensen (AKA SurfSmurf) writes ASMotor as a general-purpose
assembler/linker system for DOS/Win32.
.It
1999, Justin Lloyd (AKA Otaku no Zoku) adapts ASMotor to read and produce GBZ80
assembly/machine code, and releases this version as RGBDS.
.It
2009, Vegard Nossum adapts the code to be more UNIX-like and releases this
version as rgbds-linux on GitHub.
.It
2010, Anthony J. Bentley forks that repository. The fork becomes the reference
implementation of rgbds.
.It
2017, Bentley's repository is moved to a neutral name.
It is now maintained by a number of contributors at
https://github.com/rednex/rgbds
.El

View File

@@ -1,2 +0,0 @@
ERROR: bank-noexist.asm(2) :
'noexist' not defined

View File

@@ -1,2 +1,2 @@
ERROR: divzero-instr.asm(2) :
ERROR: divzero-instr.asm(2):
division by zero

View File

@@ -1,2 +1,2 @@
ERROR: divzero-section-bank.asm(1) :
ERROR: divzero-section-bank.asm(1):
division by zero

View File

@@ -1,2 +1,2 @@
ERROR: macro-@.asm(1) -> @(-1) :
ERROR: macro-@.asm(1) -> @(-1):
Macro '@' not defined

View File

@@ -0,0 +1,2 @@
ERROR: null-in-macro.asm(1):
Unterminated MACRO definition

4
test/asm/test.sh Normal file → Executable file
View File

@@ -1,6 +1,10 @@
fname=$(mktemp)
rc=0
for i in *.asm; do
../../rgbasm $i >$fname 2>&1
diff -u $fname ${i%.asm}.out
rc=$(($? || $rc))
done
exit $rc

View File

@@ -1,2 +1,3 @@
ERROR: undefined-dot.asm(3) :
ERROR: undefined-dot.asm(3):
'.' not defined
error: Assembly aborted in pass 2 (1 errors)!

8
test/asm/update-refs.sh Executable file
View File

@@ -0,0 +1,8 @@
fname=$(mktemp)
for i in *.asm; do
../../rgbasm $i >$fname 2>&1
mv -f $fname ${i%.asm}.out
done
exit 0

View File

@@ -0,0 +1,53 @@
section "x",rom0[$0000]
db bank(r0),bank(r1),bank(r2),bank(r3) ; Should be enough
db bank(v0),bank(v1)
db bank(w0),bank(w1),bank(w2),bank(w3),bank(w4),bank(w5),bank(w6),bank(w7)
db bank(s0),bank(s1),bank(s2),bank(s3) ; Should be enough
db bank(o0)
db bank(h0)
section "r0",rom0
r0:
section "r1",romx,bank[1]
r1:
section "r2",romx,bank[2]
r2:
section "r3",romx,bank[3]
r3:
section "v0",vram,bank[0]
v0:
section "v1",vram,bank[1]
v1:
section "s0",sram,bank[0]
s0:
section "s1",sram,bank[1]
s1:
section "s2",sram,bank[2]
s2:
section "s3",sram,bank[3]
s3:
section "w0",wram0
w0:
section "w1",wramx,bank[1]
w1:
section "w2",wramx,bank[2]
w2:
section "w3",wramx,bank[3]
w3:
section "w4",wramx,bank[4]
w4:
section "w5",wramx,bank[5]
w5:
section "w6",wramx,bank[6]
w6:
section "w7",wramx,bank[7]
w7:
section "o0",oam
o0:
section "h0",hram
h0:

View File

Binary file not shown.

22
test/link/high-low-a.asm Normal file
View File

@@ -0,0 +1,22 @@
ldhilo : MACRO
ld HIGH(\1),LOW(\2)
ENDM
SECTION "r0", ROM0[$0]
ld HIGH(af),a
ld HIGH(bc),LOW(bc)
ld LOW(bc),HIGH(bc)
ld HIGH(de),LOW(de)
ld LOW(de),HIGH(de)
ldhilo hl, hl
ld LOW(hl),HIGH(hl)
db HIGH(label+$AB)
db LOW(label+$AB)
db HIGH($1234)
db LOW($1234)
SECTION "o",OAM
DS $10
label:

18
test/link/high-low-b.asm Normal file
View File

@@ -0,0 +1,18 @@
SECTION "r0", ROM0[$0]
ld a,a
ld b,c
ld c,b
ld d,e
ld e,d
ld h,l
ld l,h
db ((label+$AB) >> 8) & $FF
db (label+$AB) & $FF
db ($1234 >> 8) & $FF
db $1234 & $FF
SECTION "o",OAM
DS $10
label:

View File

@@ -1,36 +0,0 @@
; this should generate a rom consisting of the following bytes:
; 01 02 03 04 05 06 07 00 01 02 03 00 01
section "x",rom0
db bank(w1),bank(w2),bank(w3),bank(w4),bank(w5),bank(w6),bank(w7)
db bank(s0),bank(s1),bank(s2),bank(s3)
db bank(v0),bank(v1)
section "wa",wramx,bank[1]
w1:
section "wb",wramx,bank[2]
w2:
section "wc",wramx,bank[3]
w3:
section "wd",wramx,bank[4]
w4:
section "we",wramx,bank[5]
w5:
section "wf",wramx,bank[6]
w6:
section "wg",wramx,bank[7]
w7:
section "sa",sram,bank[0]
s0:
section "sb",sram,bank[1]
s1:
section "sc",sram,bank[2]
s2:
section "sd",sram,bank[3]
s3:
section "v00",vram,bank[0]
v0:
section "v01",vram,bank[1]
v1:

View File

@@ -0,0 +1 @@
error: Unable to place 'r0b' (ROM0 section) anywhere

View File

@@ -0,0 +1 @@
error: ROMX sections can't be used with option -t.

8
test/link/romx-tiny.asm Normal file
View File

@@ -0,0 +1,8 @@
SECTION "r0a", ROM0
DS $4000
SECTION "rx", ROMX
DS $4000
SECTION "r0b", ROM0
DS $4000

57
test/link/test.sh Executable file
View File

@@ -0,0 +1,57 @@
otemp=$(mktemp)
gbtemp=$(mktemp)
gbtemp2=$(mktemp)
outtemp=$(mktemp)
rc=0
RGBASM=../../rgbasm
RGBLINK=../../rgblink
$RGBASM -o $otemp bank-numbers.asm
$RGBLINK -o $gbtemp $otemp > $outtemp 2>&1
diff bank-numbers.out $outtemp
rc=$(($? || $rc))
head -c 20 $gbtemp > $otemp 2>&1
diff bank-numbers.out.bin $otemp
rc=$(($? || $rc))
$RGBASM -o $otemp wramx-dmg-mode.asm
$RGBLINK -o $gbtemp $otemp > $outtemp 2>&1
diff wramx-dmg-mode-no-d.out $outtemp
rc=$(($? || $rc))
$RGBLINK -d -o $gbtemp $otemp > $outtemp 2>&1
diff wramx-dmg-mode-d.out $outtemp
rc=$(($? || $rc))
$RGBASM -o $otemp vram-fixed-dmg-mode.asm
$RGBLINK -o $gbtemp $otemp > $outtemp 2>&1
diff vram-fixed-dmg-mode-no-d.out $outtemp
rc=$(($? || $rc))
$RGBLINK -d -o $gbtemp $otemp > $outtemp 2>&1
diff vram-fixed-dmg-mode-d.out $outtemp
rc=$(($? || $rc))
$RGBASM -o $otemp vram-floating-dmg-mode.asm
$RGBLINK -o $gbtemp $otemp > $outtemp 2>&1
diff vram-floating-dmg-mode-no-d.out $outtemp
rc=$(($? || $rc))
$RGBLINK -d -o $gbtemp $otemp > $outtemp 2>&1
diff vram-floating-dmg-mode-d.out $outtemp
rc=$(($? || $rc))
$RGBASM -o $otemp romx-tiny.asm
$RGBLINK -o $gbtemp $otemp > $outtemp 2>&1
diff romx-tiny-no-t.out $outtemp
rc=$(($? || $rc))
$RGBLINK -t -o $gbtemp $otemp > $outtemp 2>&1
diff romx-tiny-t.out $outtemp
rc=$(($? || $rc))
$RGBASM -o $otemp high-low-a.asm
$RGBLINK -o $gbtemp $otemp
$RGBASM -o $otemp high-low-b.asm
$RGBLINK -o $gbtemp2 $otemp
diff $gbtemp $gbtemp2
rc=$(($? || $rc))
exit $rc

27
test/link/update-refs.sh Executable file
View File

@@ -0,0 +1,27 @@
otemp=$(mktemp)
gbtemp=$(mktemp)
RGBASM=../../rgbasm
RGBLINK=../../rgblink
$RGBASM -o $otemp bank-numbers.asm
$RGBLINK -o $gbtemp $otemp > bank-numbers.out 2>&1
head -c 20 $gbtemp > bank-numbers.out.bin 2>&1
$RGBASM -o $otemp wramx-dmg-mode.asm
$RGBLINK -o $gbtemp $otemp > wramx-dmg-mode-no-d.out 2>&1
$RGBLINK -d -o $gbtemp $otemp > wramx-dmg-mode-d.out 2>&1
$RGBASM -o $otemp vram-fixed-dmg-mode.asm
$RGBLINK -o $gbtemp $otemp > vram-fixed-dmg-mode-no-d.out 2>&1
$RGBLINK -d -o $gbtemp $otemp > vram-fixed-dmg-mode-d.out 2>&1
$RGBASM -o $otemp vram-floating-dmg-mode.asm
$RGBLINK -o $gbtemp $otemp > vram-floating-dmg-mode-no-d.out 2>&1
$RGBLINK -d -o $gbtemp $otemp > vram-floating-dmg-mode-d.out 2>&1
$RGBASM -o $otemp romx-tiny.asm
$RGBLINK -o $gbtemp $otemp > romx-tiny-no-t.out 2>&1
$RGBLINK -t -o $gbtemp $otemp > romx-tiny-t.out 2>&1
exit 0

View File

@@ -0,0 +1 @@
error: VRAM bank 1 can't be used with option -w.

View File

View File

@@ -0,0 +1,6 @@
SECTION "v0", VRAM, BANK[0]
DS $2000
SECTION "v1", VRAM, BANK[1]
DS $2000

View File

@@ -0,0 +1 @@
error: Unable to place 'v1' (VRAM section) in any bank

View File

@@ -0,0 +1,6 @@
SECTION "v0", VRAM
DS $2000
SECTION "v1", VRAM
DS $2000

View File

@@ -0,0 +1 @@
error: WRAMX sections can't be used with option -w.

View File

@@ -0,0 +1 @@
error: Unable to place 'w0b' (WRAM0 section) anywhere

View File

@@ -0,0 +1,8 @@
SECTION "w0a", WRAM0
DS $1000
SECTION "wx", WRAMX
DS $1000
SECTION "w0b", WRAM0
DS $1000