mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 02:32:06 +00:00
Compare commits
54 Commits
v0.4.2-pre
...
v0.4.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ede982b50a | ||
|
|
319d775c13 | ||
|
|
44124319a6 | ||
|
|
462fd7539c | ||
|
|
f16e34b804 | ||
|
|
c3ccdc548e | ||
|
|
fd721ca480 | ||
|
|
eac365aef0 | ||
|
|
4de6266442 | ||
|
|
213d985e17 | ||
|
|
de76dcb8fb | ||
|
|
30fb6bde5e | ||
|
|
4f842a1248 | ||
|
|
cc4d455b8a | ||
|
|
0bb5efebfd | ||
|
|
b6bf7ae620 | ||
|
|
dc96cc6d1e | ||
|
|
642daf1a76 | ||
|
|
84edfb3d88 | ||
|
|
7e620bff81 | ||
|
|
0c55703438 | ||
|
|
6c57ad2226 | ||
|
|
9028fb5391 | ||
|
|
12dc49b60a | ||
|
|
7e1d20acdf | ||
|
|
5230104852 | ||
|
|
55be77be69 | ||
|
|
42b3a17356 | ||
|
|
4e1d79081c | ||
|
|
4ce4fdec71 | ||
|
|
05256946ac | ||
|
|
73396166aa | ||
|
|
4c5d5c7085 | ||
|
|
045a9e8b93 | ||
|
|
4419f0d54f | ||
|
|
b07aa00d5c | ||
|
|
e4f5df1306 | ||
|
|
dc62d60e9b | ||
|
|
71d8aeb4c2 | ||
|
|
0836f67d42 | ||
|
|
176a57a1e9 | ||
|
|
0d02355dbf | ||
|
|
6767d11c23 | ||
|
|
2dd9015dc6 | ||
|
|
217c10ddac | ||
|
|
822e4e7c44 | ||
|
|
0b1d01792d | ||
|
|
01637768cf | ||
|
|
6a8ae643d5 | ||
|
|
fd83d46ba0 | ||
|
|
914856342c | ||
|
|
91889fc14a | ||
|
|
7c8ec5a5ed | ||
|
|
effc6788eb |
4
.github/actions/get-pages.sh
vendored
4
.github/actions/get-pages.sh
vendored
@@ -26,14 +26,12 @@ while getopts ":hr" opt; do
|
|||||||
;;
|
;;
|
||||||
\?)
|
\?)
|
||||||
echo "Unknown option '$OPTARG'"
|
echo "Unknown option '$OPTARG'"
|
||||||
if [ $bad_usage -eq 0 ]; then
|
|
||||||
usage
|
|
||||||
bad_usage=1
|
bad_usage=1
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
if [ $bad_usage -ne 0 ]; then
|
if [ $bad_usage -ne 0 ]; then
|
||||||
|
usage
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
shift $(($OPTIND - 1))
|
shift $(($OPTIND - 1))
|
||||||
|
|||||||
54
.github/workflows/create-release-docs.yml
vendored
Normal file
54
.github/workflows/create-release-docs.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
name: "Create release docs"
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout rgbds@master
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: gbdev/rgbds
|
||||||
|
ref: master
|
||||||
|
path: rgbds
|
||||||
|
- name: Checkout rgbds-www@master
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
repository: gbdev/rgbds-www
|
||||||
|
ref: master
|
||||||
|
path: rgbds-www
|
||||||
|
- name: Build and install mandoc
|
||||||
|
run: |
|
||||||
|
sudo apt-get -qq update
|
||||||
|
sudo apt-get install -yq zlib1g-dev
|
||||||
|
wget 'http://mandoc.bsd.lv/snapshots/mandoc-1.14.5.tar.gz'
|
||||||
|
tar xf mandoc-1.14.5.tar.gz
|
||||||
|
cd mandoc-1.14.5
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
sudo make install
|
||||||
|
- name: Update pages
|
||||||
|
working-directory: rgbds
|
||||||
|
run: |
|
||||||
|
./.github/actions/get-pages.sh ../rgbds-www/_documentation ${GITHUB_REF}
|
||||||
|
- name: Push new pages
|
||||||
|
working-directory: rgbds-www
|
||||||
|
run: |
|
||||||
|
mkdir -p -m 700 ~/.ssh
|
||||||
|
echo "${{ secrets.SSH_KEY_SECRET }}" > ~/.ssh/id_ed25519
|
||||||
|
chmod 0600 ~/.ssh/id_ed25519
|
||||||
|
eval $(ssh-agent -s)
|
||||||
|
ssh-add ~/.ssh/id_ed25519
|
||||||
|
git config --global user.name "GitHub Action"
|
||||||
|
git config --global user.email "community@gbdev.io"
|
||||||
|
git add .
|
||||||
|
git commit -m "Create RGBDS ${GITHUB_REF} documentation"
|
||||||
|
if git remote | grep -q origin; then
|
||||||
|
git remote set-url origin git@github.com:gbdev/rgbds-www.git
|
||||||
|
else
|
||||||
|
git remote add origin git@github.com:gbdev/rgbds-www.git
|
||||||
|
fi
|
||||||
|
git push origin master
|
||||||
1
.github/workflows/update-master-docs.yml
vendored
1
.github/workflows/update-master-docs.yml
vendored
@@ -17,7 +17,6 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
if: secrets.SSH_KEY_SECRET != ''
|
|
||||||
runs-on: ubuntu-18.04
|
runs-on: ubuntu-18.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout rgbds@master
|
- name: Checkout rgbds@master
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ include_directories("${PROJECT_SOURCE_DIR}/include")
|
|||||||
|
|
||||||
option(SANITIZERS "Build with sanitizers enabled" OFF)
|
option(SANITIZERS "Build with sanitizers enabled" OFF)
|
||||||
option(MORE_WARNINGS "Turn on more warnings" OFF)
|
option(MORE_WARNINGS "Turn on more warnings" OFF)
|
||||||
|
option(TRACE_PARSER "Trace parser execution" OFF)
|
||||||
|
option(TRACE_LEXER "Trace lexer execution" OFF)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_compile_options(/W1 /MP)
|
add_compile_options(/W1 /MP)
|
||||||
@@ -69,3 +71,11 @@ set(CMAKE_C_STANDARD 11)
|
|||||||
set(CMAKE_C_STANDARD_REQUIRED True)
|
set(CMAKE_C_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
|
if(TRACE_PARSER)
|
||||||
|
target_compile_definitions(rgbasm PRIVATE -DYYDEBUG)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(TRACE_LEXER)
|
||||||
|
target_compile_definitions(rgbasm PRIVATE -DLEXER_DEBUG)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ FROM alpine:latest
|
|||||||
RUN apk add --update \
|
RUN apk add --update \
|
||||||
build-base \
|
build-base \
|
||||||
byacc \
|
byacc \
|
||||||
flex \
|
|
||||||
libpng-dev
|
libpng-dev
|
||||||
COPY . /rgbds
|
COPY . /rgbds
|
||||||
WORKDIR /rgbds
|
WORKDIR /rgbds
|
||||||
|
|||||||
6
Makefile
6
Makefile
@@ -53,13 +53,13 @@ RM := rm -rf
|
|||||||
all: rgbasm rgblink rgbfix rgbgfx
|
all: rgbasm rgblink rgbfix rgbgfx
|
||||||
|
|
||||||
rgbasm_obj := \
|
rgbasm_obj := \
|
||||||
src/asm/asmy.o \
|
|
||||||
src/asm/charmap.o \
|
src/asm/charmap.o \
|
||||||
src/asm/fstack.o \
|
src/asm/fstack.o \
|
||||||
src/asm/lexer.o \
|
src/asm/lexer.o \
|
||||||
src/asm/macro.o \
|
src/asm/macro.o \
|
||||||
src/asm/main.o \
|
src/asm/main.o \
|
||||||
src/asm/math.o \
|
src/asm/math.o \
|
||||||
|
src/asm/parser.o \
|
||||||
src/asm/output.o \
|
src/asm/output.o \
|
||||||
src/asm/rpn.o \
|
src/asm/rpn.o \
|
||||||
src/asm/section.o \
|
src/asm/section.o \
|
||||||
@@ -72,7 +72,7 @@ rgbasm_obj := \
|
|||||||
src/hashmap.o \
|
src/hashmap.o \
|
||||||
src/linkdefs.o
|
src/linkdefs.o
|
||||||
|
|
||||||
src/asm/lexer.o src/asm/main.o: src/asm/asmy.h
|
src/asm/lexer.o src/asm/main.o: src/asm/parser.h
|
||||||
|
|
||||||
rgblink_obj := \
|
rgblink_obj := \
|
||||||
src/link/assign.o \
|
src/link/assign.o \
|
||||||
@@ -136,7 +136,7 @@ clean:
|
|||||||
$Q${RM} rgbgfx rgbgfx.exe
|
$Q${RM} rgbgfx rgbgfx.exe
|
||||||
$Qfind src/ -name "*.o" -exec rm {} \;
|
$Qfind src/ -name "*.o" -exec rm {} \;
|
||||||
$Q${RM} rgbshim.sh
|
$Q${RM} rgbshim.sh
|
||||||
$Q${RM} src/asm/asmy.c src/asm/asmy.h
|
$Q${RM} src/asm/parser.c src/asm/parser.h
|
||||||
|
|
||||||
# Target used to install the binaries and man pages.
|
# Target used to install the binaries and man pages.
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ is possible using ``make`` or ``cmake``; follow the link for more detailed instr
|
|||||||
|
|
||||||
.. code:: sh
|
.. code:: sh
|
||||||
|
|
||||||
cmake -S . -B build
|
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
cmake --build build
|
cmake --build build
|
||||||
cmake --install build
|
cmake --install build
|
||||||
|
|
||||||
@@ -50,6 +50,8 @@ The RGBDS source code file structure somewhat resembles the following:
|
|||||||
│ └── workflows/
|
│ └── workflows/
|
||||||
│ └── ...
|
│ └── ...
|
||||||
├── contrib/
|
├── contrib/
|
||||||
|
│ ├── zsh_compl/
|
||||||
|
│ │ └── ...
|
||||||
│ └── ...
|
│ └── ...
|
||||||
├── include/
|
├── include/
|
||||||
│ └── ...
|
│ └── ...
|
||||||
@@ -79,6 +81,8 @@ The RGBDS source code file structure somewhat resembles the following:
|
|||||||
- ``contrib/`` - scripts and other resources which may be useful to users and developers of
|
- ``contrib/`` - scripts and other resources which may be useful to users and developers of
|
||||||
RGBDS.
|
RGBDS.
|
||||||
|
|
||||||
|
* ``zsh_compl`` contains tab completion scripts for use with zsh. Put them somewhere in your ``fpath``, and they should auto-load.
|
||||||
|
|
||||||
- ``include/`` - header files for each respective C files in `src`.
|
- ``include/`` - header files for each respective C files in `src`.
|
||||||
|
|
||||||
- ``src/`` - source code and manual pages for RGBDS.
|
- ``src/`` - source code and manual pages for RGBDS.
|
||||||
|
|||||||
49
contrib/zsh_compl/_rgbasm
Normal file
49
contrib/zsh_compl/_rgbasm
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#compdef rgbasm
|
||||||
|
|
||||||
|
_rgbasm_warnings() {
|
||||||
|
local warnings=(
|
||||||
|
'error:Turn all warnings into errors'
|
||||||
|
|
||||||
|
'all:Enable most warning messages'
|
||||||
|
'extra:Enable extra, possibly unwanted, messages'
|
||||||
|
'everything:Enable literally everything'
|
||||||
|
|
||||||
|
'assert:Warn when WARN-type asserts fail'
|
||||||
|
'builtin-args:Report incorrect args to built-in funcs'
|
||||||
|
'div:Warn when dividing the smallest int by -1'
|
||||||
|
'empty-entry:Warn on empty entries in db, dw, dl args'
|
||||||
|
'large-constant:Warn on constants too large for a signed 32-bit int'
|
||||||
|
'long-string:Warn on strings too long'
|
||||||
|
'obsolete:Warn when using deprecated features'
|
||||||
|
'shift:Warn when shifting negative values'
|
||||||
|
'shift-amount:Warn when a shift'\''s operand it negative or \> 32'
|
||||||
|
'truncation:Warn when implicit truncations lose bits'
|
||||||
|
'user:Warn when executing the WARN built-in'
|
||||||
|
)
|
||||||
|
# TODO: handle `no-` and `error=` somehow?
|
||||||
|
_describe warning warnings
|
||||||
|
}
|
||||||
|
|
||||||
|
local args=(
|
||||||
|
# Arguments are listed here in the same order as in the manual, except for the version
|
||||||
|
'(- : * options)'{-V,--version}'[Print version number]'
|
||||||
|
|
||||||
|
'(-E --export-all)'{-E,--export-all}'[Export all symbols]'
|
||||||
|
'(-h --halt-without-nop)'{-h,--halt-without-nop}'[Avoid outputting a `nop` after `halt`]'
|
||||||
|
'(-L ---preserve-ld)'{-L,--preserve-ld}'[Prevent auto-optimizing `ld` into `ldh`]'
|
||||||
|
'(-v --verbose)'{-v,--verbose}'[Print additional messages regarding progression]'
|
||||||
|
-w'[Disable all warnings]'
|
||||||
|
|
||||||
|
'(-b --binary-digits)'{-b,--binary-digits}'+[Change chars for binary constants]:digit spec:'
|
||||||
|
'(-D --define)'{-D,--define}'+[Define a string symbol]:name + value (default 1):'
|
||||||
|
'(-g --gfx-chars)'{-g,--gfx-chars}'+[Change chars for gfx constants]:chars spec:'
|
||||||
|
'(-i --include)'{-i,--include}'+[Add an include directory]:include path:_files -/'
|
||||||
|
'(-M --dependfile)'{-M,--dependfile}"+[List deps in make format]:output file:_files -g '*.{d,mk}"
|
||||||
|
'(-o --output)'{-o,--output}'+[Output file]:output file:_files'
|
||||||
|
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
|
||||||
|
'(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:'
|
||||||
|
'(-W --warning)'{-W,--warning}'+[Toggle warning flags]:warning flag:_rgbasm_warnings'
|
||||||
|
|
||||||
|
'*'":assembly sources:_files -g '*.asm'"
|
||||||
|
)
|
||||||
|
_arguments -s -S : $args
|
||||||
25
contrib/zsh_compl/_rgbfix
Normal file
25
contrib/zsh_compl/_rgbfix
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#compdef rgbfix
|
||||||
|
|
||||||
|
local args=(
|
||||||
|
# Arguments are listed here in the same order as in the manual, except for the version
|
||||||
|
'(- : * options)'{-V,--version}'[Print version number]'
|
||||||
|
|
||||||
|
'(-C --color-only)'{-C,--color-only}'[Mark ROM as GBC-only]'
|
||||||
|
'(-c --color-compatible)'{-c,--color-compatible}'[Mark ROM as GBC-compatible]'
|
||||||
|
'(-j --non-japanese)'{-j,--non-japanese}'[Set the non-Japanese region flag]'
|
||||||
|
'(-s --sgb-compatible)'{-s,--sgb-compatible}'[Set the SGB flag]'
|
||||||
|
'(-f --fix-spec -v --validate)'{-v,--validate}'[Shorthand for -f lhg]'
|
||||||
|
|
||||||
|
'(-f --fix-spec -v --validate)'{-f,--fix-spec}'+[Fix or trash some header values]:fix spec:'
|
||||||
|
'(-i --game-id)'{-i,--game-id}'+[Set game ID string]:4-char game ID:'
|
||||||
|
'(-k --new-licensee)'{-k,--new-licensee}'+[Set new licensee string]:2-char licensee ID:'
|
||||||
|
'(-l --old-licensee)'{-l,--old-licensee}'+[Set old licensee ID]:licensee number:'
|
||||||
|
'(-m --mbc-type)'{-m,--mbc-type}'+[Set MBC flags]:mbc flags byte:'
|
||||||
|
'(-n --rom-version)'{-n,--rom-version}'+[Set ROM version]:rom version byte:'
|
||||||
|
'(-p --pad-value)'{-p,--pad-value}'+[Pad to next valid size using this byte as padding]:padding byte:'
|
||||||
|
'(-r --ram-size)'{-r,--ram-size}'+[Set RAM size]:ram size byte:'
|
||||||
|
'(-t --title)'{-t,--title}'+[Set title string]:11-char title string:'
|
||||||
|
|
||||||
|
'*'":ROM files:_files -g '*.{gb,sgb,gbc}'"
|
||||||
|
)
|
||||||
|
_arguments -s -S : $args
|
||||||
37
contrib/zsh_compl/_rgbgfx
Normal file
37
contrib/zsh_compl/_rgbgfx
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#compdef rgbgfx
|
||||||
|
|
||||||
|
_depths() {
|
||||||
|
local depths=(
|
||||||
|
'1:1bpp'
|
||||||
|
'2:2bpp (native)'
|
||||||
|
)
|
||||||
|
|
||||||
|
_describe 'bit depth' depths
|
||||||
|
}
|
||||||
|
|
||||||
|
local args=(
|
||||||
|
# Arguments are listed here in the same order as in the manual, except for the version
|
||||||
|
'(- : * options)'{-V,--version}'[Print version number]'
|
||||||
|
|
||||||
|
'(-a --attr-map -A --output-attr-map)'{-A,--output-attr-map}'[Shortcut for -a <file>.attrmap]'
|
||||||
|
'(-C --color-curve)'{-C,--color-curve}'[Generate palettes using GBC color curve]'
|
||||||
|
'(-D --debug)'{-D,--debug}'[Enable debug features]'
|
||||||
|
'(-f --fix -F --fix-and-save)'{-f,--fix}'[Fix input PNG into an indexed image]'
|
||||||
|
'(-f --fix -F --fix-and-save)'{-F,--fix-and-save}'[Like -f but also save CLI params within the PNG]'
|
||||||
|
'(-h --horizontal)'{-h,--horizontal}'[Lay out tiles horizontally instead of vertically]'
|
||||||
|
'(-m --mirror-tiles)'{-m,--mirror-tiles}'[Eliminate mirrored tiles from output]'
|
||||||
|
'(-p --palette -P --output-palette)'{-P,--output-palette}'[Shortcut for -p <file>.pal]'
|
||||||
|
'(-t --tilemap -T --output-tilemap)'{-T,--output-tilemap}'[Shortcut for -t <file>.tilemap]'
|
||||||
|
'(-u --unique-tiles)'{-u,--unique-tiles}'[Eliminate redundant tiles]'
|
||||||
|
'(-v --verbose)'{-v,--verbose}'[Enable verbose output]'
|
||||||
|
|
||||||
|
'(-a --attr-map -A --output-attr-map)'{-a,--attr-map}'+[Generate a map of tile attributes (mirroring)]:attrmap file:_files'
|
||||||
|
'(-d --depth)'{-d,--depth}'+[Set bit depth]:bit depth:_depths'
|
||||||
|
'(-o --output)'{-o,--output}'+[Set output file]:output file:_files'
|
||||||
|
'(-p --palette -P --output-palette)'{-p,--palette}"+[Output the image's palette in little-endian native RGB555 format]:palette file:_files"
|
||||||
|
'(-t --tilemap -T --output-tilemap)'{-t,--tilemap}'+[Generate a map of tile indices]:tilemap file:_files'
|
||||||
|
'(-x --trim-end)'{-x,--trim-end}'+[Trim end of output by this many tiles]:tile count:'
|
||||||
|
|
||||||
|
'*'":input png files:_files -g '*.png'"
|
||||||
|
)
|
||||||
|
_arguments -s -S : $args
|
||||||
22
contrib/zsh_compl/_rgblink
Normal file
22
contrib/zsh_compl/_rgblink
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#compdef rgblink
|
||||||
|
|
||||||
|
local args=(
|
||||||
|
# Arguments are listed here in the same order as in the manual, except for the version
|
||||||
|
'(- : * options)'{-V,--version}'[Print version number]'
|
||||||
|
|
||||||
|
'(-d --dmg)'{-d,--dmg}'[Enable DMG mode (-w + no VRAM banking)]'
|
||||||
|
'(-t --tiny)'{-t,--tiny}'[Enable tiny mode, disabling ROM banking]'
|
||||||
|
'(-v --verbose)'{-v,--verbose}'[Enable verbose output]'
|
||||||
|
'(-w --wramx)'{-w,--wramx}'[Disable WRAM banking]'
|
||||||
|
|
||||||
|
'(-l --linkerscript)'{-l,--linkerscript}"+[Use a linker script]:linker script:_files -g '*.link'"
|
||||||
|
'(-m --map)'{-m,--map}"+[Produce a map file]:map file:_files -g '*.map'"
|
||||||
|
'(-n --sym)'(-n,--sym)"+[Produce a symbol file]:sym file:_files -g '*.sym'"
|
||||||
|
'(-O --overlay)'{-O,--overlay}'+[Overlay sections over on top of bin file]:base overlay:_files'
|
||||||
|
'(-o --output)'{-o,--output}"+[Write ROM image to this file]:rom file:_files -g '*.{gb,sgb,gbc}'"
|
||||||
|
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
|
||||||
|
'(-s --smart)'{-s,--smart}'+[!BROKEN! Perform smart linking from this symbol]:symbol name:'
|
||||||
|
|
||||||
|
'*'":object files:_files -g '*.o'"
|
||||||
|
)
|
||||||
|
_arguments -s -S : $args
|
||||||
@@ -29,7 +29,7 @@ uint32_t macro_GetUniqueID(void);
|
|||||||
char const *macro_GetUniqueIDStr(void);
|
char const *macro_GetUniqueIDStr(void);
|
||||||
void macro_SetUniqueID(uint32_t id);
|
void macro_SetUniqueID(uint32_t id);
|
||||||
uint32_t macro_UseNewUniqueID(void);
|
uint32_t macro_UseNewUniqueID(void);
|
||||||
void macro_ShiftCurrentArgs(void);
|
void macro_ShiftCurrentArgs(int32_t count);
|
||||||
uint32_t macro_NbArgs(void);
|
uint32_t macro_NbArgs(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ struct Expression {
|
|||||||
uint32_t nRPNPatchSize; // Size the expression will take in the obj file
|
uint32_t nRPNPatchSize; // Size the expression will take in the obj file
|
||||||
};
|
};
|
||||||
|
|
||||||
/* FIXME: Should be defined in `asmy.h`, but impossible with POSIX Yacc */
|
/* FIXME: Should be defined in `parser.h`, but impossible with POSIX Yacc */
|
||||||
extern int32_t nPCOffset;
|
extern int32_t nPCOffset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -46,7 +46,7 @@ static inline bool rpn_isSymbol(const struct Expression *expr)
|
|||||||
return expr->isSymbol;
|
return expr->isSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_Symbol(struct Expression *expr, char *tzSym);
|
void rpn_Symbol(struct Expression *expr, char const *tzSym);
|
||||||
void rpn_Number(struct Expression *expr, uint32_t i);
|
void rpn_Number(struct Expression *expr, uint32_t i);
|
||||||
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
|
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
|
||||||
struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
|
struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
|
||||||
|
|||||||
@@ -121,11 +121,22 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value);
|
|||||||
uint32_t sym_GetPCValue(void);
|
uint32_t sym_GetPCValue(void);
|
||||||
uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
|
uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
|
||||||
uint32_t sym_GetConstantValue(char const *s);
|
uint32_t sym_GetConstantValue(char const *s);
|
||||||
struct Symbol *sym_FindSymbol(char const *symName);
|
/*
|
||||||
|
* Find a symbol by exact name, bypassing expansion checks
|
||||||
|
*/
|
||||||
|
struct Symbol *sym_FindExactSymbol(char const *name);
|
||||||
|
/*
|
||||||
|
* Find a symbol by exact name; may not be scoped, produces an error if it is
|
||||||
|
*/
|
||||||
|
struct Symbol *sym_FindUnscopedSymbol(char const *name);
|
||||||
|
/*
|
||||||
|
* Find a symbol, possibly scoped, by name
|
||||||
|
*/
|
||||||
|
struct Symbol *sym_FindScopedSymbol(char const *name);
|
||||||
|
struct Symbol const *sym_GetPC(void);
|
||||||
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
|
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
|
||||||
struct Symbol *sym_Ref(char const *symName);
|
struct Symbol *sym_Ref(char const *symName);
|
||||||
struct Symbol *sym_AddString(char const *symName, char const *value);
|
struct Symbol *sym_AddString(char const *symName, char const *value);
|
||||||
uint32_t sym_GetDefinedValue(char const *s);
|
|
||||||
void sym_Purge(char const *symName);
|
void sym_Purge(char const *symName);
|
||||||
void sym_Init(void);
|
void sym_Init(void);
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ enum WarningID {
|
|||||||
WARNING_EMPTY_ENTRY, /* Empty entry in `db`, `dw` or `dl` */
|
WARNING_EMPTY_ENTRY, /* Empty entry in `db`, `dw` or `dl` */
|
||||||
WARNING_LARGE_CONSTANT, /* Constants too large */
|
WARNING_LARGE_CONSTANT, /* Constants too large */
|
||||||
WARNING_LONG_STR, /* String too long for internal buffers */
|
WARNING_LONG_STR, /* String too long for internal buffers */
|
||||||
|
WARNING_NESTED_COMMENT, /* Comment-start delimeter in a block comment */
|
||||||
WARNING_OBSOLETE, /* Obsolete things */
|
WARNING_OBSOLETE, /* Obsolete things */
|
||||||
WARNING_SHIFT, /* Shifting undefined behavior */
|
WARNING_SHIFT, /* Shifting undefined behavior */
|
||||||
WARNING_SHIFT_AMOUNT, /* Strange shift amount */
|
WARNING_SHIFT_AMOUNT, /* Strange shift amount */
|
||||||
@@ -54,7 +55,7 @@ void warning(enum WarningID id, const char *fmt, ...);
|
|||||||
* It is also used when the assembler goes into an invalid state (for example,
|
* It is also used when the assembler goes into an invalid state (for example,
|
||||||
* when it fails to allocate memory).
|
* when it fails to allocate memory).
|
||||||
*/
|
*/
|
||||||
noreturn_ void fatalerror(const char *fmt, ...);
|
_Noreturn void fatalerror(const char *fmt, ...);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used for errors that make it impossible to assemble correctly, but don't
|
* Used for errors that make it impossible to assemble correctly, but don't
|
||||||
|
|||||||
8
include/extern/err.h
vendored
8
include/extern/err.h
vendored
@@ -34,10 +34,10 @@ void vwarn(const char *fmt, va_list ap) format_(printf, 1, 0);
|
|||||||
void warnx(const char *fmt, ...) format_(printf, 1, 2);
|
void warnx(const char *fmt, ...) format_(printf, 1, 2);
|
||||||
void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0);
|
void vwarnx(const char *fmt, va_list ap) format_(printf, 1, 0);
|
||||||
|
|
||||||
noreturn_ void err(int status, const char *fmt, ...) format_(printf, 2, 3);
|
_Noreturn void err(int status, const char *fmt, ...) format_(printf, 2, 3);
|
||||||
noreturn_ void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
_Noreturn void verr(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
||||||
noreturn_ void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
|
_Noreturn void errx(int status, const char *fmt, ...) format_(printf, 2, 3);
|
||||||
noreturn_ void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
_Noreturn void verrx(int status, const char *fmt, va_list ap) format_(printf, 2, 0);
|
||||||
|
|
||||||
#endif /* ERR_IN_LIBC */
|
#endif /* ERR_IN_LIBC */
|
||||||
|
|
||||||
|
|||||||
2
include/extern/utf8decoder.h
vendored
2
include/extern/utf8decoder.h
vendored
@@ -9,6 +9,6 @@
|
|||||||
#ifndef EXTERN_UTF8DECODER_H
|
#ifndef EXTERN_UTF8DECODER_H
|
||||||
#define EXTERN_UTF8DECODER_H
|
#define EXTERN_UTF8DECODER_H
|
||||||
|
|
||||||
uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte);
|
uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte);
|
||||||
|
|
||||||
#endif /* EXTERN_UTF8DECODER_H */
|
#endif /* EXTERN_UTF8DECODER_H */
|
||||||
|
|||||||
@@ -33,6 +33,16 @@ typedef struct HashMapEntry *HashMap[HASHMAP_NB_BUCKETS];
|
|||||||
*/
|
*/
|
||||||
bool hash_AddElement(HashMap map, char const *key, void *element);
|
bool hash_AddElement(HashMap map, char const *key, void *element);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces an element with an already-present key in a hashmap.
|
||||||
|
* @warning Inserting a NULL will make `hash_GetElement`'s return ambiguous!
|
||||||
|
* @param map The HashMap to replace the element in
|
||||||
|
* @param key The key with which the element will be stored and retrieved
|
||||||
|
* @param element The element to replace
|
||||||
|
* @return True if the element was found and replaced
|
||||||
|
*/
|
||||||
|
bool hash_ReplaceElement(HashMap const map, char const *key, void *element);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an element from a hashmap.
|
* Removes an element from a hashmap.
|
||||||
* @param map The HashMap to remove the element from
|
* @param map The HashMap to remove the element from
|
||||||
|
|||||||
@@ -9,21 +9,30 @@
|
|||||||
#ifndef HELPERS_H
|
#ifndef HELPERS_H
|
||||||
#define HELPERS_H
|
#define HELPERS_H
|
||||||
|
|
||||||
#ifdef __GNUC__
|
// Of course, MSVC does not support C11, so no _Noreturn there...
|
||||||
/* GCC or compatible */
|
#ifdef _MSC_VER
|
||||||
#define format_(archetype, str_index, first_arg) \
|
#define _Noreturn __declspec(noreturn)
|
||||||
__attribute__ ((format (archetype, str_index, first_arg)))
|
|
||||||
#define noreturn_ __attribute__ ((noreturn))
|
|
||||||
#define trap_ __builtin_trap()
|
|
||||||
#else
|
|
||||||
/* Unsupported, but no need to throw a fit */
|
|
||||||
#define format_(archetype, str_index, first_arg)
|
|
||||||
#define noreturn_
|
|
||||||
#define unused_
|
|
||||||
#define trap_
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Macros for stringification */
|
// Ideally, we'd use `__has_attribute` and `__has_builtin`, but these were only introduced in GCC 9
|
||||||
|
#ifdef __GNUC__ // GCC or compatible
|
||||||
|
#define format_(archetype, str_index, first_arg) \
|
||||||
|
__attribute__ ((format (archetype, str_index, first_arg)))
|
||||||
|
// In release builds, define "unreachable" as such, but trap in debug builds
|
||||||
|
#ifdef NDEBUG
|
||||||
|
#define unreachable_ __builtin_unreachable
|
||||||
|
#else
|
||||||
|
#define unreachable_ __builtin_trap
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
// Unsupported, but no need to throw a fit
|
||||||
|
#define format_(archetype, str_index, first_arg)
|
||||||
|
// This seems to generate similar code to __builtin_unreachable, despite different semantics
|
||||||
|
// Note that executing this is undefined behavior (declared _Noreturn, but does return)
|
||||||
|
static inline _Noreturn unreachable_(void) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Macros for stringification
|
||||||
#define STR(x) #x
|
#define STR(x) #x
|
||||||
#define EXPAND_AND_STR(x) STR(x)
|
#define EXPAND_AND_STR(x) STR(x)
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ void warning(struct FileStackNode const *where, uint32_t lineNo,
|
|||||||
void error(struct FileStackNode const *where, uint32_t lineNo,
|
void error(struct FileStackNode const *where, uint32_t lineNo,
|
||||||
char const *fmt, ...) format_(printf, 3, 4);
|
char const *fmt, ...) format_(printf, 3, 4);
|
||||||
|
|
||||||
noreturn_ void fatal(struct FileStackNode const *where, uint32_t lineNo,
|
_Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo,
|
||||||
char const *fmt, ...) format_(printf, 3, 4);
|
char const *fmt, ...) format_(printf, 3, 4);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#define PACKAGE_VERSION_MAJOR (0)
|
#define PACKAGE_VERSION_MAJOR (0)
|
||||||
#define PACKAGE_VERSION_MINOR (4)
|
#define PACKAGE_VERSION_MINOR (4)
|
||||||
#define PACKAGE_VERSION_PATCH (1)
|
#define PACKAGE_VERSION_PATCH (2)
|
||||||
|
|
||||||
const char *get_package_version_string(void);
|
const char *get_package_version_string(void);
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ else()
|
|||||||
pkg_check_modules(LIBPNG REQUIRED libpng)
|
pkg_check_modules(LIBPNG REQUIRED libpng)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
BISON_TARGET(ASMy "asm/asmy.y"
|
BISON_TARGET(PARSER "asm/parser.y"
|
||||||
"${PROJECT_SOURCE_DIR}/src/asm/asmy.c"
|
"${PROJECT_SOURCE_DIR}/src/asm/parser.c"
|
||||||
DEFINES_FILE "${PROJECT_SOURCE_DIR}/src/asm/asmy.h"
|
DEFINES_FILE "${PROJECT_SOURCE_DIR}/src/asm/parser.h"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(rgbasm_src
|
set(rgbasm_src
|
||||||
"${BISON_ASMy_OUTPUT_SOURCE}"
|
"${BISON_PARSER_OUTPUT_SOURCE}"
|
||||||
"asm/charmap.c"
|
"asm/charmap.c"
|
||||||
"asm/fstack.c"
|
"asm/fstack.c"
|
||||||
"asm/lexer.c"
|
"asm/lexer.c"
|
||||||
|
|||||||
4
src/asm/.gitignore
vendored
4
src/asm/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
asmy.c
|
/parser.c
|
||||||
asmy.h
|
/parser.h
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ void charmap_Add(char *mapping, uint8_t value)
|
|||||||
if (currentCharmap->usedNodes == currentCharmap->capacity) {
|
if (currentCharmap->usedNodes == currentCharmap->capacity) {
|
||||||
currentCharmap->capacity *= 2;
|
currentCharmap->capacity *= 2;
|
||||||
currentCharmap = resizeCharmap(currentCharmap, currentCharmap->capacity);
|
currentCharmap = resizeCharmap(currentCharmap, currentCharmap->capacity);
|
||||||
|
hash_ReplaceElement(charmaps, currentCharmap->name, currentCharmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Switch to and init new node */
|
/* Switch to and init new node */
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ void fstk_RunMacro(char const *macroName, struct MacroArgs *args)
|
|||||||
{
|
{
|
||||||
dbgPrint("Running macro \"%s\"\n", macroName);
|
dbgPrint("Running macro \"%s\"\n", macroName);
|
||||||
|
|
||||||
struct Symbol *macro = sym_FindSymbol(macroName);
|
struct Symbol *macro = sym_FindExactSymbol(macroName);
|
||||||
|
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
error("Macro \"%s\" not defined\n", macroName);
|
error("Macro \"%s\" not defined\n", macroName);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#include "asm/util.h"
|
#include "asm/util.h"
|
||||||
#include "asm/warning.h"
|
#include "asm/warning.h"
|
||||||
/* Include this last so it gets all type & constant definitions */
|
/* Include this last so it gets all type & constant definitions */
|
||||||
#include "asmy.h" /* For token definitions, generated from asmy.y */
|
#include "parser.h" /* For token definitions, generated from parser.y */
|
||||||
|
|
||||||
#ifdef LEXER_DEBUG
|
#ifdef LEXER_DEBUG
|
||||||
#define dbgPrint(...) fprintf(stderr, "[lexer] " __VA_ARGS__)
|
#define dbgPrint(...) fprintf(stderr, "[lexer] " __VA_ARGS__)
|
||||||
@@ -921,6 +921,33 @@ void lexer_DumpStringExpansions(void)
|
|||||||
free(stack);
|
free(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Discards an block comment */
|
||||||
|
static void discardBlockComment(void)
|
||||||
|
{
|
||||||
|
dbgPrint("Discarding block comment\n");
|
||||||
|
for (;;) {
|
||||||
|
switch (nextChar()) {
|
||||||
|
case EOF:
|
||||||
|
error("Unterminated block comment\n");
|
||||||
|
return;
|
||||||
|
case '/':
|
||||||
|
if (peek(0) == '*') {
|
||||||
|
warning(WARNING_NESTED_COMMENT,
|
||||||
|
"/* in block comment\n");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
case '*':
|
||||||
|
if (peek(0) == '/') {
|
||||||
|
shiftChars(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* fallthrough */
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Function to discard all of a line's comments */
|
/* Function to discard all of a line's comments */
|
||||||
|
|
||||||
static void discardComment(void)
|
static void discardComment(void)
|
||||||
@@ -1284,7 +1311,7 @@ static char const *readInterpolation(void)
|
|||||||
}
|
}
|
||||||
symName[i] = '\0';
|
symName[i] = '\0';
|
||||||
|
|
||||||
struct Symbol const *sym = sym_FindSymbol(symName);
|
struct Symbol const *sym = sym_FindScopedSymbol(symName);
|
||||||
|
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
error("Interpolated symbol \"%s\" does not exist\n", symName);
|
error("Interpolated symbol \"%s\" does not exist\n", symName);
|
||||||
@@ -1476,8 +1503,6 @@ static int yylex_NORMAL(void)
|
|||||||
return T_OP_ADD;
|
return T_OP_ADD;
|
||||||
case '-':
|
case '-':
|
||||||
return T_OP_SUB;
|
return T_OP_SUB;
|
||||||
case '/':
|
|
||||||
return T_OP_DIV;
|
|
||||||
case '~':
|
case '~':
|
||||||
return T_OP_NOT;
|
return T_OP_NOT;
|
||||||
|
|
||||||
@@ -1498,7 +1523,14 @@ static int yylex_NORMAL(void)
|
|||||||
|
|
||||||
/* Handle ambiguous 1- or 2-char tokens */
|
/* Handle ambiguous 1- or 2-char tokens */
|
||||||
char secondChar;
|
char secondChar;
|
||||||
|
case '/': /* Either division or a block comment */
|
||||||
|
secondChar = peek(0);
|
||||||
|
if (secondChar == '*') {
|
||||||
|
shiftChars(1);
|
||||||
|
discardBlockComment();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return T_OP_DIV;
|
||||||
case '|': /* Either binary or logical OR */
|
case '|': /* Either binary or logical OR */
|
||||||
secondChar = peek(0);
|
secondChar = peek(0);
|
||||||
if (secondChar == '|') {
|
if (secondChar == '|') {
|
||||||
@@ -1659,9 +1691,10 @@ static int yylex_NORMAL(void)
|
|||||||
if (tokenType != T_ID && tokenType != T_LOCAL_ID)
|
if (tokenType != T_ID && tokenType != T_LOCAL_ID)
|
||||||
return tokenType;
|
return tokenType;
|
||||||
|
|
||||||
if (lexerState->expandStrings) {
|
/* Local symbols cannot be string expansions */
|
||||||
|
if (tokenType == T_ID && lexerState->expandStrings) {
|
||||||
/* Attempt string expansion */
|
/* Attempt string expansion */
|
||||||
struct Symbol const *sym = sym_FindSymbol(yylval.tzSym);
|
struct Symbol const *sym = sym_FindExactSymbol(yylval.tzSym);
|
||||||
|
|
||||||
if (sym && sym->type == SYM_EQUS) {
|
if (sym && sym->type == SYM_EQUS) {
|
||||||
char const *s = sym_GetStringValue(sym);
|
char const *s = sym_GetStringValue(sym);
|
||||||
@@ -1929,13 +1962,11 @@ restart:
|
|||||||
|
|
||||||
static char *startCapture(void)
|
static char *startCapture(void)
|
||||||
{
|
{
|
||||||
assert(!lexerState->expansions);
|
|
||||||
|
|
||||||
lexerState->capturing = true;
|
lexerState->capturing = true;
|
||||||
lexerState->captureSize = 0;
|
lexerState->captureSize = 0;
|
||||||
lexerState->disableMacroArgs = true;
|
lexerState->disableMacroArgs = true;
|
||||||
|
|
||||||
if (lexerState->isMmapped) {
|
if (lexerState->isMmapped && !lexerState->expansions) {
|
||||||
return &lexerState->ptr[lexerState->offset];
|
return &lexerState->ptr[lexerState->offset];
|
||||||
} else {
|
} else {
|
||||||
lexerState->captureCapacity = 128; /* The initial size will be twice that */
|
lexerState->captureCapacity = 128; /* The initial size will be twice that */
|
||||||
@@ -2014,7 +2045,6 @@ finish:
|
|||||||
void lexer_CaptureMacroBody(char **capture, size_t *size)
|
void lexer_CaptureMacroBody(char **capture, size_t *size)
|
||||||
{
|
{
|
||||||
char *captureStart = startCapture();
|
char *captureStart = startCapture();
|
||||||
unsigned int level = 0;
|
|
||||||
int c = peek(0);
|
int c = peek(0);
|
||||||
|
|
||||||
/* If the file is `mmap`ed, we need not to unmap it to keep access to the macro */
|
/* If the file is `mmap`ed, we need not to unmap it to keep access to the macro */
|
||||||
@@ -2051,27 +2081,7 @@ void lexer_CaptureMacroBody(char **capture, size_t *size)
|
|||||||
} while (isWhitespace(c));
|
} while (isWhitespace(c));
|
||||||
/* Now, try to match either `REPT` or `ENDR` as a **whole** identifier */
|
/* Now, try to match either `REPT` or `ENDR` as a **whole** identifier */
|
||||||
if (startsIdentifier(c)) {
|
if (startsIdentifier(c)) {
|
||||||
switch (readIdentifier(c)) {
|
if (readIdentifier(c) == T_POP_ENDM) {
|
||||||
case T_ID:
|
|
||||||
/* We have an initial label, look for a single colon */
|
|
||||||
do {
|
|
||||||
c = nextChar();
|
|
||||||
} while (isWhitespace(c));
|
|
||||||
if (c != ':') /* If not a colon, give up */
|
|
||||||
break;
|
|
||||||
/* And finally, a `MACRO` token */
|
|
||||||
do {
|
|
||||||
c = nextChar();
|
|
||||||
} while (isWhitespace(c));
|
|
||||||
if (!startsIdentifier(c))
|
|
||||||
break;
|
|
||||||
if (readIdentifier(c) != T_POP_MACRO)
|
|
||||||
break;
|
|
||||||
level++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_POP_ENDM:
|
|
||||||
if (!level) {
|
|
||||||
/* Read (but don't capture) until EOL or EOF */
|
/* Read (but don't capture) until EOL or EOF */
|
||||||
lexerState->capturing = false;
|
lexerState->capturing = false;
|
||||||
do {
|
do {
|
||||||
@@ -2085,8 +2095,6 @@ void lexer_CaptureMacroBody(char **capture, size_t *size)
|
|||||||
shiftChars(1);
|
shiftChars(1);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
level--;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
lexerState->lineNo++;
|
lexerState->lineNo++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,10 +128,17 @@ uint32_t macro_UseNewUniqueID(void)
|
|||||||
return maxUniqueID;
|
return maxUniqueID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void macro_ShiftCurrentArgs(void)
|
void macro_ShiftCurrentArgs(int32_t count)
|
||||||
{
|
{
|
||||||
if (macroArgs->shift != macroArgs->nbArgs)
|
if (!macroArgs) {
|
||||||
macroArgs->shift++;
|
error("Cannot shift macro arguments outside of a macro\n");
|
||||||
|
} else if (count < 0) {
|
||||||
|
error("Cannot shift arguments by negative amount %" PRId32 "\n", count);
|
||||||
|
} else if (macroArgs->shift < macroArgs->nbArgs) {
|
||||||
|
macroArgs->shift += count;
|
||||||
|
if (macroArgs->shift > macroArgs->nbArgs)
|
||||||
|
macroArgs->shift = macroArgs->nbArgs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t macro_NbArgs(void)
|
uint32_t macro_NbArgs(void)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#include "asm/rpn.h"
|
#include "asm/rpn.h"
|
||||||
#include "asm/symbol.h"
|
#include "asm/symbol.h"
|
||||||
#include "asm/warning.h"
|
#include "asm/warning.h"
|
||||||
#include "asmy.h"
|
#include "parser.h"
|
||||||
|
|
||||||
#include "extern/err.h"
|
#include "extern/err.h"
|
||||||
#include "extern/getopt.h"
|
#include "extern/getopt.h"
|
||||||
@@ -34,6 +34,10 @@
|
|||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
// Old Bison versions (confirmed for 2.3) do not forward-declare `yyparse` in the generated header
|
||||||
|
// Unfortunately, macOS still ships 2.3, which is from 2008...
|
||||||
|
int yyparse(void);
|
||||||
|
|
||||||
size_t cldefines_index;
|
size_t cldefines_index;
|
||||||
size_t cldefines_numindices;
|
size_t cldefines_numindices;
|
||||||
size_t cldefines_bufsize;
|
size_t cldefines_bufsize;
|
||||||
@@ -432,6 +436,7 @@ int main(int argc, char *argv[])
|
|||||||
/* On first alloc, make an empty str */
|
/* On first alloc, make an empty str */
|
||||||
tzTargetFileName =
|
tzTargetFileName =
|
||||||
malloc(nTargetFileNameLen + 1);
|
malloc(nTargetFileNameLen + 1);
|
||||||
|
if (tzTargetFileName)
|
||||||
*tzTargetFileName = '\0';
|
*tzTargetFileName = '\0';
|
||||||
} else {
|
} else {
|
||||||
tzTargetFileName =
|
tzTargetFileName =
|
||||||
|
|||||||
@@ -296,6 +296,11 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
|||||||
uint8_t rpndata = popbyte();
|
uint8_t rpndata = popbyte();
|
||||||
|
|
||||||
switch (rpndata) {
|
switch (rpndata) {
|
||||||
|
struct Symbol *sym;
|
||||||
|
uint32_t value;
|
||||||
|
uint8_t b;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
case RPN_CONST:
|
case RPN_CONST:
|
||||||
writebyte(RPN_CONST);
|
writebyte(RPN_CONST);
|
||||||
writebyte(popbyte());
|
writebyte(popbyte());
|
||||||
@@ -303,13 +308,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
|||||||
writebyte(popbyte());
|
writebyte(popbyte());
|
||||||
writebyte(popbyte());
|
writebyte(popbyte());
|
||||||
break;
|
break;
|
||||||
case RPN_SYM:
|
|
||||||
{
|
|
||||||
for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
|
|
||||||
;
|
|
||||||
struct Symbol *sym = sym_FindSymbol(tzSym);
|
|
||||||
uint32_t value;
|
|
||||||
|
|
||||||
|
case RPN_SYM:
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
tzSym[i] = popbyte();
|
||||||
|
} while (tzSym[i++]);
|
||||||
|
|
||||||
|
// The symbol name is always written expanded
|
||||||
|
sym = sym_FindExactSymbol(tzSym);
|
||||||
if (sym_IsConstant(sym)) {
|
if (sym_IsConstant(sym)) {
|
||||||
writebyte(RPN_CONST);
|
writebyte(RPN_CONST);
|
||||||
value = sym_GetConstantValue(tzSym);
|
value = sym_GetConstantValue(tzSym);
|
||||||
@@ -317,18 +324,22 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
|||||||
writebyte(RPN_SYM);
|
writebyte(RPN_SYM);
|
||||||
value = getSymbolID(sym);
|
value = getSymbolID(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
writebyte(value & 0xFF);
|
writebyte(value & 0xFF);
|
||||||
writebyte(value >> 8);
|
writebyte(value >> 8);
|
||||||
writebyte(value >> 16);
|
writebyte(value >> 16);
|
||||||
writebyte(value >> 24);
|
writebyte(value >> 24);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case RPN_BANK_SYM:
|
case RPN_BANK_SYM:
|
||||||
{
|
i = 0;
|
||||||
for (unsigned int i = -1; (tzSym[++i] = popbyte()); )
|
do {
|
||||||
;
|
tzSym[i] = popbyte();
|
||||||
struct Symbol *sym = sym_FindSymbol(tzSym);
|
} while (tzSym[i++]);
|
||||||
uint32_t value = getSymbolID(sym);
|
|
||||||
|
// The symbol name is always written expanded
|
||||||
|
sym = sym_FindExactSymbol(tzSym);
|
||||||
|
value = getSymbolID(sym);
|
||||||
|
|
||||||
writebyte(RPN_BANK_SYM);
|
writebyte(RPN_BANK_SYM);
|
||||||
writebyte(value & 0xFF);
|
writebyte(value & 0xFF);
|
||||||
@@ -336,18 +347,15 @@ static void writerpn(uint8_t *rpnexpr, uint32_t *rpnptr, uint8_t *rpn,
|
|||||||
writebyte(value >> 16);
|
writebyte(value >> 16);
|
||||||
writebyte(value >> 24);
|
writebyte(value >> 24);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case RPN_BANK_SECT:
|
|
||||||
{
|
|
||||||
uint8_t b;
|
|
||||||
|
|
||||||
|
case RPN_BANK_SECT:
|
||||||
writebyte(RPN_BANK_SECT);
|
writebyte(RPN_BANK_SECT);
|
||||||
do {
|
do {
|
||||||
b = popbyte();
|
b = popbyte();
|
||||||
writebyte(b);
|
writebyte(b);
|
||||||
} while (b != 0);
|
} while (b != 0);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
writebyte(rpndata);
|
writebyte(rpndata);
|
||||||
break;
|
break;
|
||||||
@@ -471,7 +479,11 @@ static void registerExportedSymbol(struct Symbol *symbol, void *arg)
|
|||||||
*/
|
*/
|
||||||
void out_WriteObject(void)
|
void out_WriteObject(void)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(tzObjectname, "wb");
|
FILE *f;
|
||||||
|
if (strcmp(tzObjectname, "-") != 0)
|
||||||
|
f = fopen(tzObjectname, "wb");
|
||||||
|
else
|
||||||
|
f = fdopen(1, "wb");
|
||||||
|
|
||||||
if (!f)
|
if (!f)
|
||||||
err(1, "Couldn't write file '%s'", tzObjectname);
|
err(1, "Couldn't write file '%s'", tzObjectname);
|
||||||
|
|||||||
@@ -36,8 +36,6 @@
|
|||||||
#include "platform.h" // strncasecmp, strdup
|
#include "platform.h" // strncasecmp, strdup
|
||||||
|
|
||||||
uint32_t nListCountEmpty;
|
uint32_t nListCountEmpty;
|
||||||
char *tzNewMacro;
|
|
||||||
uint32_t ulNewMacroSize;
|
|
||||||
int32_t nPCOffset;
|
int32_t nPCOffset;
|
||||||
bool executeElseBlock; /* If this is set, ELIFs cannot be executed anymore */
|
bool executeElseBlock; /* If this is set, ELIFs cannot be executed anymore */
|
||||||
|
|
||||||
@@ -63,7 +61,7 @@ static size_t strlenUTF8(const char *s)
|
|||||||
uint32_t codep = 0;
|
uint32_t codep = 0;
|
||||||
|
|
||||||
while (*s) {
|
while (*s) {
|
||||||
switch (decode(&state, &codep, (uint8_t)*s)) {
|
switch (decode(&state, &codep, *s)) {
|
||||||
case 1:
|
case 1:
|
||||||
fatalerror("STRLEN: Invalid UTF-8 character\n");
|
fatalerror("STRLEN: Invalid UTF-8 character\n");
|
||||||
break;
|
break;
|
||||||
@@ -97,7 +95,7 @@ static void strsubUTF8(char *dest, const char *src, uint32_t pos, uint32_t len)
|
|||||||
|
|
||||||
/* Advance to starting position in source string. */
|
/* Advance to starting position in source string. */
|
||||||
while (src[srcIndex] && curPos < pos) {
|
while (src[srcIndex] && curPos < pos) {
|
||||||
switch (decode(&state, &codep, (uint8_t)src[srcIndex])) {
|
switch (decode(&state, &codep, src[srcIndex])) {
|
||||||
case 1:
|
case 1:
|
||||||
fatalerror("STRSUB: Invalid UTF-8 character\n");
|
fatalerror("STRSUB: Invalid UTF-8 character\n");
|
||||||
break;
|
break;
|
||||||
@@ -115,7 +113,7 @@ static void strsubUTF8(char *dest, const char *src, uint32_t pos, uint32_t len)
|
|||||||
|
|
||||||
/* Copy from source to destination. */
|
/* Copy from source to destination. */
|
||||||
while (src[srcIndex] && destIndex < MAXSTRLEN && curLen < len) {
|
while (src[srcIndex] && destIndex < MAXSTRLEN && curLen < len) {
|
||||||
switch (decode(&state, &codep, (uint8_t)src[srcIndex])) {
|
switch (decode(&state, &codep, src[srcIndex])) {
|
||||||
case 1:
|
case 1:
|
||||||
fatalerror("STRSUB: Invalid UTF-8 character\n");
|
fatalerror("STRSUB: Invalid UTF-8 character\n");
|
||||||
break;
|
break;
|
||||||
@@ -184,6 +182,7 @@ static inline void failAssertMsg(enum AssertionType type, char const *msg)
|
|||||||
%type <sVal> relocexpr_no_str
|
%type <sVal> relocexpr_no_str
|
||||||
%type <nConstValue> const
|
%type <nConstValue> const
|
||||||
%type <nConstValue> uconst
|
%type <nConstValue> uconst
|
||||||
|
%type <nConstValue> rs_uconst
|
||||||
%type <nConstValue> const_3bit
|
%type <nConstValue> const_3bit
|
||||||
%type <sVal> reloc_8bit
|
%type <sVal> reloc_8bit
|
||||||
%type <sVal> reloc_8bit_no_str
|
%type <sVal> reloc_8bit_no_str
|
||||||
@@ -581,13 +580,8 @@ assert : T_POP_ASSERT assert_type relocexpr
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
shift : T_POP_SHIFT { macro_ShiftCurrentArgs(); }
|
shift : T_POP_SHIFT { macro_ShiftCurrentArgs(1); }
|
||||||
| T_POP_SHIFT uconst
|
| T_POP_SHIFT const { macro_ShiftCurrentArgs($2); }
|
||||||
{
|
|
||||||
int32_t i = $2;
|
|
||||||
while (i--)
|
|
||||||
macro_ShiftCurrentArgs();
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
load : T_POP_LOAD string ',' sectiontype sectorg sectattrs {
|
load : T_POP_LOAD string ',' sectiontype sectorg sectattrs {
|
||||||
@@ -623,19 +617,27 @@ rsset : T_POP_RSSET uconst { sym_AddSet("_RS", $2); }
|
|||||||
rsreset : T_POP_RSRESET { sym_AddSet("_RS", 0); }
|
rsreset : T_POP_RSRESET { sym_AddSet("_RS", 0); }
|
||||||
;
|
;
|
||||||
|
|
||||||
rl : T_LABEL T_POP_RL uconst {
|
rs_uconst : /* empty */ {
|
||||||
|
$$ = 1;
|
||||||
|
}
|
||||||
|
| uconst {
|
||||||
|
$$ = $1;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
rl : T_LABEL T_POP_RL rs_uconst {
|
||||||
sym_AddEqu($1, sym_GetConstantValue("_RS"));
|
sym_AddEqu($1, sym_GetConstantValue("_RS"));
|
||||||
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 4 * $3);
|
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 4 * $3);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
rw : T_LABEL T_POP_RW uconst {
|
rw : T_LABEL T_POP_RW rs_uconst {
|
||||||
sym_AddEqu($1, sym_GetConstantValue("_RS"));
|
sym_AddEqu($1, sym_GetConstantValue("_RS"));
|
||||||
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 2 * $3);
|
sym_AddSet("_RS", sym_GetConstantValue("_RS") + 2 * $3);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
rb : T_LABEL T_POP_RB uconst {
|
rb : T_LABEL T_POP_RB rs_uconst {
|
||||||
sym_AddEqu($1, sym_GetConstantValue("_RS"));
|
sym_AddEqu($1, sym_GetConstantValue("_RS"));
|
||||||
sym_AddSet("_RS", sym_GetConstantValue("_RS") + $3);
|
sym_AddSet("_RS", sym_GetConstantValue("_RS") + $3);
|
||||||
}
|
}
|
||||||
@@ -939,7 +941,7 @@ relocexpr_no_str : scoped_id { rpn_Symbol(&$$, $1); }
|
|||||||
| T_OP_DEF {
|
| T_OP_DEF {
|
||||||
lexer_ToggleStringExpansion(false);
|
lexer_ToggleStringExpansion(false);
|
||||||
} '(' scoped_id ')' {
|
} '(' scoped_id ')' {
|
||||||
struct Symbol const *sym = sym_FindSymbol($4);
|
struct Symbol const *sym = sym_FindScopedSymbol($4);
|
||||||
|
|
||||||
rpn_Number(&$$, !!sym);
|
rpn_Number(&$$, !!sym);
|
||||||
|
|
||||||
159
src/asm/rgbasm.5
159
src/asm/rgbasm.5
@@ -12,7 +12,6 @@
|
|||||||
.Nm rgbasm
|
.Nm rgbasm
|
||||||
.Nd language documentation
|
.Nd language documentation
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Pp
|
|
||||||
This is the full description of the language used by
|
This is the full description of the language used by
|
||||||
.Xr rgbasm 1 .
|
.Xr rgbasm 1 .
|
||||||
The description of the instructions supported by the Game Boy CPU is in
|
The description of the instructions supported by the Game Boy CPU is in
|
||||||
@@ -30,7 +29,6 @@ but any program that processes RGB object files (described in
|
|||||||
.Xr rgbds 5 )
|
.Xr rgbds 5 )
|
||||||
can be used in its place.
|
can be used in its place.
|
||||||
.Sh SYNTAX
|
.Sh SYNTAX
|
||||||
.Pp
|
|
||||||
The syntax is line‐based, just as in any other assembler, meaning that you do one instruction or pseudo‐op per line:
|
The syntax is line‐based, just as in any other assembler, meaning that you do one instruction or pseudo‐op per line:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl Oo Ar label Oc Oo Ar instruction Oc Oo Ar ;\ comment Oc
|
.Dl Oo Ar label Oc Oo Ar instruction Oc Oo Ar ;\ comment Oc
|
||||||
@@ -47,13 +45,23 @@ The assembler
|
|||||||
.Em always
|
.Em always
|
||||||
ignores comments and their contents.
|
ignores comments and their contents.
|
||||||
.Pp
|
.Pp
|
||||||
There are two syntaxes for comments. The most common is that anything that follows a semicolon
|
There are three syntaxes for comments.
|
||||||
|
The most common is that anything that follows a semicolon
|
||||||
.Ql \&;
|
.Ql \&;
|
||||||
not inside a string, is a comment until the end of the line.
|
not inside a string, is a comment until the end of the line.
|
||||||
The other is that lines beginning with a
|
The second is a block comment, beginning with
|
||||||
|
.Ql /*
|
||||||
|
and ending with
|
||||||
|
.Ql */ .
|
||||||
|
It can be split across multiple lines, or occur in the middle of an expression:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
X = /* the value of x
|
||||||
|
should be 3 */ 3
|
||||||
|
.Ed
|
||||||
|
The third is that lines beginning with a
|
||||||
.Ql *
|
.Ql *
|
||||||
(not even spaces before it) are ignored.
|
(not even spaces before it) are ignored.
|
||||||
This second syntax is deprecated (will be removed in a future version) and should be replaced with the first one.
|
This third syntax is deprecated (will be removed in a future version) and should be replaced with either of the first two.
|
||||||
.Pp
|
.Pp
|
||||||
Sometimes lines can be too long and it may be necessary to split them.
|
Sometimes lines can be too long and it may be necessary to split them.
|
||||||
To do so, put a backslash at the end of the line:
|
To do so, put a backslash at the end of the line:
|
||||||
@@ -72,7 +80,6 @@ like this:
|
|||||||
"world!")
|
"world!")
|
||||||
.Ed
|
.Ed
|
||||||
.Sh EXPRESSIONS
|
.Sh EXPRESSIONS
|
||||||
.Pp
|
|
||||||
An expression can be composed of many things.
|
An expression can be composed of many things.
|
||||||
Numerical expressions are always evaluated using signed 32-bit math.
|
Numerical expressions are always evaluated using signed 32-bit math.
|
||||||
Zero is considered to be the only "false" number, all non-zero numbers (including negative) are "true".
|
Zero is considered to be the only "false" number, all non-zero numbers (including negative) are "true".
|
||||||
@@ -86,9 +93,7 @@ section.
|
|||||||
.Pp
|
.Pp
|
||||||
The instructions in the macro-language generally require constant expressions.
|
The instructions in the macro-language generally require constant expressions.
|
||||||
.Ss Numeric Formats
|
.Ss Numeric Formats
|
||||||
.Pp
|
|
||||||
There are a number of numeric formats.
|
There are a number of numeric formats.
|
||||||
.Pp
|
|
||||||
.Bl -column -offset indent "Fixed point (16.16)" "Prefix"
|
.Bl -column -offset indent "Fixed point (16.16)" "Prefix"
|
||||||
.It Sy Format type Ta Sy Prefix Ta Sy Accepted characters
|
.It Sy Format type Ta Sy Prefix Ta Sy Accepted characters
|
||||||
.It Hexadecimal Ta $ Ta 0123456789ABCDEF
|
.It Hexadecimal Ta $ Ta 0123456789ABCDEF
|
||||||
@@ -119,9 +124,7 @@ is equivalent to
|
|||||||
.Pp
|
.Pp
|
||||||
You can also use symbols, which are implicitly replaced with their value.
|
You can also use symbols, which are implicitly replaced with their value.
|
||||||
.Ss Operators
|
.Ss Operators
|
||||||
.Pp
|
|
||||||
A great number of operators you can use in expressions are available (listed from highest to lowest precedence):
|
A great number of operators you can use in expressions are available (listed from highest to lowest precedence):
|
||||||
.Pp
|
|
||||||
.Bl -column -offset indent "!= == <= >= < >"
|
.Bl -column -offset indent "!= == <= >= < >"
|
||||||
.It Sy Operator Ta Sy Meaning
|
.It Sy Operator Ta Sy Meaning
|
||||||
.It Li \&( \&) Ta Precedence override
|
.It Li \&( \&) Ta Precedence override
|
||||||
@@ -167,7 +170,6 @@ and
|
|||||||
.Pp
|
.Pp
|
||||||
! returns 1 if the operand was 0, and 0 otherwise.
|
! returns 1 if the operand was 0, and 0 otherwise.
|
||||||
.Ss Fixed‐point Expressions
|
.Ss Fixed‐point Expressions
|
||||||
.Pp
|
|
||||||
Fixed-point numbers are basically normal (32-bit) integers, which count 65536th's instead of entire units, offering better precision than integers but limiting the range of values.
|
Fixed-point numbers are basically normal (32-bit) integers, which count 65536th's instead of entire units, offering better precision than integers but limiting the range of values.
|
||||||
The upper 16 bits are used for the integer part and the lower 16 bits are used for the fraction (65536ths).
|
The upper 16 bits are used for the integer part and the lower 16 bits are used for the fraction (65536ths).
|
||||||
Since they are still akin to integers, you can use them in normal integer expressions, and some integer operators like
|
Since they are still akin to integers, you can use them in normal integer expressions, and some integer operators like
|
||||||
@@ -182,7 +184,6 @@ The following functions are designed to operate with fixed-point numbers:
|
|||||||
.EQ
|
.EQ
|
||||||
delim $$
|
delim $$
|
||||||
.EN
|
.EN
|
||||||
.Pp
|
|
||||||
.Bl -column -offset indent "ATAN2(x, y)"
|
.Bl -column -offset indent "ATAN2(x, y)"
|
||||||
.It Sy Name Ta Sy Operation
|
.It Sy Name Ta Sy Operation
|
||||||
.It Fn DIV x y Ta $x \[di] y$
|
.It Fn DIV x y Ta $x \[di] y$
|
||||||
@@ -213,7 +214,6 @@ ANGLE = ANGLE + 256.0 ; 256 = 65536 / table_len, with table_len = 256
|
|||||||
ENDR
|
ENDR
|
||||||
.Ed
|
.Ed
|
||||||
.Ss String Expressions
|
.Ss String Expressions
|
||||||
.Pp
|
|
||||||
The most basic string expression is any number of characters contained in double quotes
|
The most basic string expression is any number of characters contained in double quotes
|
||||||
.Pq Ql \&"for instance" .
|
.Pq Ql \&"for instance" .
|
||||||
The backslash character
|
The backslash character
|
||||||
@@ -222,8 +222,7 @@ is special in that it causes the character following it to be
|
|||||||
.Dq escaped ,
|
.Dq escaped ,
|
||||||
meaning that it is treated differently from normal.
|
meaning that it is treated differently from normal.
|
||||||
There are a number of escape sequences you can use within a string:
|
There are a number of escape sequences you can use within a string:
|
||||||
.Pp
|
.Bl -column -offset indent "Qo \[rs]1 Qc \[en] Qo \[rs]9 Qc"
|
||||||
.Bl -column -offset indent "'\1' - '\9'"
|
|
||||||
.It Sy String Ta Sy Meaning
|
.It Sy String Ta Sy Meaning
|
||||||
.It Ql \[rs]\[rs] Ta Produces a backslash
|
.It Ql \[rs]\[rs] Ta Produces a backslash
|
||||||
.It Ql \[rs]" Ta Produces a double quote without terminating
|
.It Ql \[rs]" Ta Produces a double quote without terminating
|
||||||
@@ -278,7 +277,6 @@ The symbol's value is again inserted directly.
|
|||||||
.Pp
|
.Pp
|
||||||
The following functions operate on string expressions.
|
The following functions operate on string expressions.
|
||||||
Most of them return a string, however some of these functions actually return an integer and can be used as part of an integer expression!
|
Most of them return a string, however some of these functions actually return an integer and can be used as part of an integer expression!
|
||||||
.Pp
|
|
||||||
.Bl -column "STRSUB(str, pos, len)"
|
.Bl -column "STRSUB(str, pos, len)"
|
||||||
.It Sy Name Ta Sy Operation
|
.It Sy Name Ta Sy Operation
|
||||||
.It Fn STRLEN string Ta Returns the number of characters in Ar string .
|
.It Fn STRLEN string Ta Returns the number of characters in Ar string .
|
||||||
@@ -290,7 +288,6 @@ Most of them return a string, however some of these functions actually return an
|
|||||||
.It Fn STRLWR str Ta Converts all characters in Ar str No to lower case and returns the new string.
|
.It Fn STRLWR str Ta Converts all characters in Ar str No to lower case and returns the new string.
|
||||||
.El
|
.El
|
||||||
.Ss Character maps
|
.Ss Character maps
|
||||||
.Pp
|
|
||||||
When writing text that is meant to be displayed in the Game Boy, the characters used in the source code may have a different encoding than the default of ASCII.
|
When writing text that is meant to be displayed in the Game Boy, the characters used in the source code may have a different encoding than the default of ASCII.
|
||||||
For example, the tiles used for uppercase letters may be placed starting at tile index 128, which makes it difficult to add text strings to the ROM.
|
For example, the tiles used for uppercase letters may be placed starting at tile index 128, which makes it difficult to add text strings to the ROM.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -325,9 +322,7 @@ This means that any string that the code may want to print as debug information
|
|||||||
The output value of a mapping can be 0.
|
The output value of a mapping can be 0.
|
||||||
If this happens, the assembler will treat this as the end of the string and the rest of it will be trimmed.
|
If this happens, the assembler will treat this as the end of the string and the rest of it will be trimmed.
|
||||||
.Ss Other functions
|
.Ss Other functions
|
||||||
.Pp
|
|
||||||
There are a few other functions that do various useful things:
|
There are a few other functions that do various useful things:
|
||||||
.Pp
|
|
||||||
.Bl -column "DEF(label)"
|
.Bl -column "DEF(label)"
|
||||||
.It Sy Name Ta Sy Operation
|
.It Sy Name Ta Sy Operation
|
||||||
.It Fn BANK arg Ta Returns a bank number.
|
.It Fn BANK arg Ta Returns a bank number.
|
||||||
@@ -356,7 +351,6 @@ String symbols are not expanded within the parentheses.
|
|||||||
or 0 if only RGBLINK can compute its value.
|
or 0 if only RGBLINK can compute its value.
|
||||||
.El
|
.El
|
||||||
.Sh SECTIONS
|
.Sh SECTIONS
|
||||||
.Pp
|
|
||||||
Before you can start writing code, you must define a section.
|
Before you can start writing code, you must define a section.
|
||||||
This tells the assembler what kind of information follows and, if it is code, where to put it.
|
This tells the assembler what kind of information follows and, if it is code, where to put it.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -373,7 +367,6 @@ All other sections must have a unique name, even in different source files, or t
|
|||||||
Possible section
|
Possible section
|
||||||
.Ar type Ns s
|
.Ar type Ns s
|
||||||
are as follows:
|
are as follows:
|
||||||
.Pp
|
|
||||||
.Bl -tag
|
.Bl -tag
|
||||||
.It Ic ROM0
|
.It Ic ROM0
|
||||||
A ROM section.
|
A ROM section.
|
||||||
@@ -559,7 +552,6 @@ SECTION "VRAM Data",ROMX,BANK[2],ALIGN[4] ;\ align to 16 bytes
|
|||||||
.Ed
|
.Ed
|
||||||
.El
|
.El
|
||||||
.Ss Section Stack
|
.Ss Section Stack
|
||||||
.Pp
|
|
||||||
.Ic POPS
|
.Ic POPS
|
||||||
and
|
and
|
||||||
.Ic PUSHS
|
.Ic PUSHS
|
||||||
@@ -572,7 +564,6 @@ will push the current section context on the section stack.
|
|||||||
can then later be used to restore it.
|
can then later be used to restore it.
|
||||||
Useful for defining sections in included files when you don't want to override the section context at the point the file was included.
|
Useful for defining sections in included files when you don't want to override the section context at the point the file was included.
|
||||||
.Ss RAM Code
|
.Ss RAM Code
|
||||||
.Pp
|
|
||||||
Sometimes you want to have some code in RAM.
|
Sometimes you want to have some code in RAM.
|
||||||
But then you can't simply put it in a RAM section, you have to store it in ROM and copy it to RAM at some point.
|
But then you can't simply put it in a RAM section, you have to store it in ROM and copy it to RAM at some point.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -633,7 +624,6 @@ You cannot nest
|
|||||||
.Ic LOAD
|
.Ic LOAD
|
||||||
blocks, nor can you change the current section within them.
|
blocks, nor can you change the current section within them.
|
||||||
.Ss Unionized Sections
|
.Ss Unionized Sections
|
||||||
.Pp
|
|
||||||
When you're tight on RAM, you may want to define overlapping blocks of variables, as explained in the
|
When you're tight on RAM, you may want to define overlapping blocks of variables, as explained in the
|
||||||
.Sx Unions
|
.Sx Unions
|
||||||
section.
|
section.
|
||||||
@@ -727,12 +717,11 @@ and the one from
|
|||||||
.Ql bar.o
|
.Ql bar.o
|
||||||
last.
|
last.
|
||||||
.Sh SYMBOLS
|
.Sh SYMBOLS
|
||||||
.Pp
|
|
||||||
RGBDS supports several types of symbols:
|
RGBDS supports several types of symbols:
|
||||||
.Pp
|
|
||||||
.Bl -hang
|
.Bl -hang
|
||||||
.It Sy Label
|
.It Sy Label
|
||||||
Numerical symbol designating a memory location. May or may not have a value known at assembly time.
|
Numerical symbol designating a memory location.
|
||||||
|
May or may not have a value known at assembly time.
|
||||||
.It Sy Constant
|
.It Sy Constant
|
||||||
Numerical symbol whose value has to be known at assembly time.
|
Numerical symbol whose value has to be known at assembly time.
|
||||||
.It Sy Macro
|
.It Sy Macro
|
||||||
@@ -743,10 +732,16 @@ code that can be invoked later.
|
|||||||
String symbol that can be evaluated, similarly to a macro.
|
String symbol that can be evaluated, similarly to a macro.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
Symbol names can contain letters, numbers, underscores, hashes and
|
Symbol names can contain letters, numbers, underscores
|
||||||
|
.Sq _ ,
|
||||||
|
hashes
|
||||||
|
.Sq #
|
||||||
|
and at signs
|
||||||
.Sq @ .
|
.Sq @ .
|
||||||
However, they must begin with either a letter, a number, or an underscore.
|
However, they must begin with either a letter, or an underscore.
|
||||||
Periods are allowed exclusively for labels, as described below.
|
Periods
|
||||||
|
.Sq \&.
|
||||||
|
are allowed exclusively for labels, as described below.
|
||||||
A symbol cannot have the same name as a reserved keyword.
|
A symbol cannot have the same name as a reserved keyword.
|
||||||
.Em \&In the line where a symbol is defined there must not be any whitespace before it ,
|
.Em \&In the line where a symbol is defined there must not be any whitespace before it ,
|
||||||
otherwise
|
otherwise
|
||||||
@@ -846,7 +841,6 @@ str_SIZEOF EQU 259
|
|||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
There are five commands in the RS group of commands:
|
There are five commands in the RS group of commands:
|
||||||
.Pp
|
|
||||||
.Bl -column "RSSET constexpr"
|
.Bl -column "RSSET constexpr"
|
||||||
.It Sy Command Ta Sy Meaning
|
.It Sy Command Ta Sy Meaning
|
||||||
.It Ic RSRESET Ta Equivalent to Ql RSSET 0 .
|
.It Ic RSRESET Ta Equivalent to Ql RSSET 0 .
|
||||||
@@ -857,6 +851,12 @@ There are five commands in the RS group of commands:
|
|||||||
(In practice, this one cannot be used due to a bug).
|
(In practice, this one cannot be used due to a bug).
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
|
If the argument to
|
||||||
|
.Ic RB , RW ,
|
||||||
|
or
|
||||||
|
.Ic RL
|
||||||
|
is omitted, it's assumed to be 1.
|
||||||
|
.Pp
|
||||||
Note that colons
|
Note that colons
|
||||||
.Ql \&:
|
.Ql \&:
|
||||||
following the name are not allowed.
|
following the name are not allowed.
|
||||||
@@ -923,9 +923,28 @@ Note that a single colon
|
|||||||
.Ql \&:
|
.Ql \&:
|
||||||
following the macro's name is required.
|
following the macro's name is required.
|
||||||
Macros can't be exported or imported.
|
Macros can't be exported or imported.
|
||||||
|
.Pp
|
||||||
|
Plainly nesting macro definitions is not allowed, but this can be worked around using
|
||||||
|
.Ic EQUS .
|
||||||
|
This won't work:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
outer: MACRO
|
||||||
|
inner: MACRO
|
||||||
|
PRINTT "Hello!\[rs]n"
|
||||||
|
ENDM
|
||||||
|
ENDM
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
But this will:
|
||||||
|
.Bd -literal -offset indent
|
||||||
|
outer: MACRO
|
||||||
|
definition equs "inner: MACRO\[rs]nPRINTT \[rs]"Hello!\[rs]\[rs]n\[rs]"\[rs]nENDM"
|
||||||
|
definition
|
||||||
|
PURGE definition
|
||||||
|
ENDM
|
||||||
|
.Ed
|
||||||
.El
|
.El
|
||||||
.Ss Exporting and importing symbols
|
.Ss Exporting and importing symbols
|
||||||
.Pp
|
|
||||||
Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file.
|
Importing and exporting of symbols is a feature that is very useful when your project spans many source files and, for example, you need to jump to a routine defined in another file.
|
||||||
.Pp
|
.Pp
|
||||||
Exporting of symbols has to be done manually, importing is done automatically if
|
Exporting of symbols has to be done manually, importing is done automatically if
|
||||||
@@ -937,15 +956,56 @@ The following will cause
|
|||||||
and so on to be accessible to other files during the link process:
|
and so on to be accessible to other files during the link process:
|
||||||
.Dl Ic EXPORT Ar symbol1 Bq , Ar symbol2 , No ...
|
.Dl Ic EXPORT Ar symbol1 Bq , Ar symbol2 , No ...
|
||||||
.Pp
|
.Pp
|
||||||
|
For example, if you have the following three files:
|
||||||
|
.Pp
|
||||||
|
.Ql a.asm :
|
||||||
|
.Bd -literal -compact
|
||||||
|
SECTION "a", WRAM0
|
||||||
|
LabelA:
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Ql b.asm :
|
||||||
|
.Bd -literal -compact
|
||||||
|
SECTION "b", WRAM0
|
||||||
|
ExportedLabelB1::
|
||||||
|
ExportedLabelB2:
|
||||||
|
EXPORT ExportedLabelB2
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
.Ql c.asm :
|
||||||
|
.Bd -literal -compact
|
||||||
|
SECTION "C", ROM0[0]
|
||||||
|
dw LabelA
|
||||||
|
dw ExportedLabelB1
|
||||||
|
dw ExportedLabelB2
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Then
|
||||||
|
.Ql c.asm
|
||||||
|
can use
|
||||||
|
.Ql ExportedLabelB1
|
||||||
|
and
|
||||||
|
.Ql ExportedLabelB2 ,
|
||||||
|
but not
|
||||||
|
.Ql LabelA ,
|
||||||
|
so linking them together will fail:
|
||||||
|
.Bd -literal
|
||||||
|
$ rgbasm -o a.o a.asm
|
||||||
|
$ rgbasm -o b.o b.asm
|
||||||
|
$ rgbasm -o c.o c.asm
|
||||||
|
$ rgblink a.o b.o c.o
|
||||||
|
error: c.asm(2): Unknown symbol "LabelA"
|
||||||
|
Linking failed with 1 error
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
Note also that only exported symbols will appear in symbol and map files produced by
|
||||||
|
.Xr rgblink 1 .
|
||||||
|
.Pp
|
||||||
.Ic GLOBAL
|
.Ic GLOBAL
|
||||||
is a deprecated synonym for
|
is a deprecated synonym for
|
||||||
.Ic EXPORT ,
|
.Ic EXPORT ,
|
||||||
do not use it.
|
do not use it.
|
||||||
.Pp
|
|
||||||
Note also that only exported symbols will appear in symbol and map files produced by
|
|
||||||
.Xr rgblink 1 .
|
|
||||||
.Ss Purging symbols
|
.Ss Purging symbols
|
||||||
.Pp
|
|
||||||
.Ic PURGE
|
.Ic PURGE
|
||||||
allows you to completely remove a symbol from the symbol table as if it had never existed.
|
allows you to completely remove a symbol from the symbol table as if it had never existed.
|
||||||
.Em USE WITH EXTREME CAUTION!!!
|
.Em USE WITH EXTREME CAUTION!!!
|
||||||
@@ -964,15 +1024,13 @@ Note that, as an exception, string symbols in the argument list of a
|
|||||||
command
|
command
|
||||||
.Em will not be expanded .
|
.Em will not be expanded .
|
||||||
.Ss Predeclared Symbols
|
.Ss Predeclared Symbols
|
||||||
.Pp
|
|
||||||
The following symbols are defined by the assembler:
|
The following symbols are defined by the assembler:
|
||||||
.Pp
|
|
||||||
.Bl -column -offset indent "EQUS" "__ISO_8601_LOCAL__"
|
.Bl -column -offset indent "EQUS" "__ISO_8601_LOCAL__"
|
||||||
.It Sy Type Ta Sy Name Ta Sy Contents
|
.It Sy Type Ta Sy Name Ta Sy Contents
|
||||||
.It Ic EQU Ta Dv @ Ta PC value (essentially, the current memory address)
|
.It Ic EQU Ta Dv @ Ta PC value (essentially, the current memory address)
|
||||||
.It Ic EQU Ta Dv _PI Ta Fixed point \[*p]
|
.It Ic EQU Ta Dv _PI Ta Fixed point \[*p]
|
||||||
.It Ic SET Ta Dv _RS Ta _RS Counter
|
.It Ic SET Ta Dv _RS Ta _RS Counter
|
||||||
.It Ic EQU Ta Dv _NARG Ta Number of arguments passed to macro
|
.It Ic EQU Ta Dv _NARG Ta Number of arguments passed to macro, updated by Ic SHIFT
|
||||||
.It Ic EQU Ta Dv __LINE__ Ta The current line number
|
.It Ic EQU Ta Dv __LINE__ Ta The current line number
|
||||||
.It Ic EQUS Ta Dv __FILE__ Ta The current filename
|
.It Ic EQUS Ta Dv __FILE__ Ta The current filename
|
||||||
.It Ic EQUS Ta Dv __DATE__ Ta Today's date
|
.It Ic EQUS Ta Dv __DATE__ Ta Today's date
|
||||||
@@ -991,7 +1049,6 @@ The following symbols are defined by the assembler:
|
|||||||
.El
|
.El
|
||||||
.Sh DEFINING DATA
|
.Sh DEFINING DATA
|
||||||
.Ss Declaring variables in a RAM section
|
.Ss Declaring variables in a RAM section
|
||||||
.Pp
|
|
||||||
.Ic DS
|
.Ic DS
|
||||||
allocates a number of empty bytes.
|
allocates a number of empty bytes.
|
||||||
This is the preferred method of allocating space in a RAM section.
|
This is the preferred method of allocating space in a RAM section.
|
||||||
@@ -1012,7 +1069,6 @@ In ROM sections, it will be filled with the value passed to the
|
|||||||
command-line option, except when using overlays with
|
command-line option, except when using overlays with
|
||||||
.Fl O .
|
.Fl O .
|
||||||
.Ss Defining constant data
|
.Ss Defining constant data
|
||||||
.Pp
|
|
||||||
.Ic DB
|
.Ic DB
|
||||||
defines a list of bytes that will be stored in the final image.
|
defines a list of bytes that will be stored in the final image.
|
||||||
Ideal for tables and text.
|
Ideal for tables and text.
|
||||||
@@ -1064,7 +1120,6 @@ can be used in a
|
|||||||
.Ic SRAM
|
.Ic SRAM
|
||||||
section.
|
section.
|
||||||
.Ss Including binary files
|
.Ss Including binary files
|
||||||
.Pp
|
|
||||||
You probably have some graphics, level data, etc. you'd like to include.
|
You probably have some graphics, level data, etc. you'd like to include.
|
||||||
Use
|
Use
|
||||||
.Ic INCBIN
|
.Ic INCBIN
|
||||||
@@ -1086,9 +1141,9 @@ The example below includes 256 bytes from data.bin, starting from byte 78.
|
|||||||
INCBIN "data.bin",78,256
|
INCBIN "data.bin",78,256
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The length argument is optional. If only the start position is specified, the bytes from the start position until the end of the file will be included.
|
The length argument is optional.
|
||||||
|
If only the start position is specified, the bytes from the start position until the end of the file will be included.
|
||||||
.Ss Unions
|
.Ss Unions
|
||||||
.Pp
|
|
||||||
Unions allow multiple memory allocations to overlap, like unions in C.
|
Unions allow multiple memory allocations to overlap, like unions in C.
|
||||||
This does not increase the amount of memory available, but allows re-using the same memory region for different purposes.
|
This does not increase the amount of memory available, but allows re-using the same memory region for different purposes.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -1140,7 +1195,6 @@ like commands (see
|
|||||||
.Sx Declaring variables in a RAM section ) .
|
.Sx Declaring variables in a RAM section ) .
|
||||||
.Sh THE MACRO LANGUAGE
|
.Sh THE MACRO LANGUAGE
|
||||||
.Ss Invoking macros
|
.Ss Invoking macros
|
||||||
.Pp
|
|
||||||
You execute the macro by inserting its name.
|
You execute the macro by inserting its name.
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
add a,b
|
add a,b
|
||||||
@@ -1202,7 +1256,6 @@ Also, a macro can have inside an
|
|||||||
.Sy EQUS
|
.Sy EQUS
|
||||||
which references the same macro, which has the same problem.
|
which references the same macro, which has the same problem.
|
||||||
.Pp
|
.Pp
|
||||||
.Pp
|
|
||||||
It's possible to pass arguments to macros as well!
|
It's possible to pass arguments to macros as well!
|
||||||
You retrieve the arguments by using the escape sequences
|
You retrieve the arguments by using the escape sequences
|
||||||
.Ic \[rs]1
|
.Ic \[rs]1
|
||||||
@@ -1276,7 +1329,9 @@ is a special command only available in macros.
|
|||||||
Very useful in
|
Very useful in
|
||||||
.Ic REPT
|
.Ic REPT
|
||||||
blocks.
|
blocks.
|
||||||
It will shift the arguments by one to the left.
|
It will shift the arguments by one to the left, and decrease
|
||||||
|
.Dv _NARG
|
||||||
|
by 1.
|
||||||
.Ic \[rs]1
|
.Ic \[rs]1
|
||||||
will get the value of
|
will get the value of
|
||||||
.Ic \[rs]2 , \[rs]2
|
.Ic \[rs]2 , \[rs]2
|
||||||
@@ -1289,7 +1344,6 @@ This is the only way of accessing the value of arguments from 10 to 256.
|
|||||||
.Ic SHIFT
|
.Ic SHIFT
|
||||||
can optionally be given an integer parameter, and will apply the above shifting that number of times.
|
can optionally be given an integer parameter, and will apply the above shifting that number of times.
|
||||||
.Ss Printing things during assembly
|
.Ss Printing things during assembly
|
||||||
.Pp
|
|
||||||
The next four commands print text and values to the standard output.
|
The next four commands print text and values to the standard output.
|
||||||
Useful for debugging macros, or wherever you may feel the need to tell yourself some important information.
|
Useful for debugging macros, or wherever you may feel the need to tell yourself some important information.
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
@@ -1298,7 +1352,6 @@ PRINTI (2 + 3) / 5
|
|||||||
PRINTV $FF00 + $F0
|
PRINTV $FF00 + $F0
|
||||||
PRINTF MUL(3.14, 3987.0)
|
PRINTF MUL(3.14, 3987.0)
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
|
||||||
.Bl -inset
|
.Bl -inset
|
||||||
.It Ic PRINTT
|
.It Ic PRINTT
|
||||||
prints out a string.
|
prints out a string.
|
||||||
@@ -1317,7 +1370,6 @@ prints out a fixed point value.
|
|||||||
Be careful that none of those automatically print a line feed; if you need one, use
|
Be careful that none of those automatically print a line feed; if you need one, use
|
||||||
.Ic PRINTT "\[rs]n" .
|
.Ic PRINTT "\[rs]n" .
|
||||||
.Ss Automatically repeating blocks of code
|
.Ss Automatically repeating blocks of code
|
||||||
.Pp
|
|
||||||
Suppose you want to unroll a time consuming loop without copy-pasting it.
|
Suppose you want to unroll a time consuming loop without copy-pasting it.
|
||||||
.Ic REPT
|
.Ic REPT
|
||||||
is here for that purpose.
|
is here for that purpose.
|
||||||
@@ -1354,7 +1406,6 @@ As in macros, you can also use the escape sequence
|
|||||||
.Ic REPT
|
.Ic REPT
|
||||||
blocks can be nested.
|
blocks can be nested.
|
||||||
.Ss Aborting the assembly process
|
.Ss Aborting the assembly process
|
||||||
.Pp
|
|
||||||
.Ic FAIL
|
.Ic FAIL
|
||||||
and
|
and
|
||||||
.Ic WARN
|
.Ic WARN
|
||||||
@@ -1375,7 +1426,6 @@ If you need to ensure some assumption is correct when compiling, you can use
|
|||||||
and
|
and
|
||||||
.Ic STATIC_ASSERT .
|
.Ic STATIC_ASSERT .
|
||||||
Syntax examples are given below:
|
Syntax examples are given below:
|
||||||
.Pp
|
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
Function:
|
Function:
|
||||||
xor a
|
xor a
|
||||||
@@ -1426,7 +1476,6 @@ to be emitted;
|
|||||||
.Ic FATAL
|
.Ic FATAL
|
||||||
immediately aborts.
|
immediately aborts.
|
||||||
.Ss Including other source files
|
.Ss Including other source files
|
||||||
.Pp
|
|
||||||
Use
|
Use
|
||||||
.Ic INCLUDE
|
.Ic INCLUDE
|
||||||
to process another assembler file and then return to the current file when done.
|
to process another assembler file and then return to the current file when done.
|
||||||
@@ -1442,7 +1491,6 @@ calls infinitely (or until you run out of memory, whichever comes first).
|
|||||||
INCLUDE "irq.inc"
|
INCLUDE "irq.inc"
|
||||||
.Ed
|
.Ed
|
||||||
.Ss Conditional assembling
|
.Ss Conditional assembling
|
||||||
.Pp
|
|
||||||
The four commands
|
The four commands
|
||||||
.Ic IF , ELIF , ELSE ,
|
.Ic IF , ELIF , ELSE ,
|
||||||
and
|
and
|
||||||
@@ -1492,7 +1540,6 @@ Also, if there is more than one
|
|||||||
block, all of them but the first one are ignored.
|
block, all of them but the first one are ignored.
|
||||||
.Sh MISCELLANEOUS
|
.Sh MISCELLANEOUS
|
||||||
.Ss Changing options while assembling
|
.Ss Changing options while assembling
|
||||||
.Pp
|
|
||||||
.Ic OPT
|
.Ic OPT
|
||||||
can be used to change some of the options during assembling from within the source, instead of defining them on the command-line.
|
can be used to change some of the options during assembling from within the source, instead of defining them on the command-line.
|
||||||
.Pp
|
.Pp
|
||||||
@@ -1522,7 +1569,6 @@ can then later be used to restore them.
|
|||||||
Useful if you want to change some options in an include file and you don't want to destroy the options set by the program that included your file.
|
Useful if you want to change some options in an include file and you don't want to destroy the options set by the program that included your file.
|
||||||
The stack's number of entries is limited only by the amount of memory in your machine.
|
The stack's number of entries is limited only by the amount of memory in your machine.
|
||||||
.Ss Requesting alignment
|
.Ss Requesting alignment
|
||||||
.Pp
|
|
||||||
While
|
While
|
||||||
.Ic ALIGN
|
.Ic ALIGN
|
||||||
as presented in
|
as presented in
|
||||||
@@ -1550,7 +1596,6 @@ is a shorthand for
|
|||||||
.Xr rgbds 7 ,
|
.Xr rgbds 7 ,
|
||||||
.Xr gbz80 7
|
.Xr gbz80 7
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
.Pp
|
|
||||||
.Nm
|
.Nm
|
||||||
was originally written by Carsten S\(/orensen as part of the ASMotor package,
|
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.
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
|
|||||||
/* If there isn't enough room to reserve the space, realloc */
|
/* If there isn't enough room to reserve the space, realloc */
|
||||||
if (!expr->tRPN)
|
if (!expr->tRPN)
|
||||||
expr->nRPNCapacity = 256; /* Initial size */
|
expr->nRPNCapacity = 256; /* Initial size */
|
||||||
else if (expr->nRPNCapacity >= MAXRPNLEN)
|
while (expr->nRPNCapacity - expr->nRPNLength < size) {
|
||||||
|
if (expr->nRPNCapacity >= MAXRPNLEN)
|
||||||
/*
|
/*
|
||||||
* To avoid generating humongous object files, cap the
|
* To avoid generating humongous object files, cap the
|
||||||
* size of RPN expressions
|
* size of RPN expressions
|
||||||
@@ -57,6 +58,7 @@ static uint8_t *reserveSpace(struct Expression *expr, uint32_t size)
|
|||||||
expr->nRPNCapacity = MAXRPNLEN;
|
expr->nRPNCapacity = MAXRPNLEN;
|
||||||
else
|
else
|
||||||
expr->nRPNCapacity *= 2;
|
expr->nRPNCapacity *= 2;
|
||||||
|
}
|
||||||
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
|
expr->tRPN = realloc(expr->tRPN, expr->nRPNCapacity);
|
||||||
|
|
||||||
if (!expr->tRPN)
|
if (!expr->tRPN)
|
||||||
@@ -102,9 +104,9 @@ void rpn_Number(struct Expression *expr, uint32_t i)
|
|||||||
expr->nVal = i;
|
expr->nVal = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rpn_Symbol(struct Expression *expr, char *tzSym)
|
void rpn_Symbol(struct Expression *expr, char const *tzSym)
|
||||||
{
|
{
|
||||||
struct Symbol *sym = sym_FindSymbol(tzSym);
|
struct Symbol *sym = sym_FindScopedSymbol(tzSym);
|
||||||
|
|
||||||
if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
|
if (sym_IsPC(sym) && !sect_GetSymbolSection()) {
|
||||||
error("PC has no value outside a section\n");
|
error("PC has no value outside a section\n");
|
||||||
@@ -113,15 +115,15 @@ void rpn_Symbol(struct Expression *expr, char *tzSym)
|
|||||||
rpn_Init(expr);
|
rpn_Init(expr);
|
||||||
expr->isSymbol = true;
|
expr->isSymbol = true;
|
||||||
|
|
||||||
sym_Ref(tzSym);
|
|
||||||
makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time"
|
makeUnknown(expr, sym_IsPC(sym) ? "PC is not constant at assembly time"
|
||||||
: "'%s' is not constant at assembly time", tzSym);
|
: "'%s' is not constant at assembly time", tzSym);
|
||||||
|
sym = sym_Ref(tzSym);
|
||||||
expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
|
expr->nRPNPatchSize += 5; /* 1-byte opcode + 4-byte symbol ID */
|
||||||
|
|
||||||
size_t nameLen = strlen(tzSym) + 1; /* Don't forget NUL! */
|
size_t nameLen = strlen(sym->name) + 1; /* Don't forget NUL! */
|
||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
*ptr++ = RPN_SYM;
|
*ptr++ = RPN_SYM;
|
||||||
memcpy(ptr, tzSym, nameLen);
|
memcpy(ptr, sym->name, nameLen);
|
||||||
|
|
||||||
/* RGBLINK assumes PC is at the byte being computed... */
|
/* RGBLINK assumes PC is at the byte being computed... */
|
||||||
if (sym_IsPC(sym) && nPCOffset) {
|
if (sym_IsPC(sym) && nPCOffset) {
|
||||||
@@ -155,7 +157,7 @@ void rpn_BankSelf(struct Expression *expr)
|
|||||||
|
|
||||||
void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
|
void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
|
||||||
{
|
{
|
||||||
struct Symbol const *sym = sym_FindSymbol(tzSym);
|
struct Symbol const *sym = sym_FindScopedSymbol(tzSym);
|
||||||
|
|
||||||
/* The @ symbol is treated differently. */
|
/* The @ symbol is treated differently. */
|
||||||
if (sym_IsPC(sym)) {
|
if (sym_IsPC(sym)) {
|
||||||
@@ -167,10 +169,8 @@ void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
|
|||||||
if (sym && !sym_IsLabel(sym)) {
|
if (sym && !sym_IsLabel(sym)) {
|
||||||
error("BANK argument must be a label\n");
|
error("BANK argument must be a label\n");
|
||||||
} else {
|
} else {
|
||||||
sym_Ref(tzSym);
|
sym = sym_Ref(tzSym);
|
||||||
if (!sym)
|
assert(sym); // If the symbol didn't exist, it should have been created
|
||||||
/* If the symbol didn't exist, `sym_Ref` created it */
|
|
||||||
sym = sym_FindSymbol(tzSym);
|
|
||||||
|
|
||||||
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != -1) {
|
if (sym_GetSection(sym) && sym_GetSection(sym)->bank != -1) {
|
||||||
/* Symbol's section is known and bank is fixed */
|
/* Symbol's section is known and bank is fixed */
|
||||||
@@ -179,10 +179,10 @@ void rpn_BankSymbol(struct Expression *expr, char const *tzSym)
|
|||||||
makeUnknown(expr, "\"%s\"'s bank is not known", tzSym);
|
makeUnknown(expr, "\"%s\"'s bank is not known", tzSym);
|
||||||
expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */
|
expr->nRPNPatchSize += 5; /* opcode + 4-byte sect ID */
|
||||||
|
|
||||||
size_t nameLen = strlen(tzSym) + 1; /* Room for NUL! */
|
size_t nameLen = strlen(sym->name) + 1; /* Room for NUL! */
|
||||||
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
uint8_t *ptr = reserveSpace(expr, nameLen + 1);
|
||||||
*ptr++ = RPN_BANK_SYM;
|
*ptr++ = RPN_BANK_SYM;
|
||||||
memcpy(ptr, tzSym, nameLen);
|
memcpy(ptr, sym->name, nameLen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,7 +296,7 @@ struct Symbol const *rpn_SymbolOf(struct Expression const *expr)
|
|||||||
{
|
{
|
||||||
if (!rpn_isSymbol(expr))
|
if (!rpn_isSymbol(expr))
|
||||||
return NULL;
|
return NULL;
|
||||||
return sym_FindSymbol((char *)expr->tRPN + 1);
|
return sym_FindScopedSymbol((char *)expr->tRPN + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
|
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
|
||||||
@@ -307,7 +307,9 @@ bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *sym)
|
|||||||
if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
|
if (!sym1 || !sym || sym1->type != SYM_LABEL || sym->type != SYM_LABEL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return sym_GetSection(sym1) == sym_GetSection(sym);
|
struct Section const *section1 = sym_GetSection(sym1);
|
||||||
|
struct Section const *section2 = sym_GetSection(sym);
|
||||||
|
return section1 && (section1 == section2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isDiffConstant(struct Expression const *src1,
|
static bool isDiffConstant(struct Expression const *src1,
|
||||||
|
|||||||
@@ -378,6 +378,7 @@ uint32_t sect_GetOutputOffset(void)
|
|||||||
|
|
||||||
void sect_AlignPC(uint8_t alignment, uint16_t offset)
|
void sect_AlignPC(uint8_t alignment, uint16_t offset)
|
||||||
{
|
{
|
||||||
|
checksection();
|
||||||
struct Section *sect = sect_GetSymbolSection();
|
struct Section *sect = sect_GetSymbolSection();
|
||||||
|
|
||||||
if (sect->org != -1) {
|
if (sect->org != -1) {
|
||||||
@@ -619,7 +620,7 @@ void out_PCRelByte(struct Expression *expr)
|
|||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(1);
|
reserveSpace(1);
|
||||||
struct Symbol const *pc = sym_FindSymbol("@");
|
struct Symbol const *pc = sym_GetPC();
|
||||||
|
|
||||||
if (!rpn_IsDiffConstant(expr, pc)) {
|
if (!rpn_IsDiffConstant(expr, pc)) {
|
||||||
createPatch(PATCHTYPE_JR, expr);
|
createPatch(PATCHTYPE_JR, expr);
|
||||||
@@ -662,9 +663,9 @@ void out_BinaryFile(char const *s, int32_t startPos)
|
|||||||
|
|
||||||
if (fstk_FindFile(s, &fullPath, &size))
|
if (fstk_FindFile(s, &fullPath, &size))
|
||||||
f = fopen(fullPath, "rb");
|
f = fopen(fullPath, "rb");
|
||||||
|
free(fullPath);
|
||||||
|
|
||||||
if (!f) {
|
if (!f) {
|
||||||
free(fullPath);
|
|
||||||
if (oGeneratedMissingIncludes) {
|
if (oGeneratedMissingIncludes) {
|
||||||
oFailedOnMissingInclude = true;
|
oFailedOnMissingInclude = true;
|
||||||
return;
|
return;
|
||||||
@@ -681,6 +682,7 @@ void out_BinaryFile(char const *s, int32_t startPos)
|
|||||||
|
|
||||||
if (startPos >= fsize) {
|
if (startPos >= fsize) {
|
||||||
error("Specified start position is greater than length of file\n");
|
error("Specified start position is greater than length of file\n");
|
||||||
|
fclose(f);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,7 +707,6 @@ void out_BinaryFile(char const *s, int32_t startPos)
|
|||||||
error("Error reading INCBIN file '%s': %s\n", s, strerror(errno));
|
error("Error reading INCBIN file '%s': %s\n", s, strerror(errno));
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
free(fullPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
|
void out_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length)
|
||||||
|
|||||||
@@ -222,32 +222,42 @@ static void fullSymbolName(char *output, size_t outputSize,
|
|||||||
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
|
fatalerror("Symbol name is too long: '%s%s'\n", scopeName, localName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
struct Symbol *sym_FindExactSymbol(char const *name)
|
||||||
* Find a symbol by name and scope
|
|
||||||
*/
|
|
||||||
static struct Symbol *findsymbol(char const *s, char const *scope)
|
|
||||||
{
|
{
|
||||||
|
return hash_GetElement(symbols, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Symbol *sym_FindUnscopedSymbol(char const *name)
|
||||||
|
{
|
||||||
|
if (strchr(name, '.')) {
|
||||||
|
error("Expected non-scoped symbol name, not \"%s\"\n", name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return sym_FindExactSymbol(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Symbol *sym_FindScopedSymbol(char const *name)
|
||||||
|
{
|
||||||
|
char const *dotPtr = strchr(name, '.');
|
||||||
|
|
||||||
|
if (dotPtr) {
|
||||||
|
if (strchr(dotPtr + 1, '.'))
|
||||||
|
fatalerror("'%s' is a nonsensical reference to a nested local symbol\n",
|
||||||
|
name);
|
||||||
|
/* If auto-scoped local label, expand the name */
|
||||||
|
if (dotPtr == name) { /* Meaning, the name begins with the dot */
|
||||||
char fullname[MAXSYMLEN + 1];
|
char fullname[MAXSYMLEN + 1];
|
||||||
|
|
||||||
if (s[0] == '.' && scope) {
|
fullSymbolName(fullname, sizeof(fullname), name, labelScope);
|
||||||
fullSymbolName(fullname, sizeof(fullname), s, scope);
|
return sym_FindExactSymbol(fullname);
|
||||||
s = fullname;
|
}
|
||||||
|
}
|
||||||
|
return sym_FindExactSymbol(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
char const *separator = strchr(s, '.');
|
struct Symbol const *sym_GetPC(void)
|
||||||
|
|
||||||
if (separator && strchr(separator + 1, '.'))
|
|
||||||
fatalerror("'%s' is a nonsensical reference to a nested local symbol\n", s);
|
|
||||||
|
|
||||||
return hash_GetElement(symbols, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a symbol by name, with automatically determined scope
|
|
||||||
*/
|
|
||||||
struct Symbol *sym_FindSymbol(char const *symName)
|
|
||||||
{
|
{
|
||||||
return findsymbol(symName, symName[0] == '.' ? labelScope : NULL);
|
return PCSymbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool isReferenced(struct Symbol const *sym)
|
static inline bool isReferenced(struct Symbol const *sym)
|
||||||
@@ -260,7 +270,7 @@ static inline bool isReferenced(struct Symbol const *sym)
|
|||||||
*/
|
*/
|
||||||
void sym_Purge(char const *symName)
|
void sym_Purge(char const *symName)
|
||||||
{
|
{
|
||||||
struct Symbol *symbol = sym_FindSymbol(symName);
|
struct Symbol *symbol = sym_FindScopedSymbol(symName);
|
||||||
|
|
||||||
if (!symbol) {
|
if (!symbol) {
|
||||||
error("'%s' not defined\n", symName);
|
error("'%s' not defined\n", symName);
|
||||||
@@ -312,7 +322,7 @@ uint32_t sym_GetConstantSymValue(struct Symbol const *sym)
|
|||||||
*/
|
*/
|
||||||
uint32_t sym_GetConstantValue(char const *s)
|
uint32_t sym_GetConstantValue(char const *s)
|
||||||
{
|
{
|
||||||
struct Symbol const *sym = sym_FindSymbol(s);
|
struct Symbol const *sym = sym_FindScopedSymbol(s);
|
||||||
|
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
error("'%s' not defined\n", s);
|
error("'%s' not defined\n", s);
|
||||||
@@ -322,23 +332,6 @@ uint32_t sym_GetConstantValue(char const *s)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Return a defined symbols value... aborts if not defined yet
|
|
||||||
*/
|
|
||||||
uint32_t sym_GetDefinedValue(char const *s)
|
|
||||||
{
|
|
||||||
struct Symbol const *sym = sym_FindSymbol(s);
|
|
||||||
|
|
||||||
if (sym == NULL || !sym_IsDefined(sym))
|
|
||||||
error("'%s' not defined\n", s);
|
|
||||||
else if (!sym_IsNumeric(sym))
|
|
||||||
error("'%s' is a macro or string symbol\n", s);
|
|
||||||
else
|
|
||||||
return sym_GetValue(sym);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char const *sym_GetCurrentSymbolScope(void)
|
char const *sym_GetCurrentSymbolScope(void)
|
||||||
{
|
{
|
||||||
return labelScope;
|
return labelScope;
|
||||||
@@ -356,11 +349,11 @@ void sym_SetCurrentSymbolScope(char const *newScope)
|
|||||||
*/
|
*/
|
||||||
static struct Symbol *createNonrelocSymbol(char const *symbolName)
|
static struct Symbol *createNonrelocSymbol(char const *symbolName)
|
||||||
{
|
{
|
||||||
struct Symbol *symbol = findsymbol(symbolName, NULL);
|
struct Symbol *symbol = sym_FindExactSymbol(symbolName);
|
||||||
|
|
||||||
if (!symbol)
|
if (!symbol) {
|
||||||
symbol = createsymbol(symbolName);
|
symbol = createsymbol(symbolName);
|
||||||
else if (sym_IsDefined(symbol)) {
|
} else if (sym_IsDefined(symbol)) {
|
||||||
error("'%s' already defined at ", symbolName);
|
error("'%s' already defined at ", symbolName);
|
||||||
dumpFilename(symbol);
|
dumpFilename(symbol);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
@@ -417,7 +410,7 @@ struct Symbol *sym_AddString(char const *symName, char const *value)
|
|||||||
*/
|
*/
|
||||||
struct Symbol *sym_AddSet(char const *symName, int32_t value)
|
struct Symbol *sym_AddSet(char const *symName, int32_t value)
|
||||||
{
|
{
|
||||||
struct Symbol *sym = findsymbol(symName, NULL);
|
struct Symbol *sym = sym_FindExactSymbol(symName);
|
||||||
|
|
||||||
if (sym == NULL) {
|
if (sym == NULL) {
|
||||||
sym = createsymbol(symName);
|
sym = createsymbol(symName);
|
||||||
@@ -426,8 +419,8 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
|
|||||||
symName, sym->type == SYM_LABEL ? "label" : "constant");
|
symName, sym->type == SYM_LABEL ? "label" : "constant");
|
||||||
dumpFilename(sym);
|
dumpFilename(sym);
|
||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
|
return sym;
|
||||||
} else {
|
} else {
|
||||||
/* TODO: can the scope be incorrect when taking over refs? */
|
|
||||||
updateSymbolFilename(sym);
|
updateSymbolFilename(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,7 +438,7 @@ struct Symbol *sym_AddSet(char const *symName, int32_t value)
|
|||||||
static struct Symbol *addLabel(char const *name)
|
static struct Symbol *addLabel(char const *name)
|
||||||
{
|
{
|
||||||
assert(name[0] != '.'); /* The symbol name must have been expanded prior */
|
assert(name[0] != '.'); /* The symbol name must have been expanded prior */
|
||||||
struct Symbol *sym = findsymbol(name, NULL); /* Due to this, don't look for expansions */
|
struct Symbol *sym = sym_FindExactSymbol(name);
|
||||||
|
|
||||||
if (!sym) {
|
if (!sym) {
|
||||||
sym = createsymbol(name);
|
sym = createsymbol(name);
|
||||||
@@ -527,7 +520,7 @@ struct Symbol *sym_AddLabel(char const *name)
|
|||||||
*/
|
*/
|
||||||
void sym_Export(char const *symName)
|
void sym_Export(char const *symName)
|
||||||
{
|
{
|
||||||
struct Symbol *sym = sym_FindSymbol(symName);
|
struct Symbol *sym = sym_FindScopedSymbol(symName);
|
||||||
|
|
||||||
/* If the symbol doesn't exist, create a ref that can be purged */
|
/* If the symbol doesn't exist, create a ref that can be purged */
|
||||||
if (!sym)
|
if (!sym)
|
||||||
@@ -561,7 +554,7 @@ struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body,
|
|||||||
*/
|
*/
|
||||||
struct Symbol *sym_Ref(char const *symName)
|
struct Symbol *sym_Ref(char const *symName)
|
||||||
{
|
{
|
||||||
struct Symbol *nsym = sym_FindSymbol(symName);
|
struct Symbol *nsym = sym_FindScopedSymbol(symName);
|
||||||
|
|
||||||
if (nsym == NULL) {
|
if (nsym == NULL) {
|
||||||
char fullname[MAXSYMLEN + 1];
|
char fullname[MAXSYMLEN + 1];
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ size_t readUTF8Char(uint8_t *dest, char const *src)
|
|||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (decode(&state, &codep, (uint8_t)src[i]) == 1)
|
if (decode(&state, &codep, src[i]) == 1)
|
||||||
fatalerror("invalid UTF-8 character\n");
|
fatalerror("invalid UTF-8 character\n");
|
||||||
|
|
||||||
dest[i] = src[i];
|
dest[i] = src[i];
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ static enum WarningState const defaultWarnings[NB_WARNINGS] = {
|
|||||||
[WARNING_EMPTY_ENTRY] = WARNING_DISABLED,
|
[WARNING_EMPTY_ENTRY] = WARNING_DISABLED,
|
||||||
[WARNING_LARGE_CONSTANT] = WARNING_DISABLED,
|
[WARNING_LARGE_CONSTANT] = WARNING_DISABLED,
|
||||||
[WARNING_LONG_STR] = WARNING_DISABLED,
|
[WARNING_LONG_STR] = WARNING_DISABLED,
|
||||||
|
[WARNING_NESTED_COMMENT] = WARNING_ENABLED,
|
||||||
[WARNING_OBSOLETE] = WARNING_ENABLED,
|
[WARNING_OBSOLETE] = WARNING_ENABLED,
|
||||||
[WARNING_SHIFT] = WARNING_DISABLED,
|
[WARNING_SHIFT] = WARNING_DISABLED,
|
||||||
[WARNING_SHIFT_AMOUNT] = WARNING_DISABLED,
|
[WARNING_SHIFT_AMOUNT] = WARNING_DISABLED,
|
||||||
@@ -75,6 +76,7 @@ static char const *warningFlags[NB_WARNINGS_ALL] = {
|
|||||||
"empty-entry",
|
"empty-entry",
|
||||||
"large-constant",
|
"large-constant",
|
||||||
"long-string",
|
"long-string",
|
||||||
|
"nested-comment",
|
||||||
"obsolete",
|
"obsolete",
|
||||||
"shift",
|
"shift",
|
||||||
"shift-amount",
|
"shift-amount",
|
||||||
@@ -104,6 +106,7 @@ static uint8_t const _wallCommands[] = {
|
|||||||
/* Warnings that are less likely to indicate an error */
|
/* Warnings that are less likely to indicate an error */
|
||||||
static uint8_t const _wextraCommands[] = {
|
static uint8_t const _wextraCommands[] = {
|
||||||
WARNING_EMPTY_ENTRY,
|
WARNING_EMPTY_ENTRY,
|
||||||
|
WARNING_NESTED_COMMENT,
|
||||||
META_WARNING_DONE
|
META_WARNING_DONE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -115,6 +118,7 @@ static uint8_t const _weverythingCommands[] = {
|
|||||||
WARNING_EMPTY_ENTRY,
|
WARNING_EMPTY_ENTRY,
|
||||||
WARNING_LARGE_CONSTANT,
|
WARNING_LARGE_CONSTANT,
|
||||||
WARNING_LONG_STR,
|
WARNING_LONG_STR,
|
||||||
|
WARNING_NESTED_COMMENT,
|
||||||
WARNING_OBSOLETE,
|
WARNING_OBSOLETE,
|
||||||
WARNING_SHIFT,
|
WARNING_SHIFT,
|
||||||
WARNING_SHIFT_AMOUNT,
|
WARNING_SHIFT_AMOUNT,
|
||||||
@@ -218,7 +222,7 @@ void error(const char *fmt, ...)
|
|||||||
nbErrors++;
|
nbErrors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void fatalerror(const char *fmt, ...)
|
_Noreturn void fatalerror(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@@ -246,7 +250,7 @@ void warning(enum WarningID id, char const *fmt, ...)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case WARNING_DEFAULT:
|
case WARNING_DEFAULT:
|
||||||
trap_;
|
unreachable_();
|
||||||
/* Not reached */
|
/* Not reached */
|
||||||
|
|
||||||
case WARNING_ENABLED:
|
case WARNING_ENABLED:
|
||||||
|
|||||||
8
src/extern/err.c
vendored
8
src/extern/err.c
vendored
@@ -34,7 +34,7 @@ void rgbds_vwarnx(const char *fmt, va_list ap)
|
|||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap)
|
_Noreturn void rgbds_verr(int status, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "error: ");
|
fprintf(stderr, "error: ");
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
@@ -46,7 +46,7 @@ noreturn_ void rgbds_verr(int status, const char *fmt, va_list ap)
|
|||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_verrx(int status, const char *fmt, va_list ap)
|
_Noreturn void rgbds_verrx(int status, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "error");
|
fprintf(stderr, "error");
|
||||||
if (fmt) {
|
if (fmt) {
|
||||||
@@ -75,7 +75,7 @@ void rgbds_warnx(const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_err(int status, const char *fmt, ...)
|
_Noreturn void rgbds_err(int status, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ noreturn_ void rgbds_err(int status, const char *fmt, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void rgbds_errx(int status, const char *fmt, ...)
|
_Noreturn void rgbds_errx(int status, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
|||||||
2
src/extern/utf8decoder.c
vendored
2
src/extern/utf8decoder.c
vendored
@@ -38,7 +38,7 @@ static const uint8_t utf8d[] = {
|
|||||||
1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* s8 */
|
1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* s8 */
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t decode(uint32_t *state, uint32_t *codep, uint32_t byte)
|
uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte)
|
||||||
{
|
{
|
||||||
uint32_t type = utf8d[byte];
|
uint32_t type = utf8d[byte];
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,10 @@ as destination can omit the destination as it is assumed to be register
|
|||||||
.Sy A
|
.Sy A
|
||||||
by default.
|
by default.
|
||||||
The following two lines have the same effect:
|
The following two lines have the same effect:
|
||||||
.Pp
|
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
OR A,B
|
OR A,B
|
||||||
OR B
|
OR B
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
|
||||||
.Sh LEGEND
|
.Sh LEGEND
|
||||||
List of abbreviations used in this document.
|
List of abbreviations used in this document.
|
||||||
.Bl -tag
|
.Bl -tag
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
program converts PNG images into the Nintendo Game Boy's planar tile format.
|
program converts PNG images into the Nintendo Game Boy's planar tile format.
|
||||||
|
.Pp
|
||||||
The resulting colors and their palette indices are determined differently depending on the input PNG file:
|
The resulting colors and their palette indices are determined differently depending on the input PNG file:
|
||||||
.Bl -dash -width Ds
|
.Bl -dash -width Ds
|
||||||
.It
|
.It
|
||||||
@@ -39,7 +39,7 @@ If the image has multiple shades that map to the same index, the palette is inst
|
|||||||
.It
|
.It
|
||||||
If the image has color (or the grayscale method failed), the colors are sorted from lightest to darkest.
|
If the image has color (or the grayscale method failed), the colors are sorted from lightest to darkest.
|
||||||
.El
|
.El
|
||||||
|
.Pp
|
||||||
The input image may not contain more colors than the selected bit depth allows.
|
The input image may not contain more colors than the selected bit depth allows.
|
||||||
Transparent pixels are set to palette index 0.
|
Transparent pixels are set to palette index 0.
|
||||||
.Sh ARGUMENTS
|
.Sh ARGUMENTS
|
||||||
|
|||||||
@@ -64,6 +64,22 @@ bool hash_AddElement(HashMap map, char const *key, void *element)
|
|||||||
return newEntry->next != NULL;
|
return newEntry->next != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hash_ReplaceElement(HashMap const map, char const *key, void *element)
|
||||||
|
{
|
||||||
|
HashType hashedKey = hash(key);
|
||||||
|
struct HashMapEntry *ptr = map[(HalfHashType)hashedKey];
|
||||||
|
|
||||||
|
while (ptr) {
|
||||||
|
if (hashedKey >> HALF_HASH_NB_BITS == ptr->hash
|
||||||
|
&& !strcmp(ptr->key, key)) {
|
||||||
|
ptr->content = element;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool hash_RemoveElement(HashMap map, char const *key)
|
bool hash_RemoveElement(HashMap map, char const *key)
|
||||||
{
|
{
|
||||||
HashType hashedKey = hash(key);
|
HashType hashedKey = hash(key);
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ void assign_AssignSections(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
trap_;
|
unreachable_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign_Cleanup(void)
|
void assign_Cleanup(void)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@@ -99,7 +100,7 @@ void error(struct FileStackNode const *where, uint32_t lineNo, char const *fmt,
|
|||||||
nbErrors++;
|
nbErrors++;
|
||||||
}
|
}
|
||||||
|
|
||||||
noreturn_ void fatal(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
|
_Noreturn void fatal(struct FileStackNode const *where, uint32_t lineNo, char const *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
@@ -126,7 +127,13 @@ FILE *openFile(char const *fileName, char const *mode)
|
|||||||
if (!fileName)
|
if (!fileName)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
FILE *file = fopen(fileName, mode);
|
FILE *file;
|
||||||
|
if (strcmp(fileName, "-") != 0)
|
||||||
|
file = fopen(fileName, mode);
|
||||||
|
else if (mode[0] == 'r')
|
||||||
|
file = fdopen(0, mode);
|
||||||
|
else
|
||||||
|
file = fdopen(1, mode);
|
||||||
|
|
||||||
if (!file)
|
if (!file)
|
||||||
err(1, "Could not open file \"%s\"", fileName);
|
err(1, "Could not open file \"%s\"", fileName);
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID)
|
|||||||
if (!nodes[fileID].nodes)
|
if (!nodes[fileID].nodes)
|
||||||
err(1, "Failed to get memory for %s's nodes", fileName);
|
err(1, "Failed to get memory for %s's nodes", fileName);
|
||||||
verbosePrint("Reading %u nodes...\n", nodes[fileID].nbNodes);
|
verbosePrint("Reading %u nodes...\n", nodes[fileID].nbNodes);
|
||||||
for (uint32_t i = 0; i < nodes[fileID].nbNodes; i++)
|
for (uint32_t i = nodes[fileID].nbNodes; i--; )
|
||||||
readFileStackNode(file, nodes[fileID].nodes, i, fileName);
|
readFileStackNode(file, nodes[fileID].nodes, i, fileName);
|
||||||
|
|
||||||
/* This file's symbols, kept to link sections to them */
|
/* This file's symbols, kept to link sections to them */
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ option!
|
|||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
All you need for a basic ROM is an object file, which can be made into a ROM image like so:
|
All you need for a basic ROM is an object file, which can be made into a ROM image like so:
|
||||||
.Pp
|
.Pp
|
||||||
.D1 $ rgblink -o bar.gb foo.o
|
.Dl $ rgblink -o bar.gb foo.o
|
||||||
.Pp
|
.Pp
|
||||||
The resulting
|
The resulting
|
||||||
.Ar bar.gb
|
.Ar bar.gb
|
||||||
@@ -126,12 +126,10 @@ You should use
|
|||||||
to fix these so that the program will actually run in a Game Boy:
|
to fix these so that the program will actually run in a Game Boy:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl $ rgbfix -v bar.gb
|
.Dl $ rgbfix -v bar.gb
|
||||||
.Ed
|
|
||||||
.Pp
|
.Pp
|
||||||
Here is a more complete example:
|
Here is a more complete example:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl $ rgblink -o bin/game.gb -n bin/game.sym -p 0xFF obj/title.o obj/engine.o
|
.Dl $ rgblink -o bin/game.gb -n bin/game.sym -p 0xFF obj/title.o obj/engine.o
|
||||||
.Ed
|
|
||||||
.Sh BUGS
|
.Sh BUGS
|
||||||
Please report bugs on
|
Please report bugs on
|
||||||
.Lk https://github.com/gbdev/rgbds/issues GitHub .
|
.Lk https://github.com/gbdev/rgbds/issues GitHub .
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ They can be lowercase or uppercase, it is ignored.
|
|||||||
Any line can contain a comment starting with
|
Any line can contain a comment starting with
|
||||||
.Ql \&;
|
.Ql \&;
|
||||||
that ends at the end of the line:
|
that ends at the end of the line:
|
||||||
.Pp
|
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
ROMX $F ; This is a comment
|
ROMX $F ; This is a comment
|
||||||
"Functions to read array"
|
"Functions to read array"
|
||||||
@@ -86,6 +85,6 @@ in the linker script.
|
|||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
.Nm
|
.Nm
|
||||||
was originally written by Carsten S\(/orensen as part of the ASMotor package,
|
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
|
and was later packaged in RGBDS by Justin Lloyd.
|
||||||
number of contributors at
|
It is now maintained by a number of contributors at
|
||||||
.Lk https://github.com/gbdev/rgbds .
|
.Lk https://github.com/gbdev/rgbds .
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ static void processCommand(enum LinkerScriptCommand command, uint16_t arg,
|
|||||||
{
|
{
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case COMMAND_INVALID:
|
case COMMAND_INVALID:
|
||||||
trap_;
|
unreachable_();
|
||||||
|
|
||||||
case COMMAND_ORG:
|
case COMMAND_ORG:
|
||||||
break;
|
break;
|
||||||
@@ -331,8 +331,8 @@ static void processCommand(enum LinkerScriptCommand command, uint16_t arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (arg < *pc)
|
if (arg < *pc)
|
||||||
errx(1, "%s(%" PRIu32 "): `%s` cannot be used to go backwards",
|
errx(1, "%s(%" PRIu32 "): `%s` cannot be used to go backwards (currently at $%x)",
|
||||||
linkerScriptName, lineNo, commands[command]);
|
linkerScriptName, lineNo, commands[command], *pc);
|
||||||
*pc = arg;
|
*pc = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,12 +391,12 @@ struct SectionPlacement *script_NextSection(void)
|
|||||||
|
|
||||||
switch (parserState) {
|
switch (parserState) {
|
||||||
case PARSER_FIRSTTIME:
|
case PARSER_FIRSTTIME:
|
||||||
trap_;
|
unreachable_();
|
||||||
|
|
||||||
case PARSER_LINESTART:
|
case PARSER_LINESTART:
|
||||||
switch (token->type) {
|
switch (token->type) {
|
||||||
case TOKEN_INVALID:
|
case TOKEN_INVALID:
|
||||||
trap_;
|
unreachable_();
|
||||||
|
|
||||||
case TOKEN_EOF:
|
case TOKEN_EOF:
|
||||||
if (!popFile())
|
if (!popFile())
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SECTION_NORMAL:
|
case SECTION_NORMAL:
|
||||||
trap_;
|
unreachable_();
|
||||||
}
|
}
|
||||||
|
|
||||||
other->nextu = target->nextu;
|
other->nextu = target->nextu;
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ and
|
|||||||
.Xr rgblink 1 .
|
.Xr rgblink 1 .
|
||||||
.Em Please note that the specifications may change .
|
.Em 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.
|
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
|
.Sh FILE STRUCTURE
|
||||||
The following types are used:
|
The following types are used:
|
||||||
.Pp
|
.Pp
|
||||||
@@ -29,7 +28,6 @@ is an 8‐bit integer.
|
|||||||
.Ar STRING
|
.Ar STRING
|
||||||
is a 0‐terminated string of
|
is a 0‐terminated string of
|
||||||
.Ar BYTE .
|
.Ar BYTE .
|
||||||
.Pp
|
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
; Header
|
; Header
|
||||||
|
|
||||||
@@ -219,8 +217,7 @@ The
|
|||||||
In the RGB format, RPN expressions are stored as
|
In the RGB format, RPN expressions are stored as
|
||||||
.Ar BYTE Ns s
|
.Ar BYTE Ns s
|
||||||
with some bytes being special prefixes for integers and symbols.
|
with some bytes being special prefixes for integers and symbols.
|
||||||
.Pp
|
.Bl -column -offset indent "Sy String" "Sy String"
|
||||||
.Bl -column -offset indent ".Sy String" ".Sy String"
|
|
||||||
.It Sy Value Ta Sy Meaning
|
.It Sy Value Ta Sy Meaning
|
||||||
.It Li $00 Ta Li + operator
|
.It Li $00 Ta Li + operator
|
||||||
.It Li $01 Ta Li - operator
|
.It Li $01 Ta Li - operator
|
||||||
@@ -259,7 +256,6 @@ integer follows.
|
|||||||
.It Li $81 Ta Ar LONG
|
.It Li $81 Ta Ar LONG
|
||||||
symbol ID follows.
|
symbol ID follows.
|
||||||
.El
|
.El
|
||||||
.Pp
|
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr rgbasm 1 ,
|
.Xr rgbasm 1 ,
|
||||||
.Xr rgblink 1 ,
|
.Xr rgblink 1 ,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
.Nd Rednex Game Boy Development System
|
.Nd Rednex Game Boy Development System
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
To get a working ROM image from a single assembly source file:
|
To get a working ROM image from a single assembly source file:
|
||||||
.Pp
|
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
$ rgbasm \-o bar.o foo.asm
|
$ rgbasm \-o bar.o foo.asm
|
||||||
$ rgblink \-o baz.gb bar.o
|
$ rgblink \-o baz.gb bar.o
|
||||||
@@ -26,7 +25,7 @@ $ rgbfix \-v \-p 0 baz.gb
|
|||||||
.Xr rgbds 5 ,
|
.Xr rgbds 5 ,
|
||||||
.Xr gbz80 7
|
.Xr gbz80 7
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
.Bl -ohang
|
.Bl -item
|
||||||
.It
|
.It
|
||||||
1997, Carsten S\(/orensen (AKA SurfSmurf) writes ASMotor as a general-purpose
|
1997, Carsten S\(/orensen (AKA SurfSmurf) writes ASMotor as a general-purpose
|
||||||
assembler/linker system for DOS/Win32.
|
assembler/linker system for DOS/Win32.
|
||||||
@@ -37,8 +36,8 @@ assembly/machine code, and releases this version as RGBDS.
|
|||||||
2009, Vegard Nossum adapts the code to be more UNIX-like and releases this
|
2009, Vegard Nossum adapts the code to be more UNIX-like and releases this
|
||||||
version as rgbds-linux on GitHub.
|
version as rgbds-linux on GitHub.
|
||||||
.It
|
.It
|
||||||
2010, Anthony J. Bentley forks that repository. The fork becomes the reference
|
2010, Anthony J. Bentley forks that repository.
|
||||||
implementation of rgbds.
|
The fork becomes the reference implementation of rgbds.
|
||||||
.It
|
.It
|
||||||
2017, Bentley's repository is moved to a neutral name.
|
2017, Bentley's repository is moved to a neutral name.
|
||||||
It is now maintained by a number of contributors at
|
It is now maintained by a number of contributors at
|
||||||
|
|||||||
1
test/asm/align-pc-outside-section.asm
Normal file
1
test/asm/align-pc-outside-section.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
align 1
|
||||||
2
test/asm/align-pc-outside-section.err
Normal file
2
test/asm/align-pc-outside-section.err
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
FATAL: align-pc-outside-section.asm(1):
|
||||||
|
Code generation before SECTION directive
|
||||||
0
test/asm/align-pc-outside-section.out
Normal file
0
test/asm/align-pc-outside-section.out
Normal file
2
test/asm/block-comment-contents-error.asm
Normal file
2
test/asm/block-comment-contents-error.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/* block comments containing /* throw warnings */
|
||||||
|
PRINTT "reachable\n"
|
||||||
2
test/asm/block-comment-contents-error.err
Normal file
2
test/asm/block-comment-contents-error.err
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
warning: block-comment-contents-error.asm(1): [-Wnested-comment]
|
||||||
|
/* in block comment
|
||||||
1
test/asm/block-comment-contents-error.out
Normal file
1
test/asm/block-comment-contents-error.out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
reachable
|
||||||
1
test/asm/block-comment-termination-error.asm
Normal file
1
test/asm/block-comment-termination-error.asm
Normal file
@@ -0,0 +1 @@
|
|||||||
|
PRINTT /* block comments must terminate before EOF
|
||||||
5
test/asm/block-comment-termination-error.err
Normal file
5
test/asm/block-comment-termination-error.err
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ERROR: block-comment-termination-error.asm(1):
|
||||||
|
Unterminated block comment
|
||||||
|
ERROR: block-comment-termination-error.asm(1):
|
||||||
|
syntax error
|
||||||
|
error: Assembly aborted (2 errors)!
|
||||||
0
test/asm/block-comment-termination-error.out
Normal file
0
test/asm/block-comment-termination-error.out
Normal file
5
test/asm/block-comment.asm
Normal file
5
test/asm/block-comment.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
PRINTT /* block comments are ignored // ** */ "hi\n"
|
||||||
|
PRINTT "block (/* ... */) comments at ends of line are fine\n" /* hi */
|
||||||
|
PRINTT /* block comments
|
||||||
|
can span multiple lines
|
||||||
|
*/ "mutliline\n"
|
||||||
0
test/asm/block-comment.err
Normal file
0
test/asm/block-comment.err
Normal file
3
test/asm/block-comment.out
Normal file
3
test/asm/block-comment.out
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
hi
|
||||||
|
block (/* ... */) comments at ends of line are fine
|
||||||
|
mutliline
|
||||||
23
test/asm/charmap-inheritance.asm
Normal file
23
test/asm/charmap-inheritance.asm
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
SECTION "test", ROM0
|
||||||
|
|
||||||
|
newcharmap foo
|
||||||
|
|
||||||
|
charmap "<START>", $00
|
||||||
|
charmap "<RAM>", $01
|
||||||
|
charmap "<WAIT>", $02
|
||||||
|
charmap "<ASM>", $03
|
||||||
|
charmap "<NUM>", $04
|
||||||
|
charmap "<EXIT>", $05
|
||||||
|
charmap "<SOUND>", $06
|
||||||
|
charmap "<DAY>", $07
|
||||||
|
charmap "<FAR>", $08
|
||||||
|
|
||||||
|
; At this point, enough nodes were allocated for 'foo' to be reallocated.
|
||||||
|
; Its value in the charmaps' hashmap should have been updated too,
|
||||||
|
; so that usages of 'foo' will not segfault.
|
||||||
|
|
||||||
|
; This uses 'foo; by switching to it.
|
||||||
|
setcharmap foo
|
||||||
|
|
||||||
|
; This uses 'foo' by deriving another charmap from it.
|
||||||
|
newcharmap bar, foo
|
||||||
0
test/asm/charmap-inheritance.err
Normal file
0
test/asm/charmap-inheritance.err
Normal file
0
test/asm/charmap-inheritance.out
Normal file
0
test/asm/charmap-inheritance.out
Normal file
5
test/asm/empty-local.asm
Normal file
5
test/asm/empty-local.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
SECTION "Test", ROM0
|
||||||
|
|
||||||
|
Label:
|
||||||
|
Label.:
|
||||||
0
test/asm/empty-local.err
Normal file
0
test/asm/empty-local.err
Normal file
0
test/asm/empty-local.out
Normal file
0
test/asm/empty-local.out
Normal file
3
test/asm/equs-macrodef.asm
Normal file
3
test/asm/equs-macrodef.asm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
DEFINE equs "mac: MACRO\nPRINTT \"Hello :D\\n\"\nENDM"
|
||||||
|
DEFINE
|
||||||
|
mac
|
||||||
0
test/asm/equs-macrodef.err
Normal file
0
test/asm/equs-macrodef.err
Normal file
1
test/asm/equs-macrodef.out
Normal file
1
test/asm/equs-macrodef.out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello :D
|
||||||
5
test/asm/invalid-utf-8.asm
Normal file
5
test/asm/invalid-utf-8.asm
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
; This test tries to pass invalid UTF-8 through a macro argument
|
||||||
|
; to exercise the lexer's reportGarbageChar
|
||||||
|
m:MACRO \1
|
||||||
|
ENDM
|
||||||
|
m <EFBFBD><EFBFBD>
|
||||||
5
test/asm/invalid-utf-8.err
Normal file
5
test/asm/invalid-utf-8.err
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ERROR: invalid-utf-8.asm(4) -> invalid-utf-8.asm::m(3):
|
||||||
|
Unknown character 0xCF
|
||||||
|
ERROR: invalid-utf-8.asm(4) -> invalid-utf-8.asm::m(3):
|
||||||
|
Unknown character 0xD3
|
||||||
|
error: Assembly aborted (2 errors)!
|
||||||
0
test/asm/invalid-utf-8.out
Normal file
0
test/asm/invalid-utf-8.out
Normal file
@@ -27,3 +27,10 @@ X EQUS "{X7E}"
|
|||||||
X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X
|
X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X
|
||||||
|
|
||||||
x: db 0
|
x: db 0
|
||||||
|
|
||||||
|
; this tests long RPN expressions being used as the RHS, as this once triggered
|
||||||
|
; a realloc bug
|
||||||
|
db 1+(x+X)
|
||||||
|
|
||||||
|
; likewise, a long symbol could result in an insufficient *initial* allocation
|
||||||
|
db A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+0+0
|
||||||
|
|||||||
2
test/asm/narg-overwrite.asm
Normal file
2
test/asm/narg-overwrite.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
_NARG = 0
|
||||||
|
_NARG = 0
|
||||||
5
test/asm/narg-overwrite.err
Normal file
5
test/asm/narg-overwrite.err
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ERROR: narg-overwrite.asm(1):
|
||||||
|
'_NARG' already defined as constant at <builtin>
|
||||||
|
ERROR: narg-overwrite.asm(2):
|
||||||
|
'_NARG' already defined as constant at <builtin>
|
||||||
|
error: Assembly aborted (2 errors)!
|
||||||
0
test/asm/narg-overwrite.out
Normal file
0
test/asm/narg-overwrite.out
Normal file
27
test/asm/nested-macrodef.asm
Normal file
27
test/asm/nested-macrodef.asm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
outer_ok: MACRO
|
||||||
|
definition equs "inner_ok: MACRO\nPRINTT \"Hello!\\n\"\nENDM"
|
||||||
|
definition
|
||||||
|
PURGE definition
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
outer_ok
|
||||||
|
inner_ok
|
||||||
|
|
||||||
|
|
||||||
|
outer_arg: MACRO
|
||||||
|
definition equs "inner_arg: MACRO\nPRINTT \"outer: \1\\ninner: \\1\\n\"\nENDM"
|
||||||
|
definition
|
||||||
|
PURGE definition
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
outer_arg outside
|
||||||
|
inner_arg inside
|
||||||
|
|
||||||
|
|
||||||
|
outer: MACRO
|
||||||
|
WARN "Nested macros shouldn't work, whose argument would be \\1?"
|
||||||
|
inner: MACRO
|
||||||
|
ENDM
|
||||||
|
|
||||||
|
outer
|
||||||
|
inner
|
||||||
5
test/asm/nested-macrodef.err
Normal file
5
test/asm/nested-macrodef.err
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
warning: nested-macrodef.asm(26) -> nested-macrodef.asm::outer(22): [-Wuser]
|
||||||
|
Nested macros shouldn't work, whose argument would be \1?
|
||||||
|
ERROR: nested-macrodef.asm(26) -> nested-macrodef.asm::outer(25):
|
||||||
|
Unterminated macro definition
|
||||||
|
error: Assembly aborted (1 errors)!
|
||||||
3
test/asm/nested-macrodef.out
Normal file
3
test/asm/nested-macrodef.out
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Hello!
|
||||||
|
outer: outside
|
||||||
|
inner: inside
|
||||||
4
test/asm/shift-negative.asm
Normal file
4
test/asm/shift-negative.asm
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
m: MACRO
|
||||||
|
shift -3
|
||||||
|
ENDM
|
||||||
|
m
|
||||||
3
test/asm/shift-negative.err
Normal file
3
test/asm/shift-negative.err
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
ERROR: shift-negative.asm(4) -> shift-negative.asm::m(2):
|
||||||
|
Cannot shift arguments by negative amount -3
|
||||||
|
error: Assembly aborted (1 errors)!
|
||||||
0
test/asm/shift-negative.out
Normal file
0
test/asm/shift-negative.out
Normal file
2
test/asm/shift-outside-macro.asm
Normal file
2
test/asm/shift-outside-macro.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
shift
|
||||||
|
shift 3
|
||||||
5
test/asm/shift-outside-macro.err
Normal file
5
test/asm/shift-outside-macro.err
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ERROR: shift-outside-macro.asm(1):
|
||||||
|
Cannot shift macro arguments outside of a macro
|
||||||
|
ERROR: shift-outside-macro.asm(2):
|
||||||
|
Cannot shift macro arguments outside of a macro
|
||||||
|
error: Assembly aborted (2 errors)!
|
||||||
0
test/asm/shift-outside-macro.out
Normal file
0
test/asm/shift-outside-macro.out
Normal file
3
test/asm/use-label-outside-section.asm
Normal file
3
test/asm/use-label-outside-section.asm
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
lab:
|
||||||
|
PRINTV lab-lab
|
||||||
|
PRINTT "\n"
|
||||||
5
test/asm/use-label-outside-section.err
Normal file
5
test/asm/use-label-outside-section.err
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
ERROR: use-label-outside-section.asm(1):
|
||||||
|
Label "lab" created outside of a SECTION
|
||||||
|
ERROR: use-label-outside-section.asm(2):
|
||||||
|
Expected constant expression: 'lab' is not constant at assembly time
|
||||||
|
error: Assembly aborted (2 errors)!
|
||||||
1
test/asm/use-label-outside-section.out
Normal file
1
test/asm/use-label-outside-section.out
Normal file
@@ -0,0 +1 @@
|
|||||||
|
$0
|
||||||
@@ -1 +1 @@
|
|||||||
RGBDS version 0.4.1
|
RGBDS version 0.4.2
|
||||||
|
|||||||
2
test/asm/weird-comments.asm
Normal file
2
test/asm/weird-comments.asm
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
PRINTT /* // PRINTT "this is **comm //ented out\n" */ "this is not commented out\n"
|
||||||
|
PRINTT /*//*/ "this is not commented out\n"
|
||||||
2
test/asm/weird-comments.err
Normal file
2
test/asm/weird-comments.err
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
warning: weird-comments.asm(2): [-Wnested-comment]
|
||||||
|
/* in block comment
|
||||||
2
test/asm/weird-comments.out
Normal file
2
test/asm/weird-comments.out
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
this is not commented out
|
||||||
|
this is not commented out
|
||||||
Reference in New Issue
Block a user