mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Compare commits
3 Commits
v0.9.0-rc1
...
v0.6.0-wel
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bffe7eb4de | ||
|
|
cd454d2e9a | ||
|
|
c814a616d6 |
88
.checkpatch.conf
Normal file
88
.checkpatch.conf
Normal file
@@ -0,0 +1,88 @@
|
||||
# Configuration for checkpatch.pl
|
||||
# ===============================
|
||||
|
||||
# Enable more tests
|
||||
--strict
|
||||
|
||||
# Quiet
|
||||
--quiet
|
||||
|
||||
# No per-file summary
|
||||
--no-summary
|
||||
|
||||
# Don't expect the Linux kernel tree
|
||||
--no-tree
|
||||
|
||||
# Show file line, not input line
|
||||
--showfile
|
||||
|
||||
# Don't expect SPDX tag in the first line of a file
|
||||
--ignore SPDX_LICENSE_TAG
|
||||
|
||||
# Don't expect Signed-off-by lines in commit messages
|
||||
--no-signoff
|
||||
|
||||
# List of ignored rules
|
||||
# ---------------------
|
||||
|
||||
# There's no BIT macro
|
||||
--ignore BIT_MACRO
|
||||
|
||||
# Don't complain when bools are used in structs
|
||||
--ignore BOOL_MEMBER
|
||||
|
||||
# Allow CamelCase
|
||||
--ignore CAMELCASE
|
||||
|
||||
# Comparing to NULL explicitly isn't a bad thing
|
||||
--ignore COMPARISON_TO_NULL
|
||||
|
||||
# Causes false positives
|
||||
--ignore COMPLEX_MACRO
|
||||
|
||||
# Don't complain about structs not being const
|
||||
--ignore CONST_STRUCT
|
||||
|
||||
# Don't complain about printing "warning:" without the function name, as warning
|
||||
# printing is relevant to the code being parsed, not RGBDS' code
|
||||
--ignore EMBEDDED_FUNCTION_NAME
|
||||
|
||||
# Do not check the format of commit messages
|
||||
--ignore GIT_COMMIT_ID
|
||||
|
||||
# Do not check for global initializers (this is specific to the kernel)
|
||||
--ignore GLOBAL_INITIALISERS
|
||||
|
||||
# Don't complain about initializing statics (this is specific to the kernel)
|
||||
--ignore INITIALISED_STATIC
|
||||
|
||||
# We don't have a MAINTAINERS file, don't complain about it.
|
||||
--ignore FILE_PATH_CHANGES
|
||||
|
||||
# Writing the continuation on the start of the line can make it clearer
|
||||
--ignore LOGICAL_CONTINUATIONS
|
||||
|
||||
# Don't complain if a line that contains a string is too long. It's better to
|
||||
# have a really long line that can be found with grep.
|
||||
--ignore LONG_LINE_STRING
|
||||
|
||||
# Don't complain when files are modified in 'include/asm'
|
||||
--ignore MODIFIED_INCLUDE_ASM
|
||||
|
||||
# Allow new typedefs
|
||||
--ignore NEW_TYPEDEFS
|
||||
|
||||
# We allow lines ending with parentheses for the usage prints
|
||||
--ignore OPEN_ENDED_LINE
|
||||
|
||||
# Prefer stdint.h types over kernel types
|
||||
--ignore PREFER_KERNEL_TYPES
|
||||
|
||||
# Don't ask to replace sscanf by kstrto
|
||||
--ignore SSCANF_TO_KSTRTO
|
||||
|
||||
# Parentheses can make the code clearer
|
||||
--ignore UNNECESSARY_PARENTHESES
|
||||
|
||||
# We don't have `fallthrough;` */
|
||||
--ignore PREFER_FALLTHROUGH
|
||||
@@ -1,13 +1,13 @@
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignArrayOfStructures: Left
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: Consecutive
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignConsecutiveMacros: Consecutive
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments: true
|
||||
AlignTrailingComments: false
|
||||
AllowShortBlocksOnASingleLine: Empty
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
@@ -21,8 +21,8 @@ AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- format_
|
||||
- attr_
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BitFieldColonSpacing: Both
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Attach
|
||||
@@ -60,8 +60,8 @@ IndentPPDirectives: BeforeHash
|
||||
IndentRequires: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
# Only support for Javascript as of clang-format 14...
|
||||
# InsertTrailingCommas: Wrapped
|
||||
# Only support for Javascript as of clang-format 13...
|
||||
# InsertTrailingCommas: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
LambdaBodyIndentation: Signature
|
||||
Language: Cpp
|
||||
@@ -69,7 +69,6 @@ MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PPIndentWidth: -1
|
||||
PointerAlignment: Right
|
||||
QualifierAlignment: Right
|
||||
ReflowComments: true
|
||||
SortIncludes: CaseSensitive
|
||||
SortUsingDeclarations: true
|
||||
@@ -97,4 +96,4 @@ SpacesInSquareBrackets: false
|
||||
Standard: c++20
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: ForIndentation
|
||||
UseTab: AlignWithSpaces
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
# This file is part of RGBDS.
|
||||
#
|
||||
# Copyright (c) 2018-2019, Phil Smith and RGBDS contributors.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
.git
|
||||
docs
|
||||
|
||||
16
.gitattributes
vendored
16
.gitattributes
vendored
@@ -1,18 +1,2 @@
|
||||
# Shell scripts need Unix line endings (see https://github.com/gbdev/rgbds/issues/841)
|
||||
*.sh text eol=lf
|
||||
*.bash text eol=lf
|
||||
|
||||
# Flags also need Unix line endings (see https://github.com/gbdev/rgbds/issues/955)
|
||||
*.flags text eol=lf
|
||||
|
||||
# Binary files need exact bytes
|
||||
*.bin binary
|
||||
*.gb binary
|
||||
*.1bpp binary
|
||||
*.2bpp binary
|
||||
*.pal binary
|
||||
*.attrmap binary
|
||||
*.tilemap binary
|
||||
*.palmap binary
|
||||
*.patch binary
|
||||
*.png binary
|
||||
|
||||
3
.github/FUNDING.yml
vendored
3
.github/FUNDING.yml
vendored
@@ -1,2 +1,3 @@
|
||||
github: avivace
|
||||
patreon: gbdev01
|
||||
open_collective: gbdev
|
||||
github: gbdev
|
||||
|
||||
56
.github/actions/doc_postproc.awk
vendored
Executable file
56
.github/actions/doc_postproc.awk
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/awk -f
|
||||
|
||||
/^\s+<td><b class="Sy">.+<\/b><\/td>$/ {
|
||||
# Assuming that all cells whose contents are bold are heading cells,
|
||||
# use the HTML tag for those
|
||||
sub(/td><b class="Sy"/, "th");
|
||||
sub(/b><\/td/, "th");
|
||||
}
|
||||
|
||||
# The whole page is being generated, so it's not meant to contain any Liquid
|
||||
BEGIN {
|
||||
print "{% raw %}"
|
||||
}
|
||||
END {
|
||||
print "{% endraw %}"
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
in_synopsis = 0
|
||||
}
|
||||
/<table class="Nm">/ {
|
||||
in_synopsis = 1
|
||||
}
|
||||
/<\/table>/ {
|
||||
# Resets synopsis state even when already reset, but whatever
|
||||
in_synopsis = 0
|
||||
}
|
||||
/<code class="Fl">-[a-zA-Z]/ {
|
||||
# Add links to arg descr in synopsis section
|
||||
if (in_synopsis) {
|
||||
while (match($0, /<code class="Fl">-[a-zA-Z]+/)) {
|
||||
# 123456789012345678 -> 18 chars
|
||||
optchars = substr($0, RSTART + 18, RLENGTH - 18)
|
||||
i = length(optchars)
|
||||
while (i) {
|
||||
end = RSTART + 18 + i
|
||||
i -= 1
|
||||
len = i ? 1 : 2
|
||||
$0 = sprintf("%s<a href=\"#%s\">%s</a>%s",
|
||||
substr($0, 0, end - len - 1),
|
||||
substr($0, end - 1, 1),
|
||||
substr($0, end - len, len),
|
||||
substr($0, end))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
# Make long opts (defined using `Fl Fl`) into a single tag
|
||||
gsub(/<code class="Fl">-<\/code>\s*<code class="Fl">/, "<code class=\"Fl\">-")
|
||||
}
|
||||
|
||||
{
|
||||
print
|
||||
}
|
||||
113
.github/actions/get-pages.sh
vendored
Executable file
113
.github/actions/get-pages.sh
vendored
Executable file
@@ -0,0 +1,113 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [-h] [-r] <rgbds-www> <version>
|
||||
Copy renders from RGBDS repository to rgbds-www documentation
|
||||
Execute from the root folder of the RGBDS repo, checked out at the desired tag
|
||||
<rgbds-www> : Path to the rgbds-www repository
|
||||
<version> : Version to be copied, such as 'v0.4.1' or 'master'
|
||||
|
||||
-h Display this help message
|
||||
-r Update "latest stable" redirection pages and add a new entry to the index
|
||||
(use for releases, not master)
|
||||
EOF
|
||||
}
|
||||
|
||||
is_release=0
|
||||
bad_usage=0
|
||||
while getopts ":hr" opt; do
|
||||
case $opt in
|
||||
r)
|
||||
is_release=1
|
||||
;;
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
\?)
|
||||
echo "Unknown option '$OPTARG'"
|
||||
bad_usage=1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ $bad_usage -ne 0 ]; then
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift $(($OPTIND - 1))
|
||||
|
||||
|
||||
declare -A PAGES
|
||||
PAGES=(
|
||||
[rgbasm.1.html]=src/asm/rgbasm.1
|
||||
[rgbasm.5.html]=src/asm/rgbasm.5
|
||||
[rgblink.1.html]=src/link/rgblink.1
|
||||
[rgblink.5.html]=src/link/rgblink.5
|
||||
[rgbfix.1.html]=src/fix/rgbfix.1
|
||||
[rgbgfx.1.html]=src/gfx/rgbgfx.1
|
||||
[rgbds.5.html]=src/rgbds.5
|
||||
[rgbds.7.html]=src/rgbds.7
|
||||
[gbz80.7.html]=src/gbz80.7
|
||||
)
|
||||
WWWPATH="/docs"
|
||||
mkdir -p "$1/_documentation/$2"
|
||||
|
||||
# `mandoc` uses a different format for referring to man pages present in the **current** directory.
|
||||
# We want that format for RGBDS man pages, and the other one for the rest;
|
||||
# we thus need to copy all pages to a temporary directory, and process them there.
|
||||
|
||||
# Copy all pages to current dir
|
||||
cp "${PAGES[@]}" .
|
||||
|
||||
for page in "${!PAGES[@]}"; do
|
||||
stem="${page%.html}"
|
||||
manpage="${stem%.?}(${stem#*.})"
|
||||
descr="$(awk -v 'FS=.Nd ' '/.Nd/ { print $2; }' "${PAGES[$page]}")"
|
||||
|
||||
cat >"$1/_documentation/$2/$page" <<EOF
|
||||
---
|
||||
layout: doc
|
||||
title: $manpage [$2]
|
||||
description: RGBDS $2 — $descr
|
||||
---
|
||||
EOF
|
||||
options=fragment,man='%N.%S;https://linux.die.net/man/%S/%N'
|
||||
if [ $stem = rgbasm.5 ]; then
|
||||
options+=,toc
|
||||
fi
|
||||
mandoc -Thtml -I os=Linux -O$options "${PAGES[$page]##*/}" | .github/actions/doc_postproc.awk >> "$1/_documentation/$2/$page"
|
||||
groff -Tpdf -mdoc -wall "${PAGES[$page]##*/}" >"$1/_documentation/$2/$stem.pdf"
|
||||
if [ $is_release -ne 0 ]; then
|
||||
cat - >"$1/_documentation/$page" <<EOF
|
||||
---
|
||||
redirect_to: $WWWPATH/$2/${page%.html}
|
||||
permalink: $WWWPATH/${page%.html}/
|
||||
title: $manpage [latest stable]
|
||||
description: RGBDS latest stable — $descr
|
||||
---
|
||||
EOF
|
||||
fi
|
||||
done
|
||||
|
||||
cat - >"$1/_documentation/$2/index.html" <<EOF
|
||||
---
|
||||
layout: doc_index
|
||||
permalink: /docs/$2/
|
||||
title: RGBDS online manual [$2]
|
||||
description: RGBDS $2 - Online manual
|
||||
---
|
||||
EOF
|
||||
|
||||
|
||||
# If making a release, add a new entry right after `master`
|
||||
if [ $is_release -ne 0 ]; then
|
||||
awk '{ print }
|
||||
/"name": "master"/ { print "\t\t{\"name\": \"'$2'\", \"text\": \"'$2'\" }," }
|
||||
' "$1/_data/doc.json" >"$1/_data/doc.json.tmp"
|
||||
mv "$1/_data/doc.json"{.tmp,}
|
||||
fi
|
||||
|
||||
|
||||
# Clean up
|
||||
rm "${PAGES[@]##*/}"
|
||||
21
.github/actions/install_deps.sh
vendored
Executable file
21
.github/actions/install_deps.sh
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
case "${1%-*}" in
|
||||
ubuntu)
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get install -yq bison libpng-dev pkg-config
|
||||
;;
|
||||
macos)
|
||||
brew install bison libpng pkg-config md5sha1sum
|
||||
# For the version check below exclusively, re-do this before building
|
||||
export PATH="/usr/local/opt/bison/bin:$PATH"
|
||||
;;
|
||||
*)
|
||||
echo "WARNING: Cannot install deps for OS '$1'"
|
||||
;;
|
||||
esac
|
||||
|
||||
bison --version
|
||||
make --version
|
||||
cmake --version
|
||||
17
.github/actions/mingw-configure.sh
vendored
Normal file
17
.github/actions/mingw-configure.sh
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
source mingw-env @TRIPLE@
|
||||
echo LAST IS: $last
|
||||
|
||||
# check if last arg is a path to configure, else use parent
|
||||
for last; do true; done
|
||||
if test -x "${last}/configure"; then
|
||||
config_path="$last"
|
||||
else
|
||||
config_path=".."
|
||||
fi
|
||||
|
||||
${config_path}/configure \
|
||||
--host=@TRIPLE@ --target=@TRIPLE@ --build="$CHOST" \
|
||||
--prefix=/usr/@TRIPLE@ --libdir=/usr/@TRIPLE@/lib --includedir=/usr/@TRIPLE@/include \
|
||||
--enable-shared --enable-static "$@"
|
||||
16
.github/actions/mingw-env.sh
vendored
Normal file
16
.github/actions/mingw-env.sh
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
_arch=$1
|
||||
|
||||
default_mingw_pp_flags="-D_FORTIFY_SOURCE=2"
|
||||
default_mingw_compiler_flags="$default_mingw_pp_flags -O2 -pipe -fno-plt -fexceptions --param=ssp-buffer-size=4"
|
||||
default_mingw_linker_flags="-Wl,-O1,--sort-common,--as-needed -fstack-protector"
|
||||
|
||||
export CPPFLAGS="${MINGW_CPPFLAGS:-$default_mingw_pp_flags $CPPFLAGS}"
|
||||
export CFLAGS="${MINGW_CFLAGS:-$default_mingw_compiler_flags $CFLAGS}"
|
||||
export CXXFLAGS="${MINGW_CXXFLAGS:-$default_mingw_compiler_flags $CXXFLAGS}"
|
||||
export LDFLAGS="${MINGW_LDFLAGS:-$default_mingw_linker_flags $LDFLAGS}"
|
||||
|
||||
mingw_prefix=/usr/${_arch}
|
||||
export PKG_CONFIG_SYSROOT_DIR="${mingw_prefix}"
|
||||
export PKG_CONFIG_LIBDIR="${mingw_prefix}/lib/pkgconfig:${mingw_prefix}/share/pkgconfig"
|
||||
44
.github/actions/mingw-w64-libpng-dev.sh
vendored
Executable file
44
.github/actions/mingw-w64-libpng-dev.sh
vendored
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/sh
|
||||
|
||||
# This script was written by ISSOtm while looking at Arch Linux's PKGBUILD for
|
||||
# the corresponding package. (And its dependencies)
|
||||
# https://aur.archlinux.org/packages/mingw-w64-libpng/
|
||||
|
||||
set -e
|
||||
|
||||
pngver=1.6.37
|
||||
_apngver=$pngver
|
||||
_arch="$1"
|
||||
|
||||
|
||||
## Install mingw-configure and mingw-env (both build dependencies)
|
||||
|
||||
install -m 755 .github/actions/mingw-env.sh /usr/bin/mingw-env
|
||||
|
||||
sed "s|@TRIPLE@|${_arch}|g" .github/actions/mingw-configure.sh > ${_arch}-configure
|
||||
install -m 755 ${_arch}-configure /usr/bin/
|
||||
|
||||
|
||||
## Grab sources and check them
|
||||
|
||||
wget http://downloads.sourceforge.net/sourceforge/libpng/libpng-$pngver.tar.xz
|
||||
wget http://downloads.sourceforge.net/project/apng/libpng/libpng16/libpng-$_apngver-apng.patch.gz
|
||||
sha256sum -c .github/actions/mingw-w64-libpng-dev.sha256sums
|
||||
|
||||
## Extract sources
|
||||
|
||||
tar -xf libpng-$pngver.tar.xz
|
||||
gunzip libpng-$_apngver-apng.patch.gz
|
||||
|
||||
|
||||
## Start building!
|
||||
|
||||
cd libpng-$pngver
|
||||
# Patch in apng support
|
||||
patch -p0 ../libpng-$_apngver-apng.patch
|
||||
|
||||
mkdir -p build-${_arch}
|
||||
cd build-${_arch}
|
||||
${_arch}-configure LDFLAGS=-static-libgcc
|
||||
make
|
||||
make install
|
||||
2
.github/actions/mingw-w64-libpng-dev.sha256sums
vendored
Normal file
2
.github/actions/mingw-w64-libpng-dev.sha256sums
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
10d9e0cb60e2b387a79b355eb7527c0bee2ed8cbd12cf04417cabc4d6976683c libpng-1.6.37-apng.patch.gz
|
||||
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-1.6.37.tar.xz
|
||||
27
.github/scripts/build_libpng.sh
vendored
27
.github/scripts/build_libpng.sh
vendored
@@ -1,27 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
pngver=1.6.43
|
||||
|
||||
## Grab sources and check them
|
||||
|
||||
curl -LOJ "http://prdownloads.sourceforge.net/libpng/libpng-$pngver.tar.xz?download"
|
||||
# Brew doesn't provide any sha256sum, so we're making do with `sha2` instead.
|
||||
if [ "$(sha2 -q -256 libpng-$pngver.tar.xz)" != 6a5ca0652392a2d7c9db2ae5b40210843c0bbc081cbd410825ab00cc59f14a6c ]; then
|
||||
sha2 -256 libpng-$pngver.tar.xz
|
||||
echo Checksum mismatch! Aborting. >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
## Extract sources and patch them
|
||||
|
||||
tar -xvf libpng-$pngver.tar.xz
|
||||
|
||||
## Start building!
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
../libpng-$pngver/configure --disable-shared --enable-static \
|
||||
CFLAGS="-O3 -flto -DNDEBUG -mmacosx-version-min=10.9 -arch x86_64 -arch arm64 -fno-exceptions"
|
||||
make -kj
|
||||
make install prefix="$PWD/../libpng-staging"
|
||||
23
.github/scripts/get_win_deps.ps1
vendored
23
.github/scripts/get_win_deps.ps1
vendored
@@ -1,23 +0,0 @@
|
||||
function getlibrary ([string] $URI, [string] $filename, [string] $hash, [string] $destdir) {
|
||||
$wc = New-Object Net.WebClient
|
||||
[string] $downloadhash = $null
|
||||
try {
|
||||
$wc.DownloadFile($URI, $filename)
|
||||
$downloadhash = $(Get-FileHash $filename -Algorithm SHA256).Hash
|
||||
} catch {
|
||||
Write-Host "${filename}: failed to download"
|
||||
exit 1
|
||||
}
|
||||
if ($hash -ne $downloadhash) {
|
||||
Write-Host "${filename}: SHA256 mismatch ($downloadhash)"
|
||||
exit 1
|
||||
}
|
||||
Expand-Archive -DestinationPath $destdir $filename
|
||||
}
|
||||
|
||||
getlibrary 'https://www.zlib.net/zlib131.zip' 'zlib.zip' '72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17' .
|
||||
getlibrary 'https://github.com/glennrp/libpng/archive/refs/tags/v1.6.43.zip' 'libpng.zip' '5e18474a26814ae479e02ca6432da32d19dc6e615551d140c954a68d63b3f192' .
|
||||
getlibrary 'https://github.com/lexxmark/winflexbison/releases/download/v2.5.25/win_flex_bison-2.5.25.zip' 'winflexbison.zip' '8d324b62be33604b2c45ad1dd34ab93d722534448f55a16ca7292de32b6ac135' install_dir
|
||||
|
||||
Move-Item zlib-1.3.1 zlib
|
||||
Move-Item libpng-1.6.43 libpng
|
||||
7
.github/scripts/install.sh
vendored
7
.github/scripts/install.sh
vendored
@@ -1,7 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
install -d /usr/local/bin/ /usr/local/share/man/man1/ /usr/local/share/man/man5/ /usr/local/share/man/man7/
|
||||
install -s -m 755 rgbasm rgblink rgbfix rgbgfx /usr/local/bin/
|
||||
install -m 644 rgbasm.1 rgblink.1 rgbfix.1 rgbgfx.1 /usr/local/share/man/man1/
|
||||
install -m 644 rgbds.5 rgbasm.5 rgblink.5 /usr/local/share/man/man5/
|
||||
install -m 644 rgbds.7 gbz80.7 /usr/local/share/man/man7/
|
||||
23
.github/scripts/install_deps.sh
vendored
23
.github/scripts/install_deps.sh
vendored
@@ -1,23 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
case "${1%-*}" in
|
||||
ubuntu)
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get install -yq bison libpng-dev pkg-config
|
||||
;;
|
||||
macos)
|
||||
brew install bison sha2 md5sha1sum
|
||||
# Export `bison` to allow using the version we install from Homebrew,
|
||||
# instead of the outdated one preinstalled on macOS (which doesn't even support `-Wall`...)
|
||||
export PATH="/opt/homebrew/opt/bison/bin:$PATH"
|
||||
printf 'PATH=%s\n' "$PATH" >>"$GITHUB_ENV" # Make it available to later CI steps too
|
||||
;;
|
||||
*)
|
||||
echo "WARNING: Cannot install deps for OS '$1'"
|
||||
;;
|
||||
esac
|
||||
|
||||
bison --version
|
||||
make --version
|
||||
cmake --version
|
||||
33
.github/scripts/mingw-w64-libpng-dev.sh
vendored
33
.github/scripts/mingw-w64-libpng-dev.sh
vendored
@@ -1,33 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
pngver=1.6.43
|
||||
arch="$1"
|
||||
|
||||
## Grab sources and check them
|
||||
|
||||
wget http://downloads.sourceforge.net/project/libpng/libpng16/$pngver/libpng-$pngver.tar.xz
|
||||
wget http://downloads.sourceforge.net/project/apng/libpng/libpng16/libpng-$pngver-apng.patch.gz
|
||||
sha256sum -c .github/scripts/mingw-w64-libpng-dev.sha256sums
|
||||
|
||||
## Extract sources and patch them
|
||||
|
||||
tar -xf libpng-$pngver.tar.xz
|
||||
gunzip libpng-$pngver-apng.patch.gz
|
||||
|
||||
# Patch in apng support
|
||||
env -C libpng-$pngver patch -p0 ../libpng-$pngver-apng.patch
|
||||
|
||||
## Start building!
|
||||
|
||||
mkdir -p build
|
||||
cd build
|
||||
../libpng-$pngver/configure \
|
||||
--host="$arch" --target="$arch" \
|
||||
--prefix="/usr/$arch" \
|
||||
--enable-shared --disable-static \
|
||||
CPPFLAGS="-D_FORTIFY_SOURCE=2" \
|
||||
CFLAGS="-O2 -pipe -fno-plt -fno-exceptions --param=ssp-buffer-size=4" \
|
||||
LDFLAGS="-Wl,-O1,--sort-common,--as-needed -fstack-protector"
|
||||
make -kj
|
||||
sudo make install
|
||||
@@ -1,2 +0,0 @@
|
||||
d6bd2a3f43f17020918a4c1bd81c1a78111b6f759af9c1d3c754f704a1bf0429 libpng-1.6.43-apng.patch.gz
|
||||
6a5ca0652392a2d7c9db2ae5b40210843c0bbc081cbd410825ab00cc59f14a6c libpng-1.6.43.tar.xz
|
||||
25
.github/workflows/checkpatch.yml
vendored
Normal file
25
.github/workflows/checkpatch.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: "Code style checking"
|
||||
on: pull_request
|
||||
|
||||
jobs:
|
||||
checkpatch:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up repo
|
||||
run: |
|
||||
git clone -b "${{ github.event.pull_request.head.ref }}" "${{ github.event.pull_request.head.repo.clone_url }}" rgbds
|
||||
cd rgbds
|
||||
git remote add upstream "${{ github.event.pull_request.base.repo.clone_url }}"
|
||||
git fetch upstream
|
||||
- name: Set up checkpatch
|
||||
working-directory: rgbds
|
||||
run: |
|
||||
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/checkpatch.pl'
|
||||
chmod +x checkpatch.pl
|
||||
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/const_structs.checkpatch'
|
||||
wget 'https://raw.githubusercontent.com/torvalds/linux/master/scripts/spelling.txt'
|
||||
- name: Checkpatch
|
||||
working-directory: rgbds
|
||||
run: |
|
||||
make checkpatch CHECKPATCH=./checkpatch.pl "BASE_REF=${{ github.event.pull_request.base.sha }}" Q= | tee log
|
||||
if grep -q ERROR: log; then exit 1; else exit 0; fi
|
||||
96
.github/workflows/create-release-artifacts.yaml
vendored
Normal file
96
.github/workflows/create-release-artifacts.yaml
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
name: "Create release artifacts"
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]*
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Get version from tag
|
||||
shell: bash
|
||||
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
|
||||
VERSION="${{ github.ref }}"
|
||||
echo "version=${VERSION##*/v}" >> $GITHUB_ENV
|
||||
- name: Get zlib, libpng and bison
|
||||
run: | # TODO: use an array
|
||||
$wc = New-Object System.Net.WebClient
|
||||
$wc.DownloadFile('https://www.zlib.net/zlib1212.zip', 'zlib.zip')
|
||||
$hash = (Get-FileHash "zlib.zip" -Algorithm SHA256).Hash
|
||||
if ($hash -ne '173e89893dcb8b4a150d7731cd72f0602f1d6b45e60e2a54efdf7f3fc3325fd7') {
|
||||
Write-Host "zlib SHA256 mismatch! ($hash)"
|
||||
exit 1
|
||||
}
|
||||
$wc.DownloadFile('https://download.sourceforge.net/libpng/lpng1637.zip', 'libpng.zip')
|
||||
$hash = (Get-FileHash "libpng.zip" -Algorithm SHA256).Hash
|
||||
if ($hash -ne '3b4b1cbd0bae6822f749d39b1ccadd6297f05e2b85a83dd2ce6ecd7d09eabdf2') {
|
||||
Write-Host "libpng SHA256 mismatch! ($hash)"
|
||||
exit 1
|
||||
}
|
||||
$wc.DownloadFile('https://github.com/lexxmark/winflexbison/releases/download/v2.5.24/win_flex_bison-2.5.24.zip', 'winflexbison.zip')
|
||||
$hash = (Get-FileHash "winflexbison.zip" -Algorithm SHA256).Hash
|
||||
if ($hash -ne '39c6086ce211d5415500acc5ed2d8939861ca1696aee48909c7f6daf5122b505') {
|
||||
Write-Host "bison SHA256 mismatch! ($hash)"
|
||||
}
|
||||
Expand-Archive -DestinationPath . "zlib.zip"
|
||||
Expand-Archive -DestinationPath . "libpng.zip"
|
||||
Expand-Archive -DestinationPath install_dir "winflexbison.zip"
|
||||
Move-Item zlib-1.2.12 zlib
|
||||
Move-Item lpng1637 libpng
|
||||
- name: Build 32-bit zlib
|
||||
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
|
||||
cmake -S zlib -B zbuild32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
||||
cmake --build zbuild32 --config Release
|
||||
cmake --install zbuild32
|
||||
- name: Build 32-bit libpng
|
||||
run: |
|
||||
cmake -S libpng -B pngbuild32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
|
||||
cmake --build pngbuild32 --config Release
|
||||
cmake --install pngbuild32
|
||||
- name: Build 32-bit Windows binaries
|
||||
run: |
|
||||
cmake -S . -B build32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build32 --config Release
|
||||
cmake --install build32
|
||||
- name: Package 32-bit binaries
|
||||
run: |
|
||||
Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/zlib1.dll", "install_dir/bin/libpng16.dll") "rgbds-${{ env.version }}-win32.zip"
|
||||
- name: Build 64-bit zlib
|
||||
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
|
||||
cmake -S zlib -B zbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
||||
cmake --build zbuild64 --config Release
|
||||
cmake --install zbuild64
|
||||
- name: Build 64-bit libpng
|
||||
run: |
|
||||
cmake -S libpng -B pngbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
|
||||
cmake --build pngbuild64 --config Release
|
||||
cmake --install pngbuild64
|
||||
- name: Build 64-bit Windows binaries
|
||||
run: |
|
||||
cmake -S . -B build64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build64 --config Release
|
||||
cmake --install build64
|
||||
- name: Package 64-bit binaries
|
||||
run: |
|
||||
Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/zlib1.dll", "install_dir/bin/libpng16.dll") "rgbds-${{ env.version }}-win64.zip"
|
||||
- name: Package sources
|
||||
run: |
|
||||
make dist
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body: |
|
||||
Please ensure that the three assets below work properly.
|
||||
Once that's done, replace this text with the changelog, un-draft the release, and update the `release` branch.
|
||||
By the way, if you forgot to update `include/version.h`, RGBASM's version test is gonna fail in the tag's regression testing! (Use `git push --delete origin <tag>` to delete it)
|
||||
draft: true # Don't publish the release quite yet...
|
||||
prerelease: ${{ contains(github.ref, '-rc') }}
|
||||
files: |
|
||||
rgbds-${{ env.version }}-win32.zip
|
||||
rgbds-${{ env.version }}-win64.zip
|
||||
rgbds-${{ env.version }}.tar.gz
|
||||
fail_on_unmatched_files: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
159
.github/workflows/create-release-artifacts.yml
vendored
159
.github/workflows/create-release-artifacts.yml
vendored
@@ -1,159 +0,0 @@
|
||||
name: "Create release artifacts"
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v[0-9]*
|
||||
|
||||
jobs:
|
||||
windows:
|
||||
runs-on: windows-2022
|
||||
strategy:
|
||||
matrix:
|
||||
bits: [32, 64]
|
||||
include:
|
||||
- bits: 32
|
||||
arch: x86
|
||||
platform: Win32
|
||||
- bits: 64
|
||||
arch: x86_x64
|
||||
platform: x64
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Get version from tag
|
||||
shell: bash
|
||||
run: | # Turn "vX.Y.Z" into "X.Y.Z"
|
||||
VERSION="${{ github.ref_name }}"
|
||||
echo "version=${VERSION#v}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install deps
|
||||
run: .github/scripts/get_win_deps.ps1
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
zbuild
|
||||
pngbuild
|
||||
key: ${{ matrix.arch }}-${{ hashFiles('zlib/**', 'libpng/**') }}
|
||||
- name: Build zlib
|
||||
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
|
||||
cmake -S zlib -B zbuild -A ${{ matrix.platform }} -Wno-dev -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
||||
cmake --build zbuild --config Release -j
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install zlib
|
||||
run: |
|
||||
cmake --install zbuild
|
||||
- name: Build libpng
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -S libpng -B pngbuild -A ${{ matrix.platform }} -Wno-dev -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=OFF -DPNG_TESTS=OFF
|
||||
cmake --build pngbuild --config Release -j
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install libpng
|
||||
run: |
|
||||
cmake --install pngbuild
|
||||
- name: Build Windows binaries
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -S . -B build -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build --config Release -j --verbose
|
||||
cmake --install build --verbose --prefix install_dir --strip
|
||||
- name: Package binaries
|
||||
run: |
|
||||
Compress-Archive -LiteralPath @("install_dir/bin/rgbasm.exe", "install_dir/bin/rgblink.exe", "install_dir/bin/rgbfix.exe", "install_dir/bin/rgbgfx.exe", "install_dir/bin/zlib1.dll", "install_dir/bin/libpng16.dll") "rgbds-${{ env.version }}-win${{ matrix.bits }}.zip"
|
||||
- name: Upload Windows binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: win${{ matrix.bits }}
|
||||
path: rgbds-${{ env.version }}-win${{ matrix.bits }}.zip
|
||||
|
||||
macos:
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- name: Get version from tag
|
||||
shell: bash
|
||||
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
|
||||
VERSION="${{ github.ref_name }}"
|
||||
echo "version=${VERSION#v}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/install_deps.sh macos
|
||||
- name: Build libpng
|
||||
run: |
|
||||
./.github/scripts/build_libpng.sh
|
||||
# We force linking libpng statically; the other libs are provided by macOS itself
|
||||
- name: Build binaries
|
||||
run: |
|
||||
make -kj CXXFLAGS="-O3 -flto -DNDEBUG -mmacosx-version-min=10.9 -arch x86_64 -arch arm64" PNGCFLAGS="-I libpng-staging/include" PNGLDLIBS="libpng-staging/lib/libpng.a -lz" Q=
|
||||
strip rgb{asm,link,fix,gfx}
|
||||
- name: Package binaries
|
||||
run: |
|
||||
zip --junk-paths rgbds-${{ env.version }}-macos.zip rgb{asm,link,fix,gfx} man/* .github/scripts/install.sh
|
||||
- name: Upload macOS binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: macos
|
||||
path: rgbds-${{ env.version }}-macos.zip
|
||||
|
||||
linux:
|
||||
runs-on: ubuntu-20.04 # Oldest supported, for best glibc compatibility.
|
||||
steps:
|
||||
- name: Get version from tag
|
||||
shell: bash
|
||||
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
|
||||
VERSION="${{ github.ref_name }}"
|
||||
echo "version=${VERSION#v}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/install_deps.sh ubuntu-20.04
|
||||
- name: Build binaries
|
||||
run: |
|
||||
make -kj WARNFLAGS="-Wall -Wextra -pedantic -static" PKG_CONFIG="pkg-config --static" Q=
|
||||
strip rgb{asm,link,fix,gfx}
|
||||
- name: Package binaries
|
||||
run: |
|
||||
tar caf rgbds-${{ env.version }}-linux-x86_64.tar.xz --transform='s#.*/##' rgb{asm,link,fix,gfx} man/* .github/scripts/install.sh
|
||||
- name: Upload Linux binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: linux
|
||||
path: rgbds-${{ env.version }}-linux-x86_64.tar.xz
|
||||
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [windows, macos, linux]
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Get version from tag
|
||||
shell: bash
|
||||
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
|
||||
VERSION="${{ github.ref_name }}"
|
||||
echo "version=${VERSION#v}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v4
|
||||
- name: Package sources
|
||||
run: |
|
||||
make dist Q=
|
||||
ls
|
||||
- uses: actions/download-artifact@v4
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
body: |
|
||||
Please ensure that the four packages below work properly.
|
||||
Once that's done, replace this text with the changelog, un-draft the release, and update the `release` branch.
|
||||
By the way, if you forgot to update `include/version.hpp`, RGBASM's version test is gonna fail in the tag's regression testing! (Use `git push --delete origin <tag>` to delete it)
|
||||
draft: true # Don't publish the release quite yet...
|
||||
prerelease: ${{ contains(github.ref, '-rc') }}
|
||||
files: |
|
||||
win32/rgbds-${{ env.version }}-win32.zip
|
||||
win64/rgbds-${{ env.version }}-win64.zip
|
||||
macos/rgbds-${{ env.version }}-macos.zip
|
||||
linux/rgbds-${{ env.version }}-linux-x86_64.tar.xz
|
||||
rgbds-${{ env.version }}.tar.gz
|
||||
fail_on_unmatched_files: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
22
.github/workflows/create-release-docs.yml
vendored
22
.github/workflows/create-release-docs.yml
vendored
@@ -7,26 +7,32 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner == 'gbdev'
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Checkout rgbds@release
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: rgbds
|
||||
- name: Checkout rgbds-www@master
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ github.repository_owner }}/rgbds-www
|
||||
path: rgbds-www
|
||||
- name: Install groff and mandoc
|
||||
# `-O toc` was added in 1.14.5, but the repos only have 1.14.4
|
||||
- name: Build and install mandoc + install groff
|
||||
run: |
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get install -yq groff mandoc
|
||||
sudo apt-get install -yq groff zlib1g-dev
|
||||
wget 'http://mandoc.bsd.lv/snapshots/mandoc-1.14.5.tar.gz'
|
||||
tar xf mandoc-1.14.5.tar.gz
|
||||
cd mandoc-1.14.5
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
- name: Update pages
|
||||
working-directory: rgbds/man
|
||||
working-directory: rgbds
|
||||
run: | # The ref appears to be in the format "refs/tags/<version>", so strip that
|
||||
../../rgbds-www/maintainer/man_to_html.sh ${GITHUB_REF##*/} *
|
||||
../../rgbds-www/maintainer/new_release.sh ${GITHUB_REF##*/}
|
||||
./.github/actions/get-pages.sh -r ../rgbds-www ${GITHUB_REF##*/}
|
||||
- name: Push new pages
|
||||
working-directory: rgbds-www
|
||||
run: |
|
||||
|
||||
286
.github/workflows/testing.yml
vendored
286
.github/workflows/testing.yml
vendored
@@ -4,130 +4,61 @@ on:
|
||||
- pull_request
|
||||
|
||||
jobs:
|
||||
unix:
|
||||
unix-testing:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-22.04, macos-14]
|
||||
cxx: [g++, clang++]
|
||||
os: [ubuntu-20.04, ubuntu-18.04, macos-11.0, macos-10.15]
|
||||
cc: [gcc, clang]
|
||||
buildsys: [make, cmake]
|
||||
exclude:
|
||||
# Don't use `g++` on macOS; it's just an alias to `clang++`.
|
||||
- os: macos-14
|
||||
cxx: g++
|
||||
# `gcc` is just an alias to `clang` on macOS, don't bother
|
||||
- os: macos-10.15
|
||||
cc: gcc
|
||||
- os: macos-11.0
|
||||
cc: gcc
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/install_deps.sh ${{ matrix.os }}
|
||||
./.github/actions/install_deps.sh ${{ matrix.os }}
|
||||
# The `export` lines are to allow working on macOS...
|
||||
# Apple's base version is severely outdated, not even supporting -Wall,
|
||||
# but it overrides Homebrew's version nonetheless...
|
||||
- name: Build & install using Make
|
||||
if: matrix.buildsys == 'make'
|
||||
run: |
|
||||
make develop -kj Q= CXX=${{ matrix.cxx }}
|
||||
export PATH="/usr/local/opt/bison/bin:$PATH"
|
||||
make develop -j Q= CC=${{ matrix.cc }}
|
||||
sudo make install -j Q=
|
||||
if: matrix.buildsys == 'make'
|
||||
- name: Build & install using CMake
|
||||
if: matrix.buildsys == 'cmake'
|
||||
run: |
|
||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_COMPILER=${{ matrix.cxx }} -DSANITIZERS=ON -DMORE_WARNINGS=ON
|
||||
cmake --build build -j --verbose
|
||||
export PATH="/usr/local/opt/bison/bin:$PATH"
|
||||
cmake -S . -B build -DCMAKE_VERBOSE_MAKEFILE=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=${{ matrix.cc }} -DSANITIZERS=ON -DMORE_WARNINGS=ON
|
||||
cmake --build build -j
|
||||
cp build/src/rgb{asm,link,fix,gfx} .
|
||||
sudo cmake --install build --verbose
|
||||
cmake --install build --verbose --component "Test support programs"
|
||||
sudo cmake --install build
|
||||
if: matrix.buildsys == 'cmake'
|
||||
- name: Package binaries
|
||||
run: |
|
||||
mkdir bins
|
||||
cp rgb{asm,link,fix,gfx} bins
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: rgbds-canary-${{ matrix.os }}-${{ matrix.cxx }}-${{ matrix.buildsys }}
|
||||
name: rgbds-canary-${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.buildsys }}
|
||||
path: bins
|
||||
- name: Compute test dependency cache params
|
||||
id: test-deps-cache-params
|
||||
shell: bash
|
||||
run: |
|
||||
paths=$(test/fetch-test-deps.sh --get-paths)
|
||||
hash=$(test/fetch-test-deps.sh --get-hash)
|
||||
tee -a <<<"paths=\"${paths//,/\\n}\"" $GITHUB_OUTPUT
|
||||
tee -a <<<"hash=${hash%-}" $GITHUB_OUTPUT
|
||||
- name: Check test dependency repositories cache
|
||||
id: test-deps-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ fromJSON(steps.test-deps-cache-params.outputs.paths) }}
|
||||
key: ${{ matrix.os }}-${{ steps.test-deps-cache-params.outputs.hash }}
|
||||
- if: steps.test-deps-cache.outputs.cache-hit != 'true'
|
||||
name: Fetch test dependency repositories
|
||||
continue-on-error: true
|
||||
run: |
|
||||
test/fetch-test-deps.sh
|
||||
- name: Install test dependency dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
test/fetch-test-deps.sh --get-deps ${{ matrix.os }}
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
CXX=${{ matrix.cxx }} test/run-tests.sh
|
||||
|
||||
macos-static:
|
||||
runs-on: macos-14
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/install_deps.sh macos
|
||||
- name: Build libpng
|
||||
run: |
|
||||
./.github/scripts/build_libpng.sh
|
||||
- name: Build & install
|
||||
run: |
|
||||
make -kj CXXFLAGS="-O3 -flto -DNDEBUG -mmacosx-version-min=10.9 -arch x86_64 -arch arm64" PNGCFLAGS="-I libpng-staging/include" PNGLDLIBS="libpng-staging/lib/libpng.a -lz" Q=
|
||||
- name: Package binaries
|
||||
run: |
|
||||
mkdir bins
|
||||
cp rgb{asm,link,fix,gfx} bins
|
||||
- name: Upload binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: rgbds-canary-macos-static
|
||||
path: bins
|
||||
- name: Compute test dependency cache params
|
||||
id: test-deps-cache-params
|
||||
shell: bash
|
||||
run: |
|
||||
paths=$(test/fetch-test-deps.sh --get-paths)
|
||||
hash=$(test/fetch-test-deps.sh --get-hash)
|
||||
tee -a <<<"paths=\"${paths//,/\\n}\"" $GITHUB_OUTPUT
|
||||
tee -a <<<"hash=${hash%-}" $GITHUB_OUTPUT
|
||||
- name: Check test dependency repositories cache
|
||||
id: test-deps-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ fromJSON(steps.test-deps-cache-params.outputs.paths) }}
|
||||
key: ${{ matrix.os }}-${{ steps.test-deps-cache-params.outputs.hash }}
|
||||
- if: steps.test-deps-cache.outputs.cache-hit != 'true'
|
||||
name: Fetch test dependency repositories
|
||||
continue-on-error: true
|
||||
run: |
|
||||
test/fetch-test-deps.sh
|
||||
- name: Install test dependency dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
test/fetch-test-deps.sh --get-deps macos
|
||||
- name: Run tests
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
test/run-tests.sh
|
||||
|
||||
windows:
|
||||
windows-testing:
|
||||
strategy:
|
||||
matrix:
|
||||
bits: [32, 64]
|
||||
os: [windows-2019, windows-2022]
|
||||
include:
|
||||
- bits: 32
|
||||
arch: x86
|
||||
@@ -136,87 +67,70 @@ jobs:
|
||||
arch: x86_x64
|
||||
platform: x64
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install deps
|
||||
run: .github/scripts/get_win_deps.ps1
|
||||
- uses: actions/cache@v4
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
zbuild
|
||||
pngbuild
|
||||
key: ${{ matrix.arch }}-${{ hashFiles('zlib/**', 'libpng/**') }}
|
||||
- uses: actions/checkout@v2
|
||||
- name: Get zlib, libpng and bison
|
||||
run: | # TODO: use an array
|
||||
$wc = New-Object System.Net.WebClient
|
||||
$wc.DownloadFile('https://www.zlib.net/zlib1212.zip', 'zlib.zip')
|
||||
$hash = (Get-FileHash "zlib.zip" -Algorithm SHA256).Hash
|
||||
if ($hash -ne '173e89893dcb8b4a150d7731cd72f0602f1d6b45e60e2a54efdf7f3fc3325fd7') {
|
||||
Write-Host "zlib SHA256 mismatch! ($hash)"
|
||||
exit 1
|
||||
}
|
||||
$wc.DownloadFile('https://download.sourceforge.net/libpng/lpng1637.zip', 'libpng.zip')
|
||||
$hash = (Get-FileHash "libpng.zip" -Algorithm SHA256).Hash
|
||||
if ($hash -ne '3b4b1cbd0bae6822f749d39b1ccadd6297f05e2b85a83dd2ce6ecd7d09eabdf2') {
|
||||
Write-Host "libpng SHA256 mismatch! ($hash)"
|
||||
exit 1
|
||||
}
|
||||
$wc.DownloadFile('https://github.com/lexxmark/winflexbison/releases/download/v2.5.24/win_flex_bison-2.5.24.zip', 'winflexbison.zip')
|
||||
$hash = (Get-FileHash "winflexbison.zip" -Algorithm SHA256).Hash
|
||||
if ($hash -ne '39c6086ce211d5415500acc5ed2d8939861ca1696aee48909c7f6daf5122b505') {
|
||||
Write-Host "bison SHA256 mismatch! ($hash)"
|
||||
}
|
||||
Expand-Archive -DestinationPath . "zlib.zip"
|
||||
Expand-Archive -DestinationPath . "libpng.zip"
|
||||
Expand-Archive -DestinationPath install_dir "winflexbison.zip"
|
||||
Move-Item zlib-1.2.12 zlib
|
||||
Move-Item lpng1637 libpng
|
||||
- name: Build zlib
|
||||
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
|
||||
cmake -S zlib -B zbuild -A ${{ matrix.platform }} -Wno-dev -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
||||
cmake -S zlib -B zbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
||||
cmake --build zbuild --config Release -j
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install zlib
|
||||
run: |
|
||||
cmake --install zbuild
|
||||
- name: Build libpng
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -S libpng -B pngbuild -A ${{ matrix.platform }} -Wno-dev -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=OFF -DPNG_TESTS=OFF
|
||||
cmake -S libpng -B pngbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
|
||||
cmake --build pngbuild --config Release -j
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
- name: Install libpng
|
||||
run: |
|
||||
cmake --install pngbuild
|
||||
- name: Build Windows binaries
|
||||
shell: bash
|
||||
run: |
|
||||
cmake -S . -B build -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build --config Release -j --verbose
|
||||
cmake --install build --verbose --prefix install_dir
|
||||
cmake --install build --verbose --component "Test support programs"
|
||||
cmake --build build --config Release -j
|
||||
cmake --install build
|
||||
- name: Package binaries
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir bins
|
||||
cp install_dir/bin/{rgbasm.exe,rgblink.exe,rgbfix.exe,rgbgfx.exe,zlib1.dll,libpng16.dll} bins
|
||||
- name: Upload Windows binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: rgbds-canary-w${{ matrix.bits }}-${{ matrix.os }}
|
||||
name: rgbds-canary-win${{ matrix.bits }}
|
||||
path: bins
|
||||
- name: Compute test dependency cache params
|
||||
id: test-deps-cache-params
|
||||
shell: bash
|
||||
run: |
|
||||
paths=$(test/fetch-test-deps.sh --get-paths)
|
||||
hash=$(test/fetch-test-deps.sh --get-hash)
|
||||
tee -a <<<"paths=\"${paths//,/\\n}\"" $GITHUB_OUTPUT
|
||||
tee -a <<<"hash=${hash%-}" $GITHUB_OUTPUT
|
||||
- name: Check test dependency repositories cache
|
||||
id: test-deps-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ fromJSON(steps.test-deps-cache-params.outputs.paths) }}
|
||||
key: ${{ matrix.os }}-${{ matrix.bits }}-${{ steps.test-deps-cache-params.outputs.hash }}
|
||||
- if: steps.test-deps-cache.outputs.cache-hit != 'true'
|
||||
name: Fetch test dependency repositories
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
run: |
|
||||
test/fetch-test-deps.sh
|
||||
- name: Install test dependency dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
test/fetch-test-deps.sh --get-deps ${{ matrix.os }}
|
||||
- name: Run tests
|
||||
- name: Test
|
||||
shell: bash
|
||||
run: |
|
||||
cp bins/* .
|
||||
cp bins/*.dll test/gfx
|
||||
test/run-tests.sh
|
||||
|
||||
windows-mingw-build:
|
||||
windows-xbuild:
|
||||
strategy:
|
||||
matrix:
|
||||
bits: [32, 64]
|
||||
os: [ubuntu-18.04]
|
||||
include:
|
||||
- bits: 32
|
||||
arch: i686
|
||||
@@ -225,94 +139,58 @@ jobs:
|
||||
arch: x86-64
|
||||
triplet: x86_64-w64-mingw32
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
DIST_DIR: win${{ matrix.bits }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Install deps
|
||||
shell: bash
|
||||
run: |
|
||||
./.github/scripts/install_deps.sh ubuntu
|
||||
./.github/actions/install_deps.sh ${{ matrix.os }}
|
||||
- name: Install MinGW
|
||||
run: | # dpkg-dev is apparently required for pkg-config for cross-building
|
||||
sudo apt-get install g++-mingw-w64-${{ matrix.arch }}-win32 mingw-w64-tools libz-mingw-w64-dev dpkg-dev
|
||||
run: |
|
||||
sudo apt-get install gcc-mingw-w64-${{ matrix.arch }} mingw-w64-tools libz-mingw-w64-dev
|
||||
- name: Install libpng dev headers for MinGW
|
||||
run: |
|
||||
./.github/scripts/mingw-w64-libpng-dev.sh ${{ matrix.triplet }}
|
||||
sudo ./.github/actions/mingw-w64-libpng-dev.sh ${{ matrix.triplet }}
|
||||
- name: Cross-build Windows binaries
|
||||
run: |
|
||||
make mingw${{ matrix.bits }} -kj Q=
|
||||
make mingw${{ matrix.bits }} -j Q=
|
||||
- name: Package binaries
|
||||
run: | # DLL dependencies can be figured out using e.g. Dependency Walker or objdump -p
|
||||
run: |
|
||||
mkdir bins
|
||||
mv -v rgb{asm,link,fix,gfx}.exe bins/
|
||||
cp -v /usr/${{ matrix.triplet }}/lib/zlib1.dll bins
|
||||
cp -v /usr/${{ matrix.triplet }}/bin/libpng16-16.dll bins
|
||||
cp -v /usr/lib/gcc/${{ matrix.triplet }}/10-win32/lib{ssp-0,stdc++-6}.dll bins
|
||||
[ "${{ matrix.bits }}" -ne 32 ] || cp -v /usr/lib/gcc/${{ matrix.triplet }}/10-win32/libgcc_s_dw2-1.dll bins
|
||||
mv rgbasm bins/rgbasm.exe
|
||||
mv rgblink bins/rgblink.exe
|
||||
mv rgbfix bins/rgbfix.exe
|
||||
mv rgbgfx bins/rgbgfx.exe
|
||||
cp /usr/${{ matrix.triplet }}/lib/zlib1.dll bins
|
||||
cp /usr/${{ matrix.triplet }}/bin/libpng16-16.dll bins
|
||||
if [ ${{ matrix.bits }} -eq 32 ]; then cp /usr/lib/gcc/${{ matrix.triplet }}/7.3-win32/libgcc_s_sjlj-1.dll bins; fi
|
||||
- name: Upload Windows binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v1
|
||||
with:
|
||||
name: rgbds-canary-mingw-win${{ matrix.bits }}
|
||||
path: bins
|
||||
- name: Upload Windows test binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: testing-programs-mingw-win${{ matrix.bits }}
|
||||
path: |
|
||||
test/gfx/randtilegen.exe
|
||||
test/gfx/rgbgfx_test.exe
|
||||
|
||||
windows-mingw-testing:
|
||||
needs: windows-mingw-build
|
||||
windows-xtesting:
|
||||
needs: windows-xbuild
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-2019, windows-2022]
|
||||
bits: [32, 64]
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: windows-2019
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v2
|
||||
- name: Retrieve binaries
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v1
|
||||
with:
|
||||
name: rgbds-canary-mingw-win${{ matrix.bits }}
|
||||
path: bins
|
||||
- name: Retrieve test binaries
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: testing-programs-mingw-win${{ matrix.bits }}
|
||||
path: test/gfx
|
||||
- name: Extract binaries
|
||||
shell: bash
|
||||
run: |
|
||||
cp bins/* .
|
||||
cp bins/*.dll test/gfx
|
||||
- name: Compute test dependency cache params
|
||||
id: test-deps-cache-params
|
||||
shell: bash
|
||||
run: |
|
||||
paths=$(test/fetch-test-deps.sh --get-paths)
|
||||
hash=$(test/fetch-test-deps.sh --get-hash)
|
||||
tee -a <<<"paths=\"${paths//,/\\n}\"" $GITHUB_OUTPUT
|
||||
tee -a <<<"hash=${hash%-}" $GITHUB_OUTPUT
|
||||
- name: Check test dependency repositories cache
|
||||
id: test-deps-cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ fromJSON(steps.test-deps-cache-params.outputs.paths) }}
|
||||
key: mingw-${{ matrix.bits }}-${{ steps.test-deps-cache-params.outputs.hash }}
|
||||
- if: steps.test-deps-cache.outputs.cache-hit != 'true'
|
||||
name: Fetch test dependency repositories
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
run: |
|
||||
test/fetch-test-deps.sh
|
||||
- name: Install test dependency dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
test/fetch-test-deps.sh --get-deps ${{ matrix.os }}
|
||||
- name: Run tests
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
41
.github/workflows/update-master-docs.yml
vendored
41
.github/workflows/update-master-docs.yml
vendored
@@ -4,41 +4,48 @@ on:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- man/gbz80.7
|
||||
- man/rgbds.5
|
||||
- man/rgbds.7
|
||||
- man/rgbasm.1
|
||||
- man/rgbasm.5
|
||||
- man/rgblink.1
|
||||
- man/rgblink.5
|
||||
- man/rgbfix.1
|
||||
- man/rgbgfx.1
|
||||
- .github/actions/get-pages.sh
|
||||
- src/gbz80.7
|
||||
- src/rgbds.5
|
||||
- src/rgbds.7
|
||||
- src/asm/rgbasm.1
|
||||
- src/asm/rgbasm.5
|
||||
- src/link/rgblink.1
|
||||
- src/link/rgblink.5
|
||||
- src/fix/rgbfix.1
|
||||
- src/gfx/rgbgfx.1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository_owner == 'gbdev'
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- name: Checkout rgbds@master
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: gbdev/rgbds
|
||||
ref: master
|
||||
path: rgbds
|
||||
- name: Checkout rgbds-www@master
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: gbdev/rgbds-www
|
||||
ref: master
|
||||
path: rgbds-www
|
||||
- name: Install groff and mandoc
|
||||
- name: Build and install mandoc + install groff
|
||||
run: |
|
||||
sudo apt-get -qq update
|
||||
sudo apt-get install -yq groff mandoc
|
||||
sudo apt-get install -yq groff zlib1g-dev
|
||||
wget 'http://mandoc.bsd.lv/snapshots/mandoc-1.14.5.tar.gz'
|
||||
tar xf mandoc-1.14.5.tar.gz
|
||||
cd mandoc-1.14.5
|
||||
./configure
|
||||
make
|
||||
sudo make install
|
||||
- name: Update pages
|
||||
working-directory: rgbds/man
|
||||
working-directory: rgbds
|
||||
run: |
|
||||
../../rgbds-www/maintainer/man_to_html.sh master *
|
||||
./.github/actions/get-pages.sh ../rgbds-www master
|
||||
- name: Push new pages
|
||||
working-directory: rgbds-www
|
||||
run: |
|
||||
@@ -49,7 +56,7 @@ jobs:
|
||||
ssh-add ~/.ssh/id_ed25519
|
||||
git config --global user.name "GitHub Action"
|
||||
git config --global user.email "community@gbdev.io"
|
||||
git add -A
|
||||
git add .
|
||||
git commit -m "Update RGBDS master documentation"
|
||||
if git remote | grep -q origin; then
|
||||
git remote set-url origin git@github.com:gbdev/rgbds-www.git
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -3,14 +3,10 @@
|
||||
/rgbfix
|
||||
/rgbgfx
|
||||
/rgbshim.sh
|
||||
/coverage/
|
||||
*.o
|
||||
*.exe
|
||||
*.dll
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.gcov
|
||||
.checkpatch-camelcase.*
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake_install.cmake
|
||||
callgrind.out.*
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
#
|
||||
# This file is part of RGBDS.
|
||||
#
|
||||
# Copyright (c) 2020 RGBDS contributors.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
# 3.9 required for LTO checks
|
||||
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||
|
||||
project(rgbds
|
||||
LANGUAGES CXX)
|
||||
LANGUAGES C)
|
||||
|
||||
# get real path of source and binary directories
|
||||
get_filename_component(srcdir "${CMAKE_SOURCE_DIR}" REALPATH)
|
||||
@@ -21,27 +27,13 @@ option(SANITIZERS "Build with sanitizers enabled" OFF) # Ignored on MSVC
|
||||
option(MORE_WARNINGS "Turn on more warnings" OFF) # Ignored on MSVC
|
||||
|
||||
if(MSVC)
|
||||
# MSVC's own standard library triggers warning C5105,
|
||||
# "macro expansion producing 'defined' has undefined behavior".
|
||||
# Warning C5030 is about unknown attributes (`[[gnu::ATTR]]`), none of ours being load-bearing.
|
||||
# Warning C4996 is about using POSIX names, which we want to do for portability.
|
||||
# We also opt into the C++20-conformant preprocessor.
|
||||
add_compile_options(/MP /wd5105 /wd5030 /wd4996 /Zc:preprocessor)
|
||||
# MSVC's standard library triggers warning C5105,
|
||||
# "macro expansion producing 'defined' has undefined behavior"
|
||||
add_compile_options(/std:c11 /W1 /MP /wd5105)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
|
||||
if(SANITIZERS)
|
||||
set(SAN_FLAGS /fsanitize=address)
|
||||
add_compile_options(${SAN_FLAGS})
|
||||
add_link_options(${SAN_FLAGS})
|
||||
endif()
|
||||
else()
|
||||
add_compile_options(-Wall -pedantic)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# C++20 allows macros to take zero variadic arguments, but Clang (aka AppleClang on macOS)
|
||||
# does not recognize this yet.
|
||||
add_compile_options(-Wno-gnu-zero-variadic-macro-arguments)
|
||||
endif()
|
||||
add_definitions(-D_POSIX_C_SOURCE=200809L)
|
||||
add_definitions(-D_POSIX_C_SOURCE=200809L -D_ISOC11_SOURCE)
|
||||
if(SANITIZERS)
|
||||
set(SAN_FLAGS -fsanitize=shift -fsanitize=integer-divide-by-zero
|
||||
-fsanitize=unreachable -fsanitize=vla-bound
|
||||
@@ -49,22 +41,22 @@ else()
|
||||
-fsanitize=object-size -fsanitize=bool -fsanitize=enum
|
||||
-fsanitize=alignment -fsanitize=null -fsanitize=address)
|
||||
add_compile_options(${SAN_FLAGS})
|
||||
add_link_options(${SAN_FLAGS})
|
||||
add_definitions(-D_GLIBCXX_ASSERTIONS)
|
||||
link_libraries(${SAN_FLAGS})
|
||||
# A non-zero optimization level is desired in debug mode, but allow overriding it nonetheless
|
||||
# TODO: this overrides anything previously set... that's a bit sloppy!
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-g -Og -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE STRING "" FORCE)
|
||||
set(CMAKE_C_FLAGS_DEBUG "-g -Og -fno-omit-frame-pointer -fno-optimize-sibling-calls" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
if(MORE_WARNINGS)
|
||||
add_compile_options(-Werror -Wextra
|
||||
-Walloc-zero -Wcast-align -Wcast-qual -Wduplicated-branches -Wduplicated-cond
|
||||
-Wfloat-equal -Wlogical-op -Wnull-dereference -Wshift-overflow=2
|
||||
-Wstringop-overflow=4 -Wundef -Wuninitialized -Wunused
|
||||
-Wshadow # TODO: -Wshadow=compatible-local?
|
||||
-Wfloat-equal -Winline -Wlogical-op -Wnested-externs -Wnull-dereference
|
||||
-Wold-style-definition -Wshift-overflow=2 -Wstrict-overflow=5
|
||||
-Wstrict-prototypes -Wstringop-overflow=4 -Wundef -Wuninitialized -Wunused
|
||||
-Wshadow # TODO: -Wshadow=compatible-local ?
|
||||
-Wformat=2 -Wformat-overflow=2 -Wformat-truncation=1
|
||||
-Wno-format-nonliteral -Wno-strict-overflow
|
||||
-Wno-unused-but-set-variable # bison's `yynerrs_` is incremented but unused
|
||||
-Wno-format-nonliteral # We have a couple of "dynamic" prints
|
||||
# We do some range checks that are always false on some platforms (GCC, Clang)
|
||||
-Wno-type-limits -Wno-tautological-constant-out-of-range-compare
|
||||
-Wvla # MSVC does not support VLAs
|
||||
-Wno-unknown-warning-option) # Clang shouldn't diagnose unknown warnings
|
||||
@@ -76,7 +68,7 @@ endif()
|
||||
|
||||
find_program(GIT git)
|
||||
if(GIT)
|
||||
execute_process(COMMAND ${GIT} --git-dir=.git describe --tags --dirty --always
|
||||
execute_process(COMMAND ${GIT} describe --tags --dirty --always
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_REV OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET)
|
||||
@@ -85,21 +77,12 @@ else(GIT)
|
||||
message(STATUS "Cannot determine RGBDS version (Git not installed), falling back")
|
||||
endif(GIT)
|
||||
|
||||
find_package(PkgConfig)
|
||||
if(MSVC OR NOT PKG_CONFIG_FOUND)
|
||||
# fallback to find_package
|
||||
find_package(PNG REQUIRED)
|
||||
else()
|
||||
pkg_check_modules(LIBPNG REQUIRED libpng)
|
||||
endif()
|
||||
|
||||
include_directories("${PROJECT_SOURCE_DIR}/include")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED True)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
||||
|
||||
# By default, build in Release mode; Debug mode must be explicitly requested
|
||||
# (You may want to augment it with the options above)
|
||||
@@ -114,19 +97,3 @@ if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
message(CHECK_FAIL "no")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(MANDIR "share/man")
|
||||
set(man1 "man/rgbasm.1"
|
||||
"man/rgbfix.1"
|
||||
"man/rgbgfx.1"
|
||||
"man/rgblink.1")
|
||||
set(man5 "man/rgbasm.5"
|
||||
"man/rgblink.5"
|
||||
"man/rgbds.5")
|
||||
set(man7 "man/gbz80.7"
|
||||
"man/rgbds.7")
|
||||
|
||||
foreach(SECTION "man1" "man5" "man7")
|
||||
set(DEST "${MANDIR}/${SECTION}")
|
||||
install(FILES ${${SECTION}} DESTINATION ${DEST})
|
||||
endforeach()
|
||||
|
||||
176
CONTRIBUTING.md
176
CONTRIBUTING.md
@@ -1,176 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
RGBDS was created in the late '90s and has received contributions from several
|
||||
developers since then. It wouldn't have been possible to get to this point
|
||||
without their work, and it is always open to the contributions of other people.
|
||||
|
||||
## Reporting Bugs
|
||||
|
||||
Bug reports are essential to improve RGBDS and they are always welcome. If you
|
||||
want to report a bug:
|
||||
|
||||
1. Make sure that there isn't a similar issue
|
||||
[already reported](https://github.com/gbdev/rgbds/issues).
|
||||
2. Figure out a way of reproducing it reliably.
|
||||
3. If there is a piece of code that triggers the bug, try to reduce it to the
|
||||
smallest file you can.
|
||||
4. Create a new [issue](https://github.com/gbdev/rgbds/issues).
|
||||
|
||||
Of course, it may not always be possible to give an accurate bug report, but it
|
||||
always helps to fix it.
|
||||
|
||||
## Requesting new features
|
||||
|
||||
If you come up with a good idea that could be implemented, you can propose it to
|
||||
be done.
|
||||
|
||||
1. Create a new [issue](https://github.com/gbdev/rgbds/issues).
|
||||
2. Try to be as accurate as possible. Describe what you need and why you need
|
||||
it, maybe with examples.
|
||||
|
||||
Please understand that the contributors are doing it in their free time, so
|
||||
simple requests are more likely to catch the interest of a contributor than
|
||||
complicated ones. If you really need something to be done, and you think you can
|
||||
implement it yourself, you can always contribute to RGBDS with your own code.
|
||||
|
||||
## Contributing code
|
||||
|
||||
If you want to contribute with your own code, whether it is to fix a current
|
||||
issue or to add something that nobody had requested, you should first consider
|
||||
if your change is going to be small (and likely to be accepted as-is) or big
|
||||
(and will have to go through some rework).
|
||||
|
||||
Big changes will most likely require some discussion, so open an
|
||||
[issue](https://github.com/gbdev/rgbds/issues) and explain what you want to
|
||||
do and how you intend to do it. If you already have a prototype, it's always a
|
||||
good idea to show it. Tests help, too.
|
||||
|
||||
If you are going to work on a specific issue that involves a lot of work, it is
|
||||
always a good idea to leave a message, just in case someone else is interested
|
||||
but doesn't know that there's someone working on it.
|
||||
|
||||
Note that you must contribute all your changes under the MIT License. If you are
|
||||
just modifying a file, you don't need to do anything (maybe update the copyright
|
||||
years). If you are adding new files, you need to use the `SPDX-License-Identifier: MIT`
|
||||
header.
|
||||
|
||||
1. Fork this repository.
|
||||
2. Checkout the `master` branch.
|
||||
3. Create a new branch to work on. You could still work on `master`, but it's
|
||||
easier that way.
|
||||
4. Compile your changes with `make develop` instead of just `make`. This
|
||||
target checks for additional warnings. Your patches shouldn't introduce any
|
||||
new warning (but it may be possible to remove some warning checks if it makes
|
||||
the code much easier).
|
||||
5. Test your changes by running `./run-tests.sh` in the `test` directory.
|
||||
(You must run `./fetch-test-deps.sh` first; if you forget to, the test suite will fail and remind you mid-way.)
|
||||
5. Format your changes according to `clang-format`, which will reformat the
|
||||
coding style according to our standards defined in `.clang-format`.
|
||||
6. Create a pull request against the branch `master`.
|
||||
7. Be prepared to get some comments about your code and to modify it. Tip: Use
|
||||
`git rebase -i origin/master` to modify chains of commits.
|
||||
|
||||
## Adding a test
|
||||
|
||||
The test suite is a little ad-hoc, so the way tests work is different for each program being tested.
|
||||
|
||||
Feel free to modify how the test scripts work, if the thing you want to test doesn't fit the existing scheme(s).
|
||||
|
||||
### RGBASM
|
||||
|
||||
Each `.asm` file corresponds to one test.
|
||||
RGBASM will be invoked on the `.asm` file with all warnings enabled.
|
||||
|
||||
If a `.out` file exists, RGBASM's output (`print`, `println`, etc.) must match its contents.
|
||||
If a `.err` file exists, RGBASM's error output (`warn`, errors, etc.) must match its contents.
|
||||
|
||||
If a `.out.bin` file exists, the object file will be linked, and the generated ROM truncated to the length of the `.out.bin` file.
|
||||
After that, the ROM must match the `.out.bin` file.
|
||||
|
||||
### RGBLINK
|
||||
|
||||
Each `.asm` file corresponds to one test, or one *set* of tests.
|
||||
|
||||
All tests begin by assembling the `.asm` file into an object file, which will be linked in various ways depending on the test.
|
||||
|
||||
#### Simple tests
|
||||
|
||||
These simply check that RGBLINK's output matches some expected output.
|
||||
|
||||
A `.out` file **must** exist, and RGBLINK's output must match that file's contents.
|
||||
|
||||
Additionally, if a `.out.bin` file exists, the `.gb` file generated by RGBLINK must match it.
|
||||
|
||||
#### Linker script tests
|
||||
|
||||
These allow applying various linker scripts to the same object file.
|
||||
If one or more `.link` files exist, whose names start the same as the `.asm` file, then each of those files correspond to one test.
|
||||
|
||||
Each `.link` linker script **must** be accompanied by a `.out` file, and RGBLINK's output must match that file's contents when passed the corresponding linker script.
|
||||
|
||||
#### Variant tests
|
||||
|
||||
These allow testing RGBLINK's `-d`, `-t`, and `-w` flags.
|
||||
If one or more <code>-<var><flag></var>.out</code> or <code>-no-<var><flag></var>.out</code> files exist, then each of them corresponds to one test.
|
||||
|
||||
The object file will be linked with and without said flag, respectively; and in each case, RGBLINK's output must match the `.out` file's contents.
|
||||
|
||||
### RGBFIX
|
||||
|
||||
Each `.flags` file corresponds to one test.
|
||||
Each one is a text file whose first line contains flags to pass to RGBFIX.
|
||||
(There may be more lines, which will be ignored; they can serve as comments to explain what the test is about.)
|
||||
|
||||
RGBFIX will be invoked on the `.bin` file if it exists, or else on default-input.bin.
|
||||
|
||||
If no `.err` file exists, RGBFIX is simply expected to be able to process the file normally.
|
||||
If one *does* exist, RGBFIX's return status is ignored, but its output **must** match the `.err` file's contents.
|
||||
|
||||
Additionally, if a `.gb` file exists, the output of RGBFIX must match the `.gb`.
|
||||
|
||||
### RGBGFX
|
||||
|
||||
There are three kinds of test.
|
||||
|
||||
#### Simple tests
|
||||
|
||||
Each `.png` file corresponds to one test.
|
||||
RGBGFX will be invoked on the file.
|
||||
If a `.flags` file exists, it will be used as part of the RGBGFX invocation (<code>@<var><file></var>.flags</code>).
|
||||
|
||||
If `.out.1bpp`, `.out.2bpp`, `.out.pal`, `.out.tilemap`, `.out.attrmap`, or `.out.palmap` files exist, RGBGFX will create the corresponding kind of output, which must match the file's contents.
|
||||
Multiple kinds of output may be tested for the same input.
|
||||
|
||||
If no `.err` file exists, RGBGFX is simply expected to be able to process the file normally.
|
||||
If one *does* exist, RGBGFX's return status is ignored, but its output **must** match the `.err` file's contents.
|
||||
|
||||
#### Reverse tests
|
||||
|
||||
Each `.1bpp` or `.2bpp` file corresponds to one test.
|
||||
RGBGFX will be invoked on the file with `-r 1` for reverse mode, then invoked on the output without `-r 1`.
|
||||
The round-trip output must match the input file's contents.
|
||||
If a `.flags` file exists, it will be used as part of the RGBGFX invocation (<code>@<var><file></var>.flags</code>).
|
||||
|
||||
#### Random seed tests
|
||||
|
||||
Each `seed*.bin` file corresponds to one test.
|
||||
Each one is a binary RNG file which is passed to the `rgbgfx_test` program.
|
||||
|
||||
### Downstream projects
|
||||
|
||||
1. Make sure the downstream project supports <code>make <var><target></var> RGBDS=<var><path/to/RGBDS/></var></code>.
|
||||
While the test suite supports any Make target name, only [Make](//gnu.org/software/make) is currently supported, and the Makefile must support a `RGBDS` variable to use a non-system RGBDS directory.
|
||||
|
||||
Also, only projects hosted on GitHub are currently supported.
|
||||
2. Add the project to `test/fetch-test-deps.sh`: add a new `action` line at the bottom, following the existing pattern:
|
||||
|
||||
```sh
|
||||
action <owner> <repo> <date of last commit> <hash of last commit>
|
||||
```
|
||||
|
||||
(The date is used to avoid fetching too much history when cloning the repositories.)
|
||||
3. Add the project to `test/run-tests.sh`: add a new `test_downstream` line at the bottom, following the existing pattern:
|
||||
|
||||
```sh
|
||||
test_downstream <owner> <repo> <makefile target> <build file> <sha1 hash of build file>
|
||||
```
|
||||
95
CONTRIBUTING.rst
Normal file
95
CONTRIBUTING.rst
Normal file
@@ -0,0 +1,95 @@
|
||||
Contributing
|
||||
============
|
||||
|
||||
RGBDS was created in the late '90s and has received contributions from several
|
||||
developers since then. It wouldn't have been possible to get to this point
|
||||
without their work, and it is always open to the contributions of other people.
|
||||
|
||||
Reporting Bugs
|
||||
--------------
|
||||
|
||||
Bug reports are essential to improve RGBDS and they are always welcome. If you
|
||||
want to report a bug:
|
||||
|
||||
1. Make sure that there isn't a similar issue already reported
|
||||
`here <https://github.com/rednex/rgbds/issues>`__.
|
||||
|
||||
2. Figure out a way of reproducing it reliably.
|
||||
|
||||
3. If there is a piece of code that triggers the bug, try to reduce it to the
|
||||
smallest file you can.
|
||||
|
||||
4. Create a new `issue <https://github.com/rednex/rgbds/issues>`__.
|
||||
|
||||
Of course, it may not always be possible to give an accurate bug report, but it
|
||||
always helps to fix it.
|
||||
|
||||
Requesting new features
|
||||
-----------------------
|
||||
|
||||
If you come up with a good idea that could be implemented, you can propose it to
|
||||
be done.
|
||||
|
||||
1. Create a new `issue <https://github.com/rednex/rgbds/issues>`__.
|
||||
|
||||
2. Try to be as accurate as possible. Describe what you need and why you need
|
||||
it, maybe with examples.
|
||||
|
||||
Please understand that the contributors are doing it in their free time, so
|
||||
simple requests are more likely to catch the interest of a contributor than
|
||||
complicated ones. If you really need something to be done, and you think you can
|
||||
implement it yourself, you can always contribute to RGBDS with your own code.
|
||||
|
||||
Contributing code
|
||||
-----------------
|
||||
|
||||
If you want to contribute with your own code, whether it is to fix a current
|
||||
issue or to add something that nobody had requested, you should first consider
|
||||
if your change is going to be small (and likely to be accepted as-is) or big
|
||||
(and will have to go through some rework).
|
||||
|
||||
Big changes will most likely require some discussion, so open an
|
||||
`issue <https://github.com/rednex/rgbds/issues>`__ and explain what you want to
|
||||
do and how you intend to do it. If you already have a prototype, it's always a
|
||||
good idea to show it. Tests help, too.
|
||||
|
||||
If you are going to work on a specific issue that involves a lot of work, it is
|
||||
always a good idea to leave a message, just in case someone else is interested
|
||||
but doesn't know that there's someone working on it.
|
||||
|
||||
Note that you must contribute all your changes under the MIT License. If you are
|
||||
just modifying a file, you don't need to do anything (maybe update the copyright
|
||||
years). If you are adding new files, you need to use the correct header with the
|
||||
copyright and the reference to the MIT License.
|
||||
|
||||
1. Fork this repository.
|
||||
|
||||
2. Checkout the ``master`` branch.
|
||||
|
||||
3. Create a new branch to work on. You could still work on ``master``, but it's
|
||||
easier that way.
|
||||
|
||||
4. Compile your changes with ``make develop`` instead of just ``make``. This
|
||||
target checks for additional warnings. Your patches shouldn't introduce any
|
||||
new warning (but it may be possible to remove some warning checks if it makes
|
||||
the code much easier).
|
||||
|
||||
5. Follow the Linux kernel coding style, which can be found in the file
|
||||
``Documentation/process/coding-style.rst`` in the Linux kernel repository.
|
||||
Note that the coding style isn't written in stone, if there is a good reason
|
||||
to deviate from it, it should be fine.
|
||||
|
||||
6. Download the files ``checkpatch.pl``, ``const_structs.checkpatch`` and
|
||||
``spelling.txt`` from the folder ``scripts`` in the Linux kernel repository.
|
||||
|
||||
7. To use ``checkpatch.pl`` you can use ``make checkpatch``, which will check
|
||||
the coding style of all patches between the current one and the upstream
|
||||
code. By default, the Makefile expects the script (and associate files) to be
|
||||
located in ``../linux/scripts/``, but you can place them anywhere you like as
|
||||
long as you specify it when executing the command:
|
||||
``make checkpatch CHECKPATCH=../path/to/folder``.
|
||||
|
||||
8. Create a pull request against the branch ``master``.
|
||||
|
||||
9. Be prepared to get some comments about your code and to modify it. Tip: Use
|
||||
``git rebase -i origin/master`` to modify chains of commits.
|
||||
@@ -1,34 +0,0 @@
|
||||
# Contributors to RGBDS
|
||||
|
||||
## Original author
|
||||
|
||||
- Carsten Elton Sørensen <csoren@gmail.com>
|
||||
|
||||
## Main contributors
|
||||
|
||||
- Justin Lloyd <jlloyd@imf.la>
|
||||
- Vegard Nossum <vegard.nossum@gmail.com>
|
||||
- Anthony J. Bentley <anthony@anjbe.name>
|
||||
- stag019 <stag019@gmail.com>
|
||||
- Antonio Niño Díaz <antonio_nd@outlook.com>
|
||||
- Eldred "ISSOtm" Habert <me@eldred.fr>
|
||||
- Sylvie "Rangi" Oukaour <https://github.com/Rangi42>
|
||||
|
||||
## Other contributors
|
||||
|
||||
- Ben Hetherington <dev@ben-h.uk>
|
||||
- Björn Höhrmann <bjoern@hoehrmann.de>
|
||||
- Christophe Staïesse <chastai@skynet.be>
|
||||
- David Brotz <dbrotz007@gmail.com>
|
||||
- Evie <https://evie.gbdev.io>
|
||||
- James "JL2210" Larrowe <https://github.com/JL2210>
|
||||
- Maja Kądziołka <github@compilercrim.es>
|
||||
- The Musl C library <https://musl.libc.org/>
|
||||
- obskyr <powpowd@gmail.com>
|
||||
- The OpenBSD Project <http://www.openbsd.org>
|
||||
- Quint Guvernator <quint@guvernator.net>
|
||||
- Sanqui <gsanky@gmail.com>
|
||||
- YamaArashi <shadow962@live.com>
|
||||
- yenatch <yenatch@gmail.com>
|
||||
- phs <phil@philhsmith.com>
|
||||
- jidoc01 <jidoc01@naver.com>
|
||||
57
CONTRIBUTORS.rst
Normal file
57
CONTRIBUTORS.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
Contributors to RGBDS
|
||||
=====================
|
||||
|
||||
Original author
|
||||
---------------
|
||||
|
||||
- Carsten Elton Sørensen <csoren@gmail.com>
|
||||
|
||||
Main contributors
|
||||
-----------------
|
||||
|
||||
- Justin Lloyd <jlloyd@imf.la>
|
||||
|
||||
- Vegard Nossum <vegard.nossum@gmail.com>
|
||||
|
||||
- Anthony J. Bentley <anthony@anjbe.name>
|
||||
|
||||
- stag019 <stag019@gmail.com>
|
||||
|
||||
- Antonio Niño Díaz <antonio_nd@outlook.com>
|
||||
|
||||
- Eldred "ISSOtm" Habert <eldredhabert0@gmail.com>
|
||||
|
||||
- Rangi <http://github.com/Rangi42>
|
||||
|
||||
Other contributors
|
||||
------------------
|
||||
|
||||
- Ben Hetherington <dev@ben-h.uk>
|
||||
|
||||
- Björn Höhrmann <bjoern@hoehrmann.de>
|
||||
|
||||
- Christophe Staïesse <chastai@skynet.be>
|
||||
|
||||
- David Brotz <dbrotz007@gmail.com>
|
||||
|
||||
- Jakub Kądziołka <kuba@kadziolka.net>
|
||||
|
||||
- James "JL2210" Larrowe <https://github.com/JL2210>
|
||||
|
||||
- The Musl C library <http://www.musl-libc.org>
|
||||
|
||||
- obskyr <powpowd@gmail.com>
|
||||
|
||||
- The OpenBSD Project <http://www.openbsd.org>
|
||||
|
||||
- Quint Guvernator <quint@guvernator.net>
|
||||
|
||||
- Sanqui <gsanky@gmail.com>
|
||||
|
||||
- YamaArashi <shadow962@live.com>
|
||||
|
||||
- yenatch <yenatch@gmail.com>
|
||||
|
||||
- phs <phil@philhsmith.com>
|
||||
|
||||
- jidoc01 <jidoc01@naver.com>
|
||||
34
Dockerfile
34
Dockerfile
@@ -1,14 +1,24 @@
|
||||
FROM debian:11-slim
|
||||
LABEL org.opencontainers.image.source=https://github.com/gbdev/rgbds
|
||||
ARG version=0.9.0-rc1
|
||||
# This file is part of RGBDS.
|
||||
#
|
||||
# Copyright (c) 2018-2019, Phil Smith and RGBDS contributors.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
# docker build -t rgbds:vX.X.X-alpine
|
||||
FROM alpine:latest
|
||||
RUN apk add --update \
|
||||
build-base \
|
||||
bison \
|
||||
libpng-dev
|
||||
COPY . /rgbds
|
||||
WORKDIR /rgbds
|
||||
RUN make Q='' all
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install sudo make cmake gcc build-essential -y
|
||||
|
||||
RUN ./.github/scripts/install_deps.sh ubuntu-20.04
|
||||
RUN make -j CXXFLAGS="-O3 -flto -DNDEBUG -static" PKG_CONFIG="pkg-config --static" Q=
|
||||
|
||||
RUN tar caf rgbds-${version}-linux-x86_64.tar.xz --transform='s#.*/##' rgbasm rgblink rgbfix rgbgfx man/* .github/scripts/install.sh
|
||||
FROM alpine:latest
|
||||
RUN apk add --update \
|
||||
libpng
|
||||
COPY --from=0 \
|
||||
/rgbds/rgbasm \
|
||||
/rgbds/rgbfix \
|
||||
/rgbds/rgblink \
|
||||
/rgbds/rgbgfx \
|
||||
/bin/
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 1997-2024, Carsten Sørensen and RGBDS contributors.
|
||||
Copyright (c) 1997-2020, Carsten Sorensen and RGBDS contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
|
||||
226
Makefile
226
Makefile
@@ -1,9 +1,13 @@
|
||||
#
|
||||
# This file is part of RGBDS.
|
||||
#
|
||||
# Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .y .o
|
||||
|
||||
.PHONY: all clean install checkdiff develop debug profile coverage iwyu mingw32 mingw64 wine-shim dist
|
||||
.SUFFIXES: .h .y .c .o
|
||||
|
||||
# User-defined variables
|
||||
|
||||
@@ -11,10 +15,10 @@ Q := @
|
||||
PREFIX := /usr/local
|
||||
bindir := ${PREFIX}/bin
|
||||
mandir := ${PREFIX}/share/man
|
||||
SUFFIX :=
|
||||
STRIP := -s
|
||||
BINMODE := 755
|
||||
MANMODE := 644
|
||||
CHECKPATCH := ../linux/scripts/checkpatch.pl
|
||||
|
||||
# Other variables
|
||||
|
||||
@@ -23,26 +27,26 @@ PNGCFLAGS := `${PKG_CONFIG} --cflags libpng`
|
||||
PNGLDFLAGS := `${PKG_CONFIG} --libs-only-L libpng`
|
||||
PNGLDLIBS := `${PKG_CONFIG} --libs-only-l libpng`
|
||||
|
||||
# Note: if this comes up empty, `version.cpp` will automatically fall back to last release number
|
||||
VERSION_STRING := `git --git-dir=.git describe --tags --dirty --always 2>/dev/null`
|
||||
# Note: if this comes up empty, `version.c` will automatically fall back to last release number
|
||||
VERSION_STRING := `git describe --tags --dirty --always 2>/dev/null`
|
||||
|
||||
WARNFLAGS := -Wall -pedantic -Wno-unknown-warning-option \
|
||||
-Wno-gnu-zero-variadic-macro-arguments
|
||||
WARNFLAGS := -Wall -pedantic
|
||||
|
||||
# Overridable CXXFLAGS
|
||||
CXXFLAGS ?= -O3 -flto -DNDEBUG
|
||||
# Non-overridable CXXFLAGS
|
||||
REALCXXFLAGS := ${CXXFLAGS} ${WARNFLAGS} -std=c++2a -I include \
|
||||
-D_POSIX_C_SOURCE=200809L -fno-exceptions -fno-rtti
|
||||
# Overridable CFLAGS
|
||||
CFLAGS ?= -O3 -flto -DNDEBUG
|
||||
# Non-overridable CFLAGS
|
||||
# _ISOC11_SOURCE is required on certain platforms to get C11 on top of the C99-based POSIX 2008
|
||||
REALCFLAGS := ${CFLAGS} ${WARNFLAGS} -std=gnu11 -I include \
|
||||
-D_POSIX_C_SOURCE=200809L -D_ISOC11_SOURCE
|
||||
# Overridable LDFLAGS
|
||||
LDFLAGS ?=
|
||||
# Non-overridable LDFLAGS
|
||||
REALLDFLAGS := ${LDFLAGS} ${WARNFLAGS} \
|
||||
-DBUILD_VERSION_STRING=\"${VERSION_STRING}\"
|
||||
|
||||
# Wrapper around bison that passes flags depending on what the version supports
|
||||
BISON := src/bison.sh
|
||||
YFLAGS ?= -Wall
|
||||
|
||||
BISON := bison
|
||||
RM := rm -rf
|
||||
|
||||
# Used for checking pull requests
|
||||
@@ -66,15 +70,16 @@ rgbasm_obj := \
|
||||
src/asm/rpn.o \
|
||||
src/asm/section.o \
|
||||
src/asm/symbol.o \
|
||||
src/asm/util.o \
|
||||
src/asm/warning.o \
|
||||
src/extern/getopt.o \
|
||||
src/extern/utf8decoder.o \
|
||||
src/error.o \
|
||||
src/hashmap.o \
|
||||
src/linkdefs.o \
|
||||
src/opmath.o \
|
||||
src/util.o
|
||||
src/opmath.o
|
||||
|
||||
src/asm/lexer.o src/asm/main.o: src/asm/parser.hpp
|
||||
src/asm/lexer.o src/asm/main.o: src/asm/parser.h
|
||||
|
||||
rgblink_obj := \
|
||||
src/link/assign.o \
|
||||
@@ -83,17 +88,13 @@ rgblink_obj := \
|
||||
src/link/output.o \
|
||||
src/link/patch.o \
|
||||
src/link/script.o \
|
||||
src/link/sdas_obj.o \
|
||||
src/link/section.o \
|
||||
src/link/symbol.o \
|
||||
src/extern/getopt.o \
|
||||
src/extern/utf8decoder.o \
|
||||
src/error.o \
|
||||
src/hashmap.o \
|
||||
src/linkdefs.o \
|
||||
src/opmath.o \
|
||||
src/util.o
|
||||
|
||||
src/link/main.o: src/link/script.hpp
|
||||
src/opmath.o
|
||||
|
||||
rgbfix_obj := \
|
||||
src/fix/main.o \
|
||||
@@ -101,69 +102,50 @@ rgbfix_obj := \
|
||||
src/error.o
|
||||
|
||||
rgbgfx_obj := \
|
||||
src/gfx/gb.o \
|
||||
src/gfx/main.o \
|
||||
src/gfx/pal_packing.o \
|
||||
src/gfx/pal_sorting.o \
|
||||
src/gfx/pal_spec.o \
|
||||
src/gfx/process.o \
|
||||
src/gfx/proto_palette.o \
|
||||
src/gfx/reverse.o \
|
||||
src/gfx/rgba.o \
|
||||
src/gfx/makepng.o \
|
||||
src/extern/getopt.o \
|
||||
src/error.o
|
||||
|
||||
rgbasm: ${rgbasm_obj}
|
||||
$Q${CXX} ${REALLDFLAGS} -o $@ ${rgbasm_obj} ${REALCXXFLAGS} src/version.cpp -lm
|
||||
$Q${CC} ${REALLDFLAGS} -o $@ ${rgbasm_obj} ${REALCFLAGS} src/version.c -lm
|
||||
|
||||
rgblink: ${rgblink_obj}
|
||||
$Q${CXX} ${REALLDFLAGS} -o $@ ${rgblink_obj} ${REALCXXFLAGS} src/version.cpp
|
||||
$Q${CC} ${REALLDFLAGS} -o $@ ${rgblink_obj} ${REALCFLAGS} src/version.c
|
||||
|
||||
rgbfix: ${rgbfix_obj}
|
||||
$Q${CXX} ${REALLDFLAGS} -o $@ ${rgbfix_obj} ${REALCXXFLAGS} src/version.cpp
|
||||
$Q${CC} ${REALLDFLAGS} -o $@ ${rgbfix_obj} ${REALCFLAGS} src/version.c
|
||||
|
||||
rgbgfx: ${rgbgfx_obj}
|
||||
$Q${CXX} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${REALCXXFLAGS} ${PNGLDLIBS} src/version.cpp
|
||||
|
||||
test/gfx/randtilegen: test/gfx/randtilegen.cpp
|
||||
$Q${CXX} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ $^ ${REALCXXFLAGS} ${PNGCFLAGS} ${PNGLDLIBS}
|
||||
|
||||
test/gfx/rgbgfx_test: test/gfx/rgbgfx_test.cpp
|
||||
$Q${CXX} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ $^ ${REALCXXFLAGS} ${PNGCFLAGS} ${PNGLDLIBS}
|
||||
$Q${CC} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${REALCFLAGS} src/version.c ${PNGLDLIBS}
|
||||
|
||||
# Rules to process files
|
||||
|
||||
# We want the Bison invocation to pass through our rules, not default ones
|
||||
.y.o:
|
||||
|
||||
.y.cpp:
|
||||
$Q${BISON} $@ $<
|
||||
|
||||
# Bison-generated C++ files have an accompanying header
|
||||
src/asm/parser.hpp: src/asm/parser.cpp
|
||||
$Qtouch $@
|
||||
src/link/script.hpp: src/link/script.cpp
|
||||
# Bison-generated C files have an accompanying header
|
||||
src/asm/parser.h: src/asm/parser.c
|
||||
$Qtouch $@
|
||||
|
||||
# Only RGBGFX uses libpng (POSIX make doesn't support pattern rules to cover all these)
|
||||
src/gfx/main.o: src/gfx/main.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/gfx/pal_packing.o: src/gfx/pal_packing.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/gfx/pal_sorting.o: src/gfx/pal_sorting.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/gfx/pal_spec.o: src/gfx/pal_spec.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/gfx/process.o: src/gfx/process.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/gfx/proto_palette.o: src/gfx/proto_palette.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/gfx/reverse.o: src/gfx/reverse.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/gfx/rgba.o: src/gfx/rgba.cpp
|
||||
$Q${CXX} ${REALCXXFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
src/asm/parser.c: src/asm/parser.y
|
||||
$QDEFS=; \
|
||||
add_flag(){ \
|
||||
if src/check_bison_ver.sh $$1 $$2; then \
|
||||
DEFS="-D$$3 $$DEFS"; \
|
||||
fi \
|
||||
}; \
|
||||
add_flag 3 5 api.token.raw=true; \
|
||||
add_flag 3 6 parse.error=detailed; \
|
||||
add_flag 3 0 parse.error=verbose; \
|
||||
add_flag 3 0 parse.lac=full; \
|
||||
add_flag 3 0 lr.type=ielr; \
|
||||
echo "DEFS=$$DEFS"; \
|
||||
${BISON} $$DEFS -d ${YFLAGS} -o $@ $<
|
||||
|
||||
.cpp.o:
|
||||
$Q${CXX} ${REALCXXFLAGS} -c -o $@ $<
|
||||
.c.o:
|
||||
$Q${CC} ${REALCFLAGS} ${PNGCFLAGS} -c -o $@ $<
|
||||
|
||||
# Target used to remove all files generated by other Makefile targets
|
||||
|
||||
@@ -173,23 +155,51 @@ clean:
|
||||
$Q${RM} rgbfix rgbfix.exe
|
||||
$Q${RM} rgbgfx rgbgfx.exe
|
||||
$Qfind src/ -name "*.o" -exec rm {} \;
|
||||
$Qfind . -type f \( -name "*.gcno" -o -name "*.gcda" -o -name "*.gcov" \) -exec rm {} \;
|
||||
$Q${RM} rgbshim.sh
|
||||
$Q${RM} src/asm/parser.cpp src/asm/parser.hpp src/asm/stack.hh
|
||||
$Q${RM} src/link/script.cpp src/link/script.hpp src/link/stack.hh
|
||||
$Q${RM} test/gfx/randtilegen test/gfx/rgbgfx_test
|
||||
$Q${RM} src/asm/parser.c src/asm/parser.h
|
||||
|
||||
# Target used to install the binaries and man pages.
|
||||
|
||||
install: all
|
||||
$Qinstall -d ${DESTDIR}${bindir}/ ${DESTDIR}${mandir}/man1/ ${DESTDIR}${mandir}/man5/ ${DESTDIR}${mandir}/man7/
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbasm ${DESTDIR}${bindir}/rgbasm${SUFFIX}
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgblink ${DESTDIR}${bindir}/rgblink${SUFFIX}
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbfix ${DESTDIR}${bindir}/rgbfix${SUFFIX}
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbgfx ${DESTDIR}${bindir}/rgbgfx${SUFFIX}
|
||||
$Qinstall -m ${MANMODE} man/rgbasm.1 man/rgblink.1 man/rgbfix.1 man/rgbgfx.1 ${DESTDIR}${mandir}/man1/
|
||||
$Qinstall -m ${MANMODE} man/rgbds.5 man/rgbasm.5 man/rgblink.5 ${DESTDIR}${mandir}/man5/
|
||||
$Qinstall -m ${MANMODE} man/rgbds.7 man/gbz80.7 ${DESTDIR}${mandir}/man7/
|
||||
$Qmkdir -p ${DESTDIR}${bindir}
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbasm ${DESTDIR}${bindir}/rgbasm
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbfix ${DESTDIR}${bindir}/rgbfix
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgblink ${DESTDIR}${bindir}/rgblink
|
||||
$Qinstall ${STRIP} -m ${BINMODE} rgbgfx ${DESTDIR}${bindir}/rgbgfx
|
||||
$Qmkdir -p ${DESTDIR}${mandir}/man1 ${DESTDIR}${mandir}/man5 ${DESTDIR}${mandir}/man7
|
||||
$Qinstall -m ${MANMODE} src/rgbds.7 ${DESTDIR}${mandir}/man7/rgbds.7
|
||||
$Qinstall -m ${MANMODE} src/gbz80.7 ${DESTDIR}${mandir}/man7/gbz80.7
|
||||
$Qinstall -m ${MANMODE} src/rgbds.5 ${DESTDIR}${mandir}/man5/rgbds.5
|
||||
$Qinstall -m ${MANMODE} src/asm/rgbasm.1 ${DESTDIR}${mandir}/man1/rgbasm.1
|
||||
$Qinstall -m ${MANMODE} src/asm/rgbasm.5 ${DESTDIR}${mandir}/man5/rgbasm.5
|
||||
$Qinstall -m ${MANMODE} src/fix/rgbfix.1 ${DESTDIR}${mandir}/man1/rgbfix.1
|
||||
$Qinstall -m ${MANMODE} src/link/rgblink.1 ${DESTDIR}${mandir}/man1/rgblink.1
|
||||
$Qinstall -m ${MANMODE} src/link/rgblink.5 ${DESTDIR}${mandir}/man5/rgblink.5
|
||||
$Qinstall -m ${MANMODE} src/gfx/rgbgfx.1 ${DESTDIR}${mandir}/man1/rgbgfx.1
|
||||
|
||||
# Target used to check the coding style of the whole codebase.
|
||||
# `extern/` is excluded, as it contains external code that should not be patched
|
||||
# to meet our coding style, so applying upstream patches is easier.
|
||||
# `.y` files aren't checked, unfortunately...
|
||||
|
||||
checkcodebase:
|
||||
$Qfor file in `git ls-files | grep -E '(\.c|\.h)$$' | grep -Ev '(src|include)/extern/'`; do \
|
||||
${CHECKPATCH} -f "$$file"; \
|
||||
done
|
||||
|
||||
# Target used to check the coding style of the patches from the upstream branch
|
||||
# to the HEAD. Runs checkpatch once for each commit between the current HEAD and
|
||||
# the first common commit between the HEAD and origin/master.
|
||||
# `.y` files aren't checked, unfortunately...
|
||||
|
||||
checkpatch:
|
||||
$QCOMMON_COMMIT=`git merge-base HEAD ${BASE_REF}`; \
|
||||
for commit in `git rev-list $$COMMON_COMMIT..HEAD`; do \
|
||||
echo "[*] Analyzing commit '$$commit'"; \
|
||||
git format-patch --stdout "$$commit~..$$commit" \
|
||||
-- src include '!src/extern' '!include/extern' \
|
||||
| ${CHECKPATCH} - || true; \
|
||||
done
|
||||
|
||||
# Target used to check for suspiciously missing changed files.
|
||||
|
||||
@@ -202,64 +212,40 @@ checkdiff:
|
||||
# The rationale for some of the flags is documented in the CMakeLists.
|
||||
|
||||
develop:
|
||||
$Q${MAKE} WARNFLAGS="${WARNFLAGS} -Werror -Wextra \
|
||||
$Qenv ${MAKE} WARNFLAGS="-Werror -Wextra \
|
||||
-Walloc-zero -Wcast-align -Wcast-qual -Wduplicated-branches -Wduplicated-cond \
|
||||
-Wfloat-equal -Wlogical-op -Wnull-dereference -Wshift-overflow=2 \
|
||||
-Wstringop-overflow=4 -Wundef -Wuninitialized -Wunused -Wshadow \
|
||||
-Wfloat-equal -Winline -Wlogical-op -Wnested-externs -Wold-style-definition \
|
||||
-Wshift-overflow=2 \
|
||||
-Wstrict-overflow=5 -Wstrict-prototypes -Wundef -Wuninitialized -Wunused \
|
||||
-Wshadow \
|
||||
-Wnull-dereference -Wstringop-overflow=4 \
|
||||
-Wformat=2 -Wformat-overflow=2 -Wformat-truncation=1 \
|
||||
-Wno-format-nonliteral -Wno-strict-overflow -Wno-unused-but-set-variable \
|
||||
-Wno-type-limits -Wno-tautological-constant-out-of-range-compare -Wvla \
|
||||
-D_GLIBCXX_ASSERTIONS \
|
||||
-Wno-format-nonliteral \
|
||||
-Wno-type-limits -Wno-tautological-constant-out-of-range-compare \
|
||||
-Wvla \
|
||||
-Wno-unknown-warning-option \
|
||||
-fsanitize=shift -fsanitize=integer-divide-by-zero \
|
||||
-fsanitize=unreachable -fsanitize=vla-bound \
|
||||
-fsanitize=signed-integer-overflow -fsanitize=bounds \
|
||||
-fsanitize=object-size -fsanitize=bool -fsanitize=enum \
|
||||
-fsanitize=alignment -fsanitize=null -fsanitize=address" \
|
||||
CXXFLAGS="-ggdb3 -Og -fno-omit-frame-pointer -fno-optimize-sibling-calls"
|
||||
|
||||
# This target is used during development in order to more easily debug with gdb.
|
||||
|
||||
debug:
|
||||
$Qenv ${MAKE} \
|
||||
CXXFLAGS="-ggdb3 -O0 -fno-omit-frame-pointer -fno-optimize-sibling-calls"
|
||||
|
||||
# This target is used during development in order to more easily profile with callgrind.
|
||||
|
||||
profile:
|
||||
$Qenv ${MAKE} \
|
||||
CXXFLAGS="-ggdb3 -O3 -fno-omit-frame-pointer -fno-optimize-sibling-calls"
|
||||
|
||||
# This target is used during development in order to inspect code coverage with gcov.
|
||||
|
||||
coverage:
|
||||
$Qenv ${MAKE} \
|
||||
CXXFLAGS="-ggdb3 -Og --coverage -fno-omit-frame-pointer -fno-optimize-sibling-calls"
|
||||
|
||||
# This target is used during development in order to remove unused `#include` headers.
|
||||
|
||||
iwyu:
|
||||
$Qenv ${MAKE} \
|
||||
CXX="include-what-you-use" \
|
||||
REALCXXFLAGS="-std=c++2a -I include"
|
||||
CFLAGS="-ggdb3 -Og -fno-omit-frame-pointer -fno-optimize-sibling-calls"
|
||||
|
||||
# Targets for the project maintainer to easily create Windows exes.
|
||||
# This is not for Windows users!
|
||||
# If you're building on Windows with Cygwin or MinGW, just follow the Unix
|
||||
# If you're building on Windows with Cygwin or Mingw, just follow the Unix
|
||||
# install instructions instead.
|
||||
|
||||
mingw32:
|
||||
$Q${MAKE} all test/gfx/randtilegen test/gfx/rgbgfx_test \
|
||||
CXX=i686-w64-mingw32-g++ \
|
||||
CXXFLAGS="-O3 -flto -DNDEBUG -static-libgcc -static-libstdc++" \
|
||||
PKG_CONFIG="PKG_CONFIG_SYSROOT_DIR=/usr/i686-w64-mingw32 pkg-config"
|
||||
$Q${MAKE} CC=i686-w64-mingw32-gcc BISON=bison \
|
||||
PKG_CONFIG=i686-w64-mingw32-pkg-config -j
|
||||
|
||||
mingw64:
|
||||
$Q${MAKE} all test/gfx/randtilegen test/gfx/rgbgfx_test \
|
||||
CXX=x86_64-w64-mingw32-g++ \
|
||||
PKG_CONFIG="PKG_CONFIG_SYSROOT_DIR=/usr/x86_64-w64-mingw32 pkg-config"
|
||||
$Q${MAKE} CC=x86_64-w64-mingw32-gcc BISON=bison \
|
||||
PKG_CONFIG=x86_64-w64-mingw32-pkg-config -j
|
||||
|
||||
wine-shim:
|
||||
$Qecho '#!/usr/bin/env bash' > rgbshim.sh
|
||||
$Qecho '#!/bin/bash' > rgbshim.sh
|
||||
$Qecho 'WINEDEBUG=-all wine $$0.exe "$${@:1}"' >> rgbshim.sh
|
||||
$Qchmod +x rgbshim.sh
|
||||
$Qln -s rgbshim.sh rgbasm
|
||||
|
||||
161
README.md
161
README.md
@@ -1,161 +0,0 @@
|
||||
# RGBDS
|
||||
|
||||
RGBDS (Rednex Game Boy Development System) is a free assembler/linker package
|
||||
for the Game Boy and Game Boy Color. It consists of:
|
||||
|
||||
- RGBASM (assembler)
|
||||
- RGBLINK (linker)
|
||||
- RGBFIX (checksum/header fixer)
|
||||
- RGBGFX (PNG‐to‐Game Boy graphics converter)
|
||||
|
||||
This is a fork of the original RGBDS which aims to make the programs more like
|
||||
other UNIX tools.
|
||||
|
||||
|
||||
This toolchain is maintained [on GitHub](https://github.com/gbdev/rgbds).
|
||||
|
||||
The documentation of this toolchain can be [viewed online](https://rgbds.gbdev.io/docs/).
|
||||
It is generated from the man pages found in this repository.
|
||||
The source code of the website itself is on GitHub as well under the repository
|
||||
[rgbds-www](https://github.com/gbdev/rgbds-www).
|
||||
|
||||
If you want to contribute or maintain RGBDS, or you have questions regarding the code, its
|
||||
organization, etc. you can find the maintainers [on the gbdev community channels](https://gbdev.io/chat)
|
||||
or via mail at `rgbds at gbdev dot io`.
|
||||
|
||||
## 1. Installing RGBDS
|
||||
|
||||
The [installation procedure](https://rgbds.gbdev.io/install) is available
|
||||
online for various platforms. [Building from source](https://rgbds.gbdev.io/install/source)
|
||||
is possible using `make` or `cmake`; follow the link for more detailed instructions.
|
||||
|
||||
```sh
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
```sh
|
||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build
|
||||
cmake --install build
|
||||
```
|
||||
|
||||
Two parameters available when building are a prefix (e.g. to put the executables in a directory)
|
||||
and a suffix (e.g. to append the version number or commit ID).
|
||||
|
||||
```sh
|
||||
make
|
||||
sudo make install PREFIX=install_dir/ SUFFIX=-$(git rev-parse --short HEAD)
|
||||
```
|
||||
|
||||
```sh
|
||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DSUFFIX=-$(git rev-parse --short HEAD)
|
||||
cmake --build build
|
||||
cmake --install build --prefix install_dir
|
||||
```
|
||||
|
||||
(If you set a `SUFFIX`, it should include the `.exe` extension on Windows.)
|
||||
|
||||
## 2. RGBDS Folder Organization
|
||||
|
||||
The RGBDS source code file structure is as follows:
|
||||
|
||||
```
|
||||
.
|
||||
├── .github/
|
||||
│ ├── scripts/
|
||||
│ │ └── ...
|
||||
│ └── workflows/
|
||||
│ └── ...
|
||||
├── contrib/
|
||||
│ ├── zsh_compl/
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
├── include/
|
||||
│ └── ...
|
||||
├── man/
|
||||
│ └── ...
|
||||
├── src/
|
||||
│ ├── asm/
|
||||
│ │ └── ...
|
||||
│ ├── extern/
|
||||
│ │ └── ...
|
||||
│ ├── fix/
|
||||
│ │ └── ...
|
||||
│ ├── gfx/
|
||||
│ │ └── ...
|
||||
│ ├── link/
|
||||
│ │ └── ...
|
||||
│ ├── CMakeLists.txt
|
||||
│ └── ...
|
||||
├── test/
|
||||
│ ├── ...
|
||||
│ └── run-tests.sh
|
||||
├── .clang-format
|
||||
├── CMakeLists.txt
|
||||
├── Dockerfile
|
||||
├── Makefile
|
||||
└── README.md
|
||||
```
|
||||
|
||||
- `.github/` - files and scripts related to the integration of the RGBDS codebase with
|
||||
GitHub.
|
||||
* `scripts/` - scripts used by workflow files.
|
||||
* `workflows/` - CI workflow description files.
|
||||
- `contrib/` - scripts and other resources which may be useful to users and developers of
|
||||
RGBDS.
|
||||
* `zsh_compl` contains tab completion scripts for use with zsh. Put them somewhere in
|
||||
your `fpath`, and they should auto-load.
|
||||
* `bash_compl` contains tab completion scripts for use with bash. Run them with `source`
|
||||
somewhere in your `.bashrc`, and they should load every time you open a shell.
|
||||
- `include/` - header files for the respective source files in `src`.
|
||||
- `man/` - manual pages.
|
||||
- `src/` - source code of RGBDS.
|
||||
* Note that the code unique to each RGBDS tool is stored in its respective subdirectory
|
||||
(RGBASM's code is in `src/asm/`, for example). `src/extern/` contains code imported from
|
||||
external sources.
|
||||
- `test/` - testing framework used to verify that changes to the code don't break or
|
||||
modify the behavior of RGBDS.
|
||||
- `.clang-format` - code style for automated C++ formatting with
|
||||
[`clang-format`](https://clang.llvm.org/docs/ClangFormat.html).
|
||||
- `Dockerfile` - defines how to build RGBDS with Docker.
|
||||
|
||||
## 3. History
|
||||
|
||||
- 1996-10-01: Carsten Sørensen (a.k.a. SurfSmurf) releases
|
||||
[xAsm](http://otakunozoku.com/RGBDSdocs/asm.htm),
|
||||
[xLink](http://otakunozoku.com/RGBDSdocs/link.htm), and
|
||||
[RGBFix](http://otakunozoku.com/RGBDSdocs/fix.htm),
|
||||
a Game Boy SM83 (GBZ80) assembler/linker system for DOS/Win32.
|
||||
- 1997-07-03: Sørensen releases [ASMotor](http://otakunozoku.com/RGBDSdocs/geninfo.htm),
|
||||
packaging the three programs together and moving towards making them a
|
||||
general-purpose target-independent system.
|
||||
- 1999-08-01: Justin Lloyd (a.k.a. Otaku no Zoku) adapts ASMotor to re-focus
|
||||
on SM83 assembly/machine code, and releases this version as
|
||||
[RGBDS](http://otakunozoku.com/rednex-gameboy-development-system/).
|
||||
- 2009-06-11: Vegard Nossum adapts the code to be more UNIX-like and releases
|
||||
this version as [rgbds-linux](https://github.com/vegard/rgbds-linux).
|
||||
- 2010-01-12: Anthony J. Bentley [forks](https://github.com/bentley) Nossum's
|
||||
repository. The fork becomes the reference implementation of RGBDS.
|
||||
- 2015-01-18: stag019 begins implementing [RGBGFX](https://github.com/stag019/rgbgfx),
|
||||
a PNG‐to‐Game Boy graphics converter, for eventual integration into RGBDS.
|
||||
- 2016-09-05: RGBGFX is [integrated](https://github.com/gbdev/rgbds/commit/c3c31138ddbd8680d4e67957e387f2816798a71b)
|
||||
into Bentley's repository.
|
||||
- 2017-02-23: Bentley's repository is moved to the [rednex](https://github.com/rednex)
|
||||
organization.
|
||||
- 2018-01-26: The codebase is [relicensed](https://github.com/gbdev/rgbds/issues/128)
|
||||
under the MIT license.
|
||||
- 2020-09-15: The repository is [moved](https://github.com/gbdev/rgbds/issues/567)
|
||||
to the [gbdev](https://github.com/gbdev) organization.
|
||||
- 2022-05-17: The [rgbds.gbdev.io](https://rgbds.gbdev.io) website for RGBDS
|
||||
documentation and downloads is published.
|
||||
|
||||
## 4. Acknowledgements
|
||||
|
||||
RGBGFX generates palettes using algorithms found in the paper
|
||||
["Algorithms for the Pagination Problem, a Bin Packing with Overlapping Items"](https://arxiv.org/abs/1605.00558)
|
||||
([GitHub](https://github.com/pagination-problem/pagination), MIT license),
|
||||
by Aristide Grange, Imed Kacem, and Sébastien Martin.
|
||||
|
||||
RGBGFX's color palette was taken from [SameBoy](https://sameboy.github.io), with permission and help
|
||||
by [LIJI](https://github.com/LIJI32).
|
||||
128
README.rst
Normal file
128
README.rst
Normal file
@@ -0,0 +1,128 @@
|
||||
RGBDS
|
||||
=====
|
||||
|
||||
RGBDS (Rednex Game Boy Development System) is a free assembler/linker package
|
||||
for the Game Boy and Game Boy Color. It consists of:
|
||||
|
||||
- rgbasm (assembler)
|
||||
- rgblink (linker)
|
||||
- rgbfix (checksum/header fixer)
|
||||
- rgbgfx (PNG‐to‐Game Boy graphics converter)
|
||||
|
||||
This is a fork of the original RGBDS which aims to make the programs more like
|
||||
other UNIX tools.
|
||||
|
||||
This toolchain is maintained on `GitHub <https://github.com/rednex/rgbds>`__.
|
||||
|
||||
The documentation of this toolchain can be viewed online
|
||||
`here <https://rgbds.gbdev.io/docs/>`__, it is generated from the man pages
|
||||
found in this repository.
|
||||
|
||||
If you want to contribute or maintain RGBDS, and have questions regarding the code, its organisation, etc. you can find me `on GBDev <https://gbdev.io/chat>`__ or via mail at ``rgbds at eldred dot fr``.
|
||||
|
||||
1. Installing RGBDS
|
||||
-------------------
|
||||
|
||||
The `installation procedure <https://rgbds.gbdev.io/install>`__ is available
|
||||
online for various platforms. `Building from source <https://rgbds.gbdev.io/install/source>`__
|
||||
is possible using ``make`` or ``cmake``; follow the link for more detailed instructions.
|
||||
|
||||
.. code:: sh
|
||||
|
||||
make
|
||||
sudo make install
|
||||
|
||||
.. code:: sh
|
||||
|
||||
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build
|
||||
cmake --install build
|
||||
|
||||
2. RGBDS Folder Organization
|
||||
----------------------------
|
||||
|
||||
The RGBDS source code file structure somewhat resembles the following:
|
||||
|
||||
::
|
||||
|
||||
.
|
||||
├── .github/
|
||||
│ ├── actions/
|
||||
│ │ └── ...
|
||||
│ └── workflows/
|
||||
│ └── ...
|
||||
├── contrib/
|
||||
│ ├── zsh_compl/
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
├── include/
|
||||
│ └── ...
|
||||
├── src/
|
||||
│ ├── asm/
|
||||
│ │ └── ...
|
||||
│ ├── extern/
|
||||
│ │ └── ...
|
||||
│ ├── fix/
|
||||
│ │ └── ...
|
||||
│ ├── gfx/
|
||||
│ │ └── ...
|
||||
│ ├── link/
|
||||
│ │ └── ...
|
||||
│ ├── CMakeLists.txt
|
||||
│ └── ...
|
||||
├── test/
|
||||
│ ├── ...
|
||||
│ └── run-tests.sh
|
||||
├── .clang-format
|
||||
├── CMakeLists.txt
|
||||
├── Makefile
|
||||
└── README.rst
|
||||
|
||||
.. |clang-format| replace:: ``clang-format``
|
||||
.. _clang-format: https://clang.llvm.org/docs/ClangFormat.html
|
||||
|
||||
- ``.github/`` - files and scripts related to the integration of the RGBDS codebase with
|
||||
GitHub.
|
||||
|
||||
* ``actions/`` - scripts used by workflow files.
|
||||
* ``workflows/`` - CI workflow description files.
|
||||
|
||||
- ``contrib/`` - scripts and other resources which may be useful to users and developers of
|
||||
RGBDS.
|
||||
|
||||
* ``zsh_compl`` contains tab completion scripts for use with zsh. Put them somewhere in your ``fpath``, and they should auto-load.
|
||||
|
||||
* ``bash_compl`` contains tab completion scripts for use with bash. Run them with ``source`` somewhere in your ``.bashrc``, and they should load every time you open a shell.
|
||||
|
||||
- ``include/`` - header files for each respective C files in `src`.
|
||||
|
||||
- ``src/`` - source code and manual pages for RGBDS.
|
||||
|
||||
* Note that the code unique to each RGBDS tool is stored in its respective subdirectory
|
||||
(rgbasm -> ``src/asm/``, for example). ``src/extern/`` contains code imported from external sources.
|
||||
|
||||
- ``test/`` - testing framework used to verify that changes to the code don't break or modify the behavior of RGBDS.
|
||||
|
||||
- ``.clang-format`` - code style for automated formatting with |clang-format|_. The C code does not currently follow this style, but all C++ code should.
|
||||
|
||||
3. History
|
||||
----------
|
||||
|
||||
- Around 1997, Carsten Sørensen (AKA SurfSmurf) writes ASMotor as a
|
||||
general-purpose assembler/linker system for DOS/Win32
|
||||
|
||||
- Around 1999, Justin Lloyd (AKA Otaku no Zoku) adapts ASMotor to read and
|
||||
produce GBZ80 assembly/machine code, and releases this version as RGBDS.
|
||||
|
||||
- 2009, Vegard Nossum adapts the code to be more UNIX-like and releases
|
||||
this version as rgbds-linux on
|
||||
`GitHub <https://github.com/vegard/rgbds-linux>`__.
|
||||
|
||||
- 2010, Anthony J. Bentley forks that repository. The fork becomes the reference
|
||||
implementation of rgbds.
|
||||
|
||||
- 2017, Bentley's repository is moved to a neutral name.
|
||||
|
||||
- 2018, codebase relicensed under the MIT license.
|
||||
|
||||
- 2020, repository is moved to the `gbdev <https://github.com/gbdev>`__ organisation. The `rgbds.gbdev.io <https://rgbds.gbdev.io>`__ website serving documentation and downloads is created.
|
||||
66
RELEASE.md
66
RELEASE.md
@@ -1,66 +0,0 @@
|
||||
# Releasing
|
||||
|
||||
This describes for the maintainers of RGBDS how to publish a new release on
|
||||
GitHub.
|
||||
|
||||
1. Update, commit, and push [include/version.hpp](include/version.hpp) with
|
||||
values for `PACKAGE_VERSION_MAJOR`, `PACKAGE_VERSION_MINOR`,
|
||||
`PACKAGE_VERSION_PATCH`, and `PACKAGE_VERSION_RC`, as well as
|
||||
[Dockerfile](Dockerfile) with a value for `ARG version`. Only define
|
||||
`PACKAGE_VERSION_RC` if you are publishing a release candidate! You can
|
||||
use <code>git commit -m "Release <i><version></i>"</code> and
|
||||
`git push origin master`.
|
||||
|
||||
2. Create a Git tag formatted as <code>v<i><MAJOR></i>.<i><MINOR></i>.<i><PATCH></i></code>,
|
||||
or <code>v<i><MAJOR></i>.<i><MINOR></i>.<i><PATCH></i>-rc<i><RC></i></code>
|
||||
for a release candidate. <code><i>MAJOR</i></code>, <code><i>MINOR</i></code>,
|
||||
<code><i>PATCH</i></code>, and <code><i>RC</i></code> should match their values from
|
||||
[include/version.hpp](include/version.hpp). You can use <code>git tag <i><tag></i></code>.
|
||||
|
||||
3. Push the tag to GitHub. You can use <code>git push origin <i><tag></i></code>.
|
||||
|
||||
GitHub Actions will run the [create-release-artifacts.yaml](.github/workflows/create-release-artifacts.yaml)
|
||||
workflow to detect the tag starting with "`v[0-9]`" and automatically do the following:
|
||||
|
||||
1. Build 32-bit and 64-bit RGBDS binaries for Windows with `cmake`.
|
||||
|
||||
2. Package the binaries into zip files.
|
||||
|
||||
3. Package the source code into a tar.gz file with `make dist`.
|
||||
|
||||
4. Create a draft GitHub release for the tag, attaching the three
|
||||
packaged files. It will be a prerelease if the tag contains "`-rc`".
|
||||
|
||||
If an error occurred in the above steps, delete the tag and restart the
|
||||
procedure. You can use <code>git push --delete origin <i><tag></i></code> and
|
||||
<code>git tag --delete <i><tag></i></code>.
|
||||
|
||||
4. GitHub Actions will run the [create-release-docs.yml](.github/workflows/create-release-docs.yml)
|
||||
workflow to add the release documentation to [rgbds-www](https://github.com/gbdev/rgbds-www).
|
||||
|
||||
This is not done automatically for prereleases; if you want to do this manually,
|
||||
|
||||
1. Clone [rgbds-www](https://github.com/gbdev/rgbds-www). You can use
|
||||
`git clone https://github.com/gbdev/rgbds-www.git`.
|
||||
|
||||
2. Make sure that you have installed `groff` and `mandoc`. You will
|
||||
need `mandoc` 1.14.5 or later to support `-O toc`.
|
||||
|
||||
3. Inside of the `man` directory, run <code><i><path/to/rgbds-www></i>/maintainer/man_to_html.sh <i><tag></i> *</code> then <code><i><path/to/rgbds-www></i>/maintainer/new_release.sh <i><tag></i></code>.
|
||||
This will render the RGBDS documentation as HTML and PDF and copy it to
|
||||
`rgbds-www`.
|
||||
|
||||
If you do not have `groff` installed, you can change
|
||||
`groff -Tpdf -mdoc -wall` to `mandoc -Tpdf -I os=Linux` in
|
||||
[.github/actions/get-pages.sh](.github/actions/get-pages.sh) and it
|
||||
will suffice.
|
||||
|
||||
4. Commit and push the documentation. You can use <code>git commit -m
|
||||
"Create RGBDS <i><tag></i> documentation"</code> and `git push origin master`
|
||||
(within the `rgbds-www` directory, not RGBDS).
|
||||
|
||||
5. Write a changelog in the GitHub draft release.
|
||||
|
||||
6. Click the "Publish release" button to publish it!
|
||||
|
||||
7. Update the `release` branch. You can use `git push origin release`.
|
||||
67
RELEASE.rst
Normal file
67
RELEASE.rst
Normal file
@@ -0,0 +1,67 @@
|
||||
Releasing
|
||||
=========
|
||||
|
||||
This describes for the maintainers of RGBDS how to publish a new release on
|
||||
GitHub.
|
||||
|
||||
1. Update, commit, and push `include/version.h <include/version.h>`__ with
|
||||
values for ``PACKAGE_VERSION_MAJOR``, ``PACKAGE_VERSION_MINOR``,
|
||||
``PACKAGE_VERSION_PATCH``, and ``PACKAGE_VERSION_RC``. Only define
|
||||
``PACKAGE_VERSION_RC`` if you are publishing a release candidate! You can
|
||||
use ``git commit -m "Release <version>"`` and ``git push origin master``.
|
||||
|
||||
2. Create a Git tag formatted as ``v<MAJOR>.<MINOR>.<PATCH>``, or
|
||||
``v<MAJOR>.<MINOR>.<PATCH>-rc<RC>`` for a release candidate. ``MAJOR``,
|
||||
``MINOR``, ``PATCH``, and ``RC`` should match their values from
|
||||
`include/version.h <include/version.h>`__. You can use ``git tag <tag>``.
|
||||
|
||||
3. Push the tag to GitHub. You can use ``git push origin <tag>``.
|
||||
|
||||
GitHub Actions will run the `create-release-artifacts.yaml
|
||||
<.github/workflows/create-release-artifacts.yaml>`__ workflow to detect the
|
||||
tag starting with "``v[0-9]``" and automatically do the following:
|
||||
|
||||
1. Build 32-bit and 64-bit RGBDS binaries for Windows with ``cmake``.
|
||||
|
||||
2. Package the binaries into zip files.
|
||||
|
||||
3. Package the source code into a tar.gz file with ``make dist``.
|
||||
|
||||
4. Create a draft GitHub release for the tag, attaching the three
|
||||
packaged files. It will be a prerelease if the tag contains "``-rc``".
|
||||
|
||||
If an error occurred in the above steps, delete the tag and restart the
|
||||
procedure. You can use ``git push --delete origin <tag>`` and
|
||||
``git tag --delete <tag>``.
|
||||
|
||||
4. GitHub Actions will run the `create-release-docs.yml
|
||||
<.github/workflows/create-release-docs.yml>`__ workflow to add the release
|
||||
documentation to `rgbds-www <https://github.com/gbdev/rgbds-www>`__.
|
||||
|
||||
For a release candidate, which creates a prerelease, you will have to
|
||||
take these steps yourself.
|
||||
|
||||
1. Clone `rgbds-www <https://github.com/gbdev/rgbds-www>`__. You can use
|
||||
``git clone https://github.com/gbdev/rgbds-www.git``.
|
||||
|
||||
2. Make sure that you have installed ``groff`` and ``mandoc``. You will
|
||||
need ``mandoc`` 1.14.5 or later to support ``-O toc``.
|
||||
|
||||
3. Run ``.github/actions/get-pages.sh -r <path/to/rgbds-www> <tag>``. This
|
||||
will render the RGBDS documentation as HTML and PDF and copy it to
|
||||
``rgbds-www``.
|
||||
|
||||
If you do not have ``groff`` installed, you can change
|
||||
``groff -Tpdf -mdoc -wall`` to ``mandoc -Tpdf -I os=Linux`` in
|
||||
`.github/actions/get-pages.sh <.github/actions/get-pages.sh>`__ and it
|
||||
will suffice.
|
||||
|
||||
4. Commit and push the documentation. You can use ``git commit -m
|
||||
"Create RGBDS <tag> documentation"`` and ``git push origin master``
|
||||
(within the ``rgbds-www`` directory, not RGBDS).
|
||||
|
||||
5. Write a changelog in the GitHub draft release.
|
||||
|
||||
6. Click the "Publish release" button to publish it!
|
||||
|
||||
7. Update the `release` branch. You can use ``git push origin release``.
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#/usr/bin/env bash
|
||||
|
||||
# Known bugs:
|
||||
# - Newlines in file/directory names break this script
|
||||
@@ -11,7 +11,7 @@
|
||||
# - Directories are not completed as such in "coalesced" short-opt arguments. For example,
|
||||
# `rgbasm -M d<tab>` can autocomplete to `rgbasm -M dir/` (no space), but
|
||||
# `rgbasm -Md<tab>` would autocomplete to `rgbasm -Mdir ` (trailing space) instead.
|
||||
# This is because directory handling is performed by Readline, whom we can't tell about the short
|
||||
# This is because dircetory handling is performed by Readline, whom we can't tell about the short
|
||||
# opt kerfuffle. The user can work around by separating the argument, as shown above.
|
||||
# (Also, there might be more possible bugs if `-Mdir` is actually a directory. Ugh.)
|
||||
|
||||
@@ -20,27 +20,27 @@
|
||||
# Thus, we don't need to do much to handle that form of argument passing: skip '=' after long opts.
|
||||
|
||||
_rgbasm_completions() {
|
||||
COMPREPLY=()
|
||||
|
||||
# Format: "long_opt:state_after"
|
||||
# Empty long opt = it doesn't exit
|
||||
# See the `state` variable below for info about `state_after`
|
||||
declare -A opts=(
|
||||
[V]="version:normal"
|
||||
[E]="export-all:normal"
|
||||
[h]="halt-without-nop:normal"
|
||||
[L]="preserve-ld:normal"
|
||||
[v]="verbose:normal"
|
||||
[w]=":normal"
|
||||
[b]="binary-digits:unk"
|
||||
[D]="define:unk"
|
||||
[g]="gfx-chars:unk"
|
||||
[I]="include:dir"
|
||||
[i]="include:dir"
|
||||
[M]="dependfile:glob-*.mk *.d"
|
||||
[o]="output:glob-*.o"
|
||||
[P]="preinclude:glob-*.asm *.inc"
|
||||
[p]="pad-value:unk"
|
||||
[Q]="q-precision:unk"
|
||||
[r]="recursion-depth:unk"
|
||||
[s]="state:unk"
|
||||
[W]="warning:warning"
|
||||
[X]="max-errors:unk"
|
||||
)
|
||||
# Parse command-line up to current word
|
||||
local opt_ena=true
|
||||
@@ -58,18 +58,6 @@ _rgbasm_completions() {
|
||||
# "normal" is not returned, `optlen` will be set to the length (dash included) of the "option"
|
||||
# part of the argument.
|
||||
parse_short_opt() {
|
||||
# These options act like a long option (= takes up the entire word), but only use a single dash
|
||||
# So, they need some special handling
|
||||
if [[ "$1" = "-M"[GP] ]]; then
|
||||
state=normal
|
||||
optlen=${#1}
|
||||
return;
|
||||
elif [[ "$1" = "-M"[QT] ]]; then
|
||||
state='glob-*.d *.mk *.o'
|
||||
optlen=${#1}
|
||||
return;
|
||||
fi
|
||||
|
||||
for (( i = 1; i < "${#1}"; i++ )); do
|
||||
# If the option is not known, assume it doesn't take an argument
|
||||
local opt="${opts["${1:$i:1}"]:-":normal"}"
|
||||
@@ -83,7 +71,7 @@ _rgbasm_completions() {
|
||||
optlen=0
|
||||
}
|
||||
|
||||
for (( i = 1; i < COMP_CWORD; i++ )); do
|
||||
for (( i = 1; i < $COMP_CWORD; i++ )); do
|
||||
local word="${COMP_WORDS[$i]}"
|
||||
|
||||
# If currently processing an argument, skip this word
|
||||
@@ -99,7 +87,7 @@ _rgbasm_completions() {
|
||||
fi
|
||||
|
||||
# Check if it's a long option
|
||||
if [[ "$word" = '--'* ]]; then
|
||||
if [[ "${word:0:2}" = '--' ]]; then
|
||||
# If the option is unknown, assume it takes no arguments: keep the state at "normal"
|
||||
for long_opt in "${opts[@]}"; do
|
||||
if [[ "$word" = "--${long_opt%%:*}" ]]; then
|
||||
@@ -115,16 +103,25 @@ _rgbasm_completions() {
|
||||
fi
|
||||
done
|
||||
# Check if it's a short option
|
||||
elif [[ "$word" = '-'* ]]; then
|
||||
parse_short_opt "$word"
|
||||
# The last option takes an argument...
|
||||
if [[ "$state" != 'normal' ]]; then
|
||||
if [[ "$optlen" -ne "${#word}" ]]; then
|
||||
# If it's contained within the word, we won't complete it, revert to "normal"
|
||||
state=normal
|
||||
else
|
||||
# Otherwise, complete it, but start at the beginning of *that* word
|
||||
optlen=0
|
||||
elif [[ "${word:0:1}" = '-' ]]; then
|
||||
# The `-M?` ones are a mix of short and long, augh
|
||||
# They must match the *full* word, but only take a single dash
|
||||
# So, handle them here
|
||||
if [[ "$1" = "-M"[GP] ]]; then
|
||||
state=normal
|
||||
elif [[ "$1" = "-M"[TQ] ]]; then
|
||||
state='glob-*.d *.mk *.o'
|
||||
else
|
||||
parse_short_opt "$word"
|
||||
# The last option takes an argument...
|
||||
if [[ "$state" != 'normal' ]]; then
|
||||
if [[ "$optlen" -ne "${#word}" ]]; then
|
||||
# If it's contained within the word, we won't complete it, revert to "normal"
|
||||
state=normal
|
||||
else
|
||||
# Otherwise, complete it, but start at the beginning of *that* word
|
||||
optlen=0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -132,48 +129,48 @@ _rgbasm_completions() {
|
||||
|
||||
# Parse current word
|
||||
# Careful that it might look like an option, so use `--` aggressively!
|
||||
local cur_word="${COMP_WORDS[$i]}"
|
||||
local cur_word="${COMP_WORDS[$COMP_CWORD]}"
|
||||
|
||||
# Process options, as short ones may change the state
|
||||
if $opt_ena && [[ "$state" = 'normal' && "$cur_word" = '-'* ]]; then
|
||||
if $opt_ena && [[ "$state" = 'normal' && "${cur_word:0:1}" = '-' ]]; then
|
||||
# We might want to complete to an option or an arg to that option
|
||||
# Parse the option word to check
|
||||
# There's no whitespace in the option names, so we can ride a little dirty...
|
||||
|
||||
# Is this a long option?
|
||||
if [[ "$cur_word" = '--'* ]]; then
|
||||
if [[ "${cur_word:1:1}" = '-' ]]; then
|
||||
# It is, try to complete one
|
||||
mapfile -t COMPREPLY < <(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}")
|
||||
return 0
|
||||
elif [[ "$cur_word" = '-M'[GPQT] ]]; then
|
||||
# These options act like long opts with no arguments, so return them and exactly them
|
||||
COMPREPLY=( "$cur_word" )
|
||||
COMPREPLY+=( $(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}") )
|
||||
return 0
|
||||
else
|
||||
# Short options may be grouped, parse them to determine what to complete
|
||||
parse_short_opt "$cur_word"
|
||||
# The `-M?` ones may not be followed by anything
|
||||
if [[ "$1" != "-M"[GPTQ] ]]; then
|
||||
parse_short_opt "$cur_word"
|
||||
# We got some short options that behave like long ones
|
||||
COMPREPLY+=( $(compgen -W '-MG -MP -MT -MQ' -- "$cur_word") )
|
||||
|
||||
if [[ "$state" = 'normal' ]]; then
|
||||
mapfile -t COMPREPLY < <(compgen -W "${!opts[*]}" -P "$cur_word" ''; compgen -W '-MG -MP -MQ -MT' "$cur_word")
|
||||
return 0
|
||||
elif [[ "$optlen" = "${#cur_word}" && "$state" != "warning" ]]; then
|
||||
# This short option group only awaits its argument!
|
||||
# Post the option group as-is as a reply so that Readline inserts a space,
|
||||
# so that the next completion request switches to the argument
|
||||
# An exception is made for warnings, since it's idiomatic to stick them to the
|
||||
# `-W`, and it doesn't break anything.
|
||||
COMPREPLY=( "$cur_word" )
|
||||
return 0
|
||||
if [[ "$state" = 'normal' ]]; then
|
||||
COMPREPLY+=( $(compgen -W "${!opts[*]}" -P "$cur_word" '') )
|
||||
return 0
|
||||
elif [[ "$optlen" = "${#cur_word}" && "$state" != "warning" ]]; then
|
||||
# This short option group only awaits its argument!
|
||||
# Post the option group as-is as a reply so that Readline inserts a space,
|
||||
# so that the next completion request switches to the argument
|
||||
# An exception is made for warnings, since it's idiomatic to stick them to the
|
||||
# `-W`, and it doesn't break anything.
|
||||
COMPREPLY+=( "$cur_word" )
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
COMPREPLY=()
|
||||
case "$state" in
|
||||
unk) # Return with no replies: no idea what to complete!
|
||||
;;
|
||||
warning)
|
||||
mapfile -t COMPREPLY < <(compgen -W "
|
||||
COMPREPLY+=( $(compgen -W "
|
||||
assert
|
||||
backwards-for
|
||||
builtin-args
|
||||
@@ -183,20 +180,19 @@ _rgbasm_completions() {
|
||||
empty-macro-arg
|
||||
empty-strrpl
|
||||
large-constant
|
||||
long-string
|
||||
macro-shift
|
||||
nested-comment
|
||||
numeric-string
|
||||
obsolete
|
||||
purge
|
||||
shift
|
||||
shift-amount
|
||||
truncation
|
||||
unmapped-char
|
||||
user
|
||||
all
|
||||
extra
|
||||
everything
|
||||
error" -P "${cur_word:0:$optlen}" -- "${cur_word:$optlen}")
|
||||
error" -P "${cur_word:0:$optlen}" -- "${cur_word:$optlen}") )
|
||||
;;
|
||||
normal) # Acts like a glob...
|
||||
state="glob-*.asm *.inc *.sm83"
|
||||
@@ -213,10 +209,6 @@ _rgbasm_completions() {
|
||||
done < <(compgen -A directory -- "${cur_word:$optlen}")
|
||||
compopt -o filenames
|
||||
;;
|
||||
*)
|
||||
echo >&2 "Internal completion error: invalid state \"$state\", please report this bug"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
#/usr/bin/env bash
|
||||
|
||||
# Same notes as RGBASM
|
||||
|
||||
_rgbfix_completions() {
|
||||
COMPREPLY=()
|
||||
|
||||
# Format: "long_opt:state_after"
|
||||
# Empty long opt = it doesn't exit
|
||||
# See the `state` variable below for info about `state_after`
|
||||
@@ -16,7 +18,6 @@ _rgbfix_completions() {
|
||||
[f]="fix-spec:fix-spec"
|
||||
[i]="game-id:unk"
|
||||
[k]="new-licensee:unk"
|
||||
[L]="custom-logo:glob-*.1bpp"
|
||||
[l]="old-licensee:unk"
|
||||
[m]="mbc-type:mbc"
|
||||
[n]="rom-version:unk"
|
||||
@@ -53,7 +54,7 @@ _rgbfix_completions() {
|
||||
optlen=0
|
||||
}
|
||||
|
||||
for (( i = 1; i < COMP_CWORD; i++ )); do
|
||||
for (( i = 1; i < $COMP_CWORD; i++ )); do
|
||||
local word="${COMP_WORDS[$i]}"
|
||||
|
||||
# If currently processing an argument, skip this word
|
||||
@@ -69,7 +70,7 @@ _rgbfix_completions() {
|
||||
fi
|
||||
|
||||
# Check if it's a long option
|
||||
if [[ "$word" = '--'* ]]; then
|
||||
if [[ "${word:0:2}" = '--' ]]; then
|
||||
# If the option is unknown, assume it takes no arguments: keep the state at "normal"
|
||||
for long_opt in "${opts[@]}"; do
|
||||
if [[ "$word" = "--${long_opt%%:*}" ]]; then
|
||||
@@ -85,7 +86,7 @@ _rgbfix_completions() {
|
||||
fi
|
||||
done
|
||||
# Check if it's a short option
|
||||
elif [[ "$word" = '-'* ]]; then
|
||||
elif [[ "${word:0:1}" = '-' ]]; then
|
||||
parse_short_opt "$word"
|
||||
# The last option takes an argument...
|
||||
if [[ "$state" != 'normal' ]]; then
|
||||
@@ -102,25 +103,25 @@ _rgbfix_completions() {
|
||||
|
||||
# Parse current word
|
||||
# Careful that it might look like an option, so use `--` aggressively!
|
||||
local cur_word="${COMP_WORDS[$i]}"
|
||||
local cur_word="${COMP_WORDS[$COMP_CWORD]}"
|
||||
|
||||
# Process options, as short ones may change the state
|
||||
if $opt_ena && [[ "$state" = 'normal' && "$cur_word" = '-'* ]]; then
|
||||
if $opt_ena && [[ "$state" = 'normal' && "${cur_word:0:1}" = '-' ]]; then
|
||||
# We might want to complete to an option or an arg to that option
|
||||
# Parse the option word to check
|
||||
# There's no whitespace in the option names, so we can ride a little dirty...
|
||||
|
||||
# Is this a long option?
|
||||
if [[ "$cur_word" = '--'* ]]; then
|
||||
if [[ "${cur_word:1:1}" = '-' ]]; then
|
||||
# It is, try to complete one
|
||||
mapfile -t COMPREPLY < <(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}")
|
||||
COMPREPLY+=( $(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}") )
|
||||
return 0
|
||||
else
|
||||
# Short options may be grouped, parse them to determine what to complete
|
||||
parse_short_opt "$cur_word"
|
||||
|
||||
if [[ "$state" = 'normal' ]]; then
|
||||
mapfile -t COMPREPLY < <(compgen -W "${!opts[*]}" -P "$cur_word" '')
|
||||
COMPREPLY+=( $(compgen -W "${!opts[*]}" -P "$cur_word" '') )
|
||||
return 0
|
||||
elif [[ "$optlen" = "${#cur_word}" && "$state" != "warning" ]]; then
|
||||
# This short option group only awaits its argument!
|
||||
@@ -128,25 +129,22 @@ _rgbfix_completions() {
|
||||
# so that the next completion request switches to the argument
|
||||
# An exception is made for warnings, since it's idiomatic to stick them to the
|
||||
# `-W`, and it doesn't break anything.
|
||||
COMPREPLY=( "$cur_word" )
|
||||
COMPREPLY+=( "$cur_word" )
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
COMPREPLY=()
|
||||
case "$state" in
|
||||
unk) # Return with no replies: no idea what to complete!
|
||||
;;
|
||||
fix-spec)
|
||||
COMPREPLY=( "${cur_word}"{l,h,g,L,H,G} )
|
||||
COMPREPLY+=( "${cur_word}"{l,h,g,L,H,G} )
|
||||
;;
|
||||
mbc)
|
||||
local cur_arg="${cur_word:$optlen}"
|
||||
cur_arg="${cur_arg@U}"
|
||||
compopt -o nosort # Keep `help` first in the list, mainly
|
||||
mapfile -t COMPREPLY < <(compgen -W "help" -P "${cur_word:0:$optlen}" -- "${cur_word:$optlen}")
|
||||
mapfile -t COMPREPLY -O ${#COMPREPLY} < <(compgen -W "
|
||||
COMPREPLY=( $(compgen -W "
|
||||
ROM_ONLY
|
||||
MBC1{,+RAM,+RAM+BATTERY}
|
||||
MBC2{,+BATTERY}
|
||||
@@ -159,7 +157,8 @@ _rgbfix_completions() {
|
||||
BANDAI_TAMA5
|
||||
HUC3
|
||||
HUC1+RAM+BATTERY
|
||||
TPP1_1.0{,+BATTERY}{,+RTC}{,+RUMBLE,+MULTIRUMBLE}" -P "${cur_word:0:$optlen}" -- "${cur_word/ /_}")
|
||||
TPP1_1.0{,+BATTERY}{,+RTC}{,+RUMBLE,+MULTIRUMBLE}" -P "${cur_word:0:$optlen}" -- "`tr 'a-z ' 'A-Z_' <<<"${cur_word/ /_}"`") )
|
||||
COMPREPLY+=( $(compgen -W "help" -P "${cur_word:0:$optlen}" -- "${cur_word:$optlen}") )
|
||||
;;
|
||||
normal) # Acts like a glob...
|
||||
state="glob-*.gb *.gbc *.sgb"
|
||||
@@ -176,10 +175,6 @@ _rgbfix_completions() {
|
||||
done < <(compgen -A directory -- "${cur_word:$optlen}")
|
||||
compopt -o filenames
|
||||
;;
|
||||
*)
|
||||
echo >&2 "Internal completion error: invalid state \"$state\", please report this bug"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
#/usr/bin/env bash
|
||||
|
||||
# Same notes as RGBASM
|
||||
|
||||
_rgbgfx_completions() {
|
||||
COMPREPLY=()
|
||||
|
||||
# Format: "long_opt:state_after"
|
||||
# Empty long opt = it doesn't exit
|
||||
# See the `state` variable below for info about `state_after`
|
||||
declare -A opts=(
|
||||
[V]="version:normal"
|
||||
[C]="color-curve:normal"
|
||||
[D]="debug:normal"
|
||||
[h]="horizontal:normal"
|
||||
[m]="mirror-tiles:normal"
|
||||
[O]="group-outputs:normal"
|
||||
[u]="unique-tiles:normal"
|
||||
[v]="verbose:normal"
|
||||
[X]="mirror-x:normal"
|
||||
[Y]="mirror-y:normal"
|
||||
[Z]="columns:normal"
|
||||
[a]="attr-map:glob-*.attrmap"
|
||||
[A]="auto-attr-map:normal"
|
||||
[b]="base-tiles:unk"
|
||||
[c]="colors:unk"
|
||||
[f]="fix:normal"
|
||||
[F]="fix-and-save:normal"
|
||||
[a]="attr-map:*.attrmap"
|
||||
[A]="output-attr-map:normal"
|
||||
[d]="depth:unk"
|
||||
[i]="input-tileset:glob-*.2bpp"
|
||||
[L]="slice:unk"
|
||||
[N]="nb-tiles:unk"
|
||||
[n]="nb-palettes:unk"
|
||||
[o]="output:glob-*.2bpp"
|
||||
[p]="palette:glob-*.pal"
|
||||
[P]="auto-palette:normal"
|
||||
[q]="palette-map:glob-*.palmap"
|
||||
[Q]="auto-palette-map:normal"
|
||||
[r]="reverse:unk"
|
||||
[s]="palette-size:unk"
|
||||
[t]="tilemap:glob-*.tilemap"
|
||||
[T]="auto-tilemap:normal"
|
||||
[o]="output:glob *.2bpp"
|
||||
[p]="palette:glob *.pal"
|
||||
[P]="output-palette:normal"
|
||||
[t]="tilemap:glob *.tilemap"
|
||||
[T]="output-tilemap:normal"
|
||||
[x]="trim-end:unk"
|
||||
)
|
||||
# Parse command-line up to current word
|
||||
@@ -65,7 +57,7 @@ _rgbgfx_completions() {
|
||||
optlen=0
|
||||
}
|
||||
|
||||
for (( i = 1; i < COMP_CWORD; i++ )); do
|
||||
for (( i = 1; i < $COMP_CWORD; i++ )); do
|
||||
local word="${COMP_WORDS[$i]}"
|
||||
|
||||
# If currently processing an argument, skip this word
|
||||
@@ -81,7 +73,7 @@ _rgbgfx_completions() {
|
||||
fi
|
||||
|
||||
# Check if it's a long option
|
||||
if [[ "$word" = '--'* ]]; then
|
||||
if [[ "${word:0:2}" = '--' ]]; then
|
||||
# If the option is unknown, assume it takes no arguments: keep the state at "normal"
|
||||
for long_opt in "${opts[@]}"; do
|
||||
if [[ "$word" = "--${long_opt%%:*}" ]]; then
|
||||
@@ -97,7 +89,7 @@ _rgbgfx_completions() {
|
||||
fi
|
||||
done
|
||||
# Check if it's a short option
|
||||
elif [[ "$word" = '-'* ]]; then
|
||||
elif [[ "${word:0:1}" = '-' ]]; then
|
||||
parse_short_opt "$word"
|
||||
# The last option takes an argument...
|
||||
if [[ "$state" != 'normal' ]]; then
|
||||
@@ -114,25 +106,25 @@ _rgbgfx_completions() {
|
||||
|
||||
# Parse current word
|
||||
# Careful that it might look like an option, so use `--` aggressively!
|
||||
local cur_word="${COMP_WORDS[$i]}"
|
||||
local cur_word="${COMP_WORDS[$COMP_CWORD]}"
|
||||
|
||||
# Process options, as short ones may change the state
|
||||
if $opt_ena && [[ "$state" = 'normal' && "$cur_word" = '-'* ]]; then
|
||||
if $opt_ena && [[ "$state" = 'normal' && "${cur_word:0:1}" = '-' ]]; then
|
||||
# We might want to complete to an option or an arg to that option
|
||||
# Parse the option word to check
|
||||
# There's no whitespace in the option names, so we can ride a little dirty...
|
||||
|
||||
# Is this a long option?
|
||||
if [[ "$cur_word" = '--'* ]]; then
|
||||
if [[ "${cur_word:1:1}" = '-' ]]; then
|
||||
# It is, try to complete one
|
||||
mapfile -t COMPREPLY < <(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}")
|
||||
COMPREPLY+=( $(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}") )
|
||||
return 0
|
||||
else
|
||||
# Short options may be grouped, parse them to determine what to complete
|
||||
parse_short_opt "$cur_word"
|
||||
|
||||
if [[ "$state" = 'normal' ]]; then
|
||||
mapfile -t COMPREPLY < <(compgen -W "${!opts[*]}" -P "$cur_word" '')
|
||||
COMPREPLY+=( $(compgen -W "${!opts[*]}" -P "$cur_word" '') )
|
||||
return 0
|
||||
elif [[ "$optlen" = "${#cur_word}" && "$state" != "warning" ]]; then
|
||||
# This short option group only awaits its argument!
|
||||
@@ -140,13 +132,12 @@ _rgbgfx_completions() {
|
||||
# so that the next completion request switches to the argument
|
||||
# An exception is made for warnings, since it's idiomatic to stick them to the
|
||||
# `-W`, and it doesn't break anything.
|
||||
COMPREPLY=( "$cur_word" )
|
||||
COMPREPLY+=( "$cur_word" )
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
COMPREPLY=()
|
||||
case "$state" in
|
||||
unk) # Return with no replies: no idea what to complete!
|
||||
;;
|
||||
@@ -165,10 +156,6 @@ _rgbgfx_completions() {
|
||||
done < <(compgen -A directory -- "${cur_word:$optlen}")
|
||||
compopt -o filenames
|
||||
;;
|
||||
*)
|
||||
echo >&2 "Internal completion error: invalid state \"$state\", please report this bug"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
#/usr/bin/env bash
|
||||
|
||||
# Same notes as RGBASM
|
||||
|
||||
_rgblink_completions() {
|
||||
COMPREPLY=()
|
||||
|
||||
# Format: "long_opt:state_after"
|
||||
# Empty long opt = it doesn't exit
|
||||
# See the `state` variable below for info about `state_after`
|
||||
@@ -14,12 +16,12 @@ _rgblink_completions() {
|
||||
[w]="wramx:normal"
|
||||
[x]="nopad:normal"
|
||||
[l]="linkerscript:glob-*"
|
||||
[M]="no-sym-in-map:normal"
|
||||
[m]="map:glob-*.map"
|
||||
[n]="sym:glob-*.sym"
|
||||
[O]="overlay:glob-*.gb *.gbc *.sgb"
|
||||
[o]="output:glob-*.gb *.gbc *.sgb"
|
||||
[p]="pad:unk"
|
||||
[s]="smart:unk"
|
||||
)
|
||||
# Parse command-line up to current word
|
||||
local opt_ena=true
|
||||
@@ -50,7 +52,7 @@ _rgblink_completions() {
|
||||
optlen=0
|
||||
}
|
||||
|
||||
for (( i = 1; i < COMP_CWORD; i++ )); do
|
||||
for (( i = 1; i < $COMP_CWORD; i++ )); do
|
||||
local word="${COMP_WORDS[$i]}"
|
||||
|
||||
# If currently processing an argument, skip this word
|
||||
@@ -66,7 +68,7 @@ _rgblink_completions() {
|
||||
fi
|
||||
|
||||
# Check if it's a long option
|
||||
if [[ "$word" = '--'* ]]; then
|
||||
if [[ "${word:0:2}" = '--' ]]; then
|
||||
# If the option is unknown, assume it takes no arguments: keep the state at "normal"
|
||||
for long_opt in "${opts[@]}"; do
|
||||
if [[ "$word" = "--${long_opt%%:*}" ]]; then
|
||||
@@ -82,7 +84,7 @@ _rgblink_completions() {
|
||||
fi
|
||||
done
|
||||
# Check if it's a short option
|
||||
elif [[ "$word" = '-'* ]]; then
|
||||
elif [[ "${word:0:1}" = '-' ]]; then
|
||||
parse_short_opt "$word"
|
||||
# The last option takes an argument...
|
||||
if [[ "$state" != 'normal' ]]; then
|
||||
@@ -99,25 +101,25 @@ _rgblink_completions() {
|
||||
|
||||
# Parse current word
|
||||
# Careful that it might look like an option, so use `--` aggressively!
|
||||
local cur_word="${COMP_WORDS[$i]}"
|
||||
local cur_word="${COMP_WORDS[$COMP_CWORD]}"
|
||||
|
||||
# Process options, as short ones may change the state
|
||||
if $opt_ena && [[ "$state" = 'normal' && "$cur_word" = '-'* ]]; then
|
||||
if $opt_ena && [[ "$state" = 'normal' && "${cur_word:0:1}" = '-' ]]; then
|
||||
# We might want to complete to an option or an arg to that option
|
||||
# Parse the option word to check
|
||||
# There's no whitespace in the option names, so we can ride a little dirty...
|
||||
|
||||
# Is this a long option?
|
||||
if [[ "$cur_word" = '--'* ]]; then
|
||||
if [[ "${cur_word:1:1}" = '-' ]]; then
|
||||
# It is, try to complete one
|
||||
mapfile -t COMPREPLY < <(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}")
|
||||
COMPREPLY+=( $(compgen -W "${opts[*]%%:*}" -P '--' -- "${cur_word#--}") )
|
||||
return 0
|
||||
else
|
||||
# Short options may be grouped, parse them to determine what to complete
|
||||
parse_short_opt "$cur_word"
|
||||
|
||||
if [[ "$state" = 'normal' ]]; then
|
||||
mapfile -t COMPREPLY < <(compgen -W "${!opts[*]}" -P "$cur_word" '')
|
||||
COMPREPLY+=( $(compgen -W "${!opts[*]}" -P "$cur_word" '') )
|
||||
return 0
|
||||
elif [[ "$optlen" = "${#cur_word}" && "$state" != "warning" ]]; then
|
||||
# This short option group only awaits its argument!
|
||||
@@ -125,13 +127,12 @@ _rgblink_completions() {
|
||||
# so that the next completion request switches to the argument
|
||||
# An exception is made for warnings, since it's idiomatic to stick them to the
|
||||
# `-W`, and it doesn't break anything.
|
||||
COMPREPLY=( "$cur_word" )
|
||||
COMPREPLY+=( "$cur_word" )
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
COMPREPLY=()
|
||||
case "$state" in
|
||||
unk) # Return with no replies: no idea what to complete!
|
||||
;;
|
||||
@@ -150,10 +151,6 @@ _rgblink_completions() {
|
||||
done < <(compgen -A directory -- "${cur_word:$optlen}")
|
||||
compopt -o filenames
|
||||
;;
|
||||
*)
|
||||
echo >&2 "Internal completion error: invalid state \"$state\", please report this bug"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright (c) 2021 Rangi
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
declare -A FILES
|
||||
while read -r -d '' file; do
|
||||
FILES["$file"]="true"
|
||||
done < <(git diff --name-only -z "$1" HEAD)
|
||||
done < <(git diff --name-only -z $1 HEAD)
|
||||
|
||||
edited () {
|
||||
${FILES["$1"]:-"false"}
|
||||
@@ -20,62 +40,46 @@ dependency () {
|
||||
# Pull requests that edit the first file without the second may be correct,
|
||||
# but are suspicious enough to require review.
|
||||
|
||||
dependency include/linkdefs.hpp man/rgbds.5 \
|
||||
dependency include/linkdefs.h src/rgbds.5 \
|
||||
"Was the object file format changed?"
|
||||
|
||||
dependency src/asm/parser.y man/rgbasm.5 \
|
||||
dependency src/asm/parser.y src/asm/rgbasm.5 \
|
||||
"Was the rgbasm grammar changed?"
|
||||
|
||||
dependency src/link/script.y man/rgblink.5 \
|
||||
"Was the linker script grammar changed?"
|
||||
|
||||
dependency include/asm/warning.hpp man/rgbasm.1 \
|
||||
dependency include/asm/warning.h src/asm/rgbasm.1 \
|
||||
"Were the rgbasm warnings changed?"
|
||||
|
||||
dependency src/asm/object.cpp include/linkdefs.hpp \
|
||||
dependency src/asm/object.c include/linkdefs.h \
|
||||
"Should the object file revision be bumped?"
|
||||
dependency src/link/object.cpp include/linkdefs.hpp \
|
||||
dependency src/link/object.c include/linkdefs.h \
|
||||
"Should the object file revision be bumped?"
|
||||
|
||||
dependency Makefile CMakeLists.txt \
|
||||
dependency Makefile CMakeLists.txt \
|
||||
"Did the build process change?"
|
||||
dependency Makefile src/CMakeLists.txt \
|
||||
dependency Makefile src/CMakeLists.txt \
|
||||
"Did the build process change?"
|
||||
|
||||
dependency src/asm/main.cpp man/rgbasm.1 \
|
||||
dependency src/asm/main.c src/asm/rgbasm.1 \
|
||||
"Did the rgbasm CLI change?"
|
||||
dependency src/asm/main.cpp contrib/zsh_compl/_rgbasm \
|
||||
dependency src/asm/main.c contrib/zsh_compl/_rgbasm \
|
||||
"Did the rgbasm CLI change?"
|
||||
dependency src/asm/main.cpp contrib/bash_compl/_rgbasm.bash \
|
||||
dependency src/asm/main.c contrib/bash_compl/_rgbasm.bash \
|
||||
"Did the rgbasm CLI change?"
|
||||
dependency src/link/main.cpp man/rgblink.1 \
|
||||
dependency src/link/main.c src/link/rgblink.1 \
|
||||
"Did the rgblink CLI change?"
|
||||
dependency src/link/main.cpp contrib/zsh_compl/_rgblink \
|
||||
dependency src/link/main.c contrib/zsh_compl/_rgblink \
|
||||
"Did the rgblink CLI change?"
|
||||
dependency src/link/main.cpp contrib/bash_compl/_rgblink.bash \
|
||||
dependency src/link/main.c contrib/bash_compl/_rgblink.bash \
|
||||
"Did the rgblink CLI change?"
|
||||
dependency src/fix/main.cpp man/rgbfix.1 \
|
||||
dependency src/fix/main.c src/fix/rgbfix.1 \
|
||||
"Did the rgbfix CLI change?"
|
||||
dependency src/fix/main.cpp contrib/zsh_compl/_rgbfix \
|
||||
dependency src/fix/main.c contrib/zsh_compl/_rgbfix \
|
||||
"Did the rgbfix CLI change?"
|
||||
dependency src/fix/main.cpp contrib/bash_compl/_rgbfix.bash \
|
||||
dependency src/fix/main.c contrib/bash_compl/_rgbfix.bash \
|
||||
"Did the rgbfix CLI change?"
|
||||
dependency src/gfx/main.cpp man/rgbgfx.1 \
|
||||
dependency src/gfx/main.c src/gfx/rgbgfx.1 \
|
||||
"Did the rgbgfx CLI change?"
|
||||
dependency src/gfx/main.cpp contrib/zsh_compl/_rgbgfx \
|
||||
dependency src/gfx/main.c contrib/zsh_compl/_rgbgfx \
|
||||
"Did the rgbgfx CLI change?"
|
||||
dependency src/gfx/main.cpp contrib/bash_compl/_rgbgfx.bash \
|
||||
dependency src/gfx/main.c contrib/bash_compl/_rgbgfx.bash \
|
||||
"Did the rgbgfx CLI change?"
|
||||
|
||||
dependency test/fetch-test-deps.sh CONTRIBUTING.md \
|
||||
"Did the test protocol change?"
|
||||
dependency test/run-tests.sh CONTRIBUTING.md \
|
||||
"Did the test protocol change?"
|
||||
dependency test/asm/test.sh CONTRIBUTING.md \
|
||||
"Did the RGBASM test protocol change?"
|
||||
dependency test/link/test.sh CONTRIBUTING.md \
|
||||
"Did the RGBLINK test protocol change?"
|
||||
dependency test/fix/test.sh CONTRIBUTING.md \
|
||||
"Did the RGBFIX test protocol change?"
|
||||
dependency test/gfx/test.sh CONTRIBUTING.md \
|
||||
"Did the RGBGFX test protocol change?"
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
# Build RGBDS with gcov support
|
||||
make coverage -j
|
||||
|
||||
# Run the tests
|
||||
pushd test
|
||||
./fetch-test-deps.sh
|
||||
./run-tests.sh
|
||||
popd
|
||||
|
||||
# Generate coverage logs
|
||||
gcov src/**/*.cpp
|
||||
mkdir -p coverage
|
||||
|
||||
# Generate coverage report
|
||||
lcov -c --no-external -d . -o coverage/coverage.info
|
||||
genhtml -f -s -o coverage/ coverage/coverage.info
|
||||
|
||||
# Open report in web browser
|
||||
if [ "$(uname)" == "Darwin" ]; then
|
||||
open coverage/index.html
|
||||
else
|
||||
xdg-open coverage/index.html
|
||||
fi
|
||||
@@ -1,53 +1,73 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Copyright (c) 2020 Eldred Habert
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
STATE=0
|
||||
diff <(xxd "$1") <(xxd "$2") | while read -r LINE; do
|
||||
if [[ $STATE -eq 0 ]]; then
|
||||
diff <(xxd $1) <(xxd $2) | while read -r LINE; do
|
||||
if [ $STATE -eq 0 ]; then
|
||||
# Discard first line (line info)
|
||||
STATE=1
|
||||
elif [[ "$LINE" = '---' ]]; then
|
||||
elif [ "$LINE" = '---' ]; then
|
||||
# Separator between files switches states
|
||||
echo "$LINE"
|
||||
echo $LINE
|
||||
STATE=3
|
||||
elif grep -Eq '^[0-9]+(,[0-9]+)?[cd][0-9]+(,[0-9]+)?' <<< "$LINE"; then
|
||||
# Line info resets the whole thing
|
||||
STATE=1
|
||||
elif [[ $STATE -eq 1 || $STATE -eq 3 ]]; then
|
||||
elif [ $STATE -eq 1 -o $STATE -eq 3 ]; then
|
||||
# Compute the GB address from the ROM offset
|
||||
OFS=$(cut -d ' ' -f 2 <<< "$LINE" | tr -d ':')
|
||||
BANK=$((0x$OFS / 0x4000))
|
||||
ADDR=$((0x$OFS % 0x4000 + (BANK != 0) * 0x4000))
|
||||
ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000))
|
||||
# Try finding the preceding symbol closest to the diff
|
||||
if [[ $STATE -eq 1 ]]; then
|
||||
if [ $STATE -eq 1 ]; then
|
||||
STATE=2
|
||||
SYMFILE=${1%.*}.sym
|
||||
else
|
||||
STATE=4
|
||||
SYMFILE=${2%.*}.sym
|
||||
fi
|
||||
EXTRA=$(if [[ -f "$SYMFILE" ]]; then
|
||||
EXTRA=$(if [ -f "$SYMFILE" ]; then
|
||||
# Read the sym file for such a symbol
|
||||
# Ignore comment lines, only pick matching bank
|
||||
# (The bank regex ignores comments already, make `cut` and `tr` process less lines)
|
||||
grep -Ei "$(printf "^%02x:" $BANK)" "$SYMFILE" |
|
||||
grep -Ei $(printf "^%02x:" $BANK) "$SYMFILE" |
|
||||
cut -d ';' -f 1 |
|
||||
tr -d "\r" |
|
||||
while read -r SYMADDR SYM; do
|
||||
SYMADDR=$((0x${SYMADDR#*:}))
|
||||
if [[ $SYMADDR -le $ADDR ]]; then
|
||||
printf " (%s+0x%x)\n" "$SYM" $((ADDR - SYMADDR))
|
||||
if [ $SYMADDR -le $ADDR ]; then
|
||||
printf " (%s+%#x)\n" "$SYM" $(($ADDR - $SYMADDR))
|
||||
fi
|
||||
# TODO: assumes sorted sym files
|
||||
done | tail -n 1
|
||||
fi)
|
||||
printf "%02x:%04x %s\n" $BANK $ADDR "$EXTRA"
|
||||
printf "%02x:%04x %s\n" $BANK $ADDR $EXTRA
|
||||
fi
|
||||
if [[ $STATE -eq 2 || $STATE -eq 4 ]]; then
|
||||
if [ $STATE -eq 2 -o $STATE -eq 4 ]; then
|
||||
OFS=$(cut -d ' ' -f 2 <<< "$LINE" | tr -d ':')
|
||||
BANK=$((0x$OFS / 0x4000))
|
||||
ADDR=$((0x$OFS % 0x4000 + (BANK != 0) * 0x4000))
|
||||
ADDR=$((0x$OFS % 0x4000 + ($BANK != 0) * 0x4000))
|
||||
printf "%s %02x:%04x: %s\n" "${LINE:0:1}" $BANK $ADDR "${LINE#*: }"
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -ne 2 ]]; then
|
||||
cat <<EOF >&2
|
||||
Usage: $0 <palettes.pal> <output.png>
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TMP=$(mktemp -d)
|
||||
readonly TMP
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
tile() { for i in {0..7}; do printf "$1"; done }
|
||||
{ tile '\x00\x00' && tile '\xFF\x00' && tile '\x00\xFF' && tile '\xFF\xFF'; } >"$TMP/tmp.2bpp"
|
||||
|
||||
NB_BYTES=$(wc -c <"$1")
|
||||
(( NB_PALS = NB_BYTES / 8 ))
|
||||
for (( i = 0; i < NB_PALS; i++ )); do
|
||||
printf '\0\1\2\3' >>"$TMP/tmp.tilemap"
|
||||
printf $(printf '\\x%x' $i{,,,}) >> "$TMP/tmp.palmap"
|
||||
done
|
||||
|
||||
"${RGBGFX:-${RGBDS+$RGBDS/}rgbgfx}" -r 4 "$2" -o "$TMP/tmp.2bpp" -OTQ -p "$1" -n "$NB_PALS"
|
||||
@@ -17,19 +17,18 @@ _rgbasm_warnings() {
|
||||
'empty-macro-arg:Warn on empty macro arg'
|
||||
'empty-strrpl:Warn on calling STRRPL with empty pattern'
|
||||
'large-constant:Warn on constants too large for a signed 32-bit int'
|
||||
'long-string:Warn on strings too long'
|
||||
'macro-shift:Warn when shifting macro args part their limits'
|
||||
'nested-comment:Warn on "/*" inside block comments'
|
||||
'numeric-string:Warn when a multi-character string is treated as a number'
|
||||
'obsolete:Warn when using deprecated features'
|
||||
'purge:Warn when purging exported symbols or labels'
|
||||
'shift:Warn when shifting negative values'
|
||||
'shift-amount:Warn when a shift'\''s operand it negative or \> 32'
|
||||
'truncation:Warn when implicit truncation loses bits'
|
||||
'unmapped-char:Warn on unmapped character'
|
||||
'user:Warn when executing the WARN built-in'
|
||||
)
|
||||
# TODO: handle `no-` and `error=` somehow?
|
||||
# TODO: handle `=0|1|2` levels for `numeric-string`, `purge`, `truncation`, and `unmapped-char`?
|
||||
# TODO: handle `=0|1|2` levels for `numeric-string` and `truncation`?
|
||||
_describe warning warnings
|
||||
}
|
||||
|
||||
@@ -38,26 +37,24 @@ local args=(
|
||||
'(- : * 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}'+[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}"+[Write deps in make format]:output file:_files -g '*.{d,mk}'"
|
||||
'(-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}'"
|
||||
-MG'[Assume missing files should be generated]'
|
||||
-MP'[Add phony targets to all deps]'
|
||||
'*'-MT"+[Add a target to the rules]:target:_files -g '*.{d,mk,o}'"
|
||||
'*'-MQ"+[Add a target to the rules]:target:_files -g '*.{d,mk,o}'"
|
||||
'(-o --output)'{-o,--output}'+[Output file]:output file:_files'
|
||||
'(-P --preinclude)'{-P,--preinclude}"+[Pre-include a file]:include file:_files -g '*.{asm,inc}'"
|
||||
'(-p --pad-value)'{-p,--pad-value}'+[Set padding byte]:padding byte:'
|
||||
'(-Q --q-precision)'{-Q,--q-precision}'+[Set fixed-point precision]:precision:'
|
||||
'(-r --recursion-depth)'{-r,--recursion-depth}'+[Set maximum recursion depth]:depth:'
|
||||
'(-s --state)'{-s,--state}"+[Write features of final state]:state file:_files -g '*.dump.asm'"
|
||||
'(-W --warning)'{-W,--warning}'+[Toggle warning flags]:warning flag:_rgbasm_warnings'
|
||||
'(-X --max-errors)'{-X,--max-errors}'+[Set maximum errors before aborting]:maximum errors:'
|
||||
|
||||
":assembly sources:_files -g '*.asm'"
|
||||
)
|
||||
|
||||
@@ -49,7 +49,6 @@ local args=(
|
||||
'(-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:'
|
||||
'(-L --logo)'{-L,--logo}'+[Set custom logo]:1bpp image:'
|
||||
'(-m --mbc-type)'{-m,--mbc-type}"+[Set MBC flags]:mbc name:_mbc_names"
|
||||
'(-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:'
|
||||
|
||||
@@ -13,33 +13,23 @@ 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 --auto-attr-map)'{-A,--auto-attr-map}'[Shortcut for -a <file>.attrmap]'
|
||||
'(-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]'
|
||||
'(-O --group-outputs)'{-O,--group-outputs}'[Base "shortcut" options on the output path, not input]'
|
||||
'(-p --palette -P --auto-palette)'{-P,--auto-palette}'[Shortcut for -p <file>.pal]'
|
||||
'(-q --palette-map -Q --auto-palette-map)'{-Q,--auto-palette-map}'[Shortcut for -p <file>.palmap]'
|
||||
'(-t --tilemap -T --auto-tilemap)'{-T,--auto-tilemap}'[Shortcut for -t <file>.tilemap]'
|
||||
'(-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}'[Enable verbose output]'
|
||||
'(-X --mirror-x)'{-X,--mirror-x}'[Eliminate horizontally mirrored tiles from output]'
|
||||
'(-Y --mirror-y)'{-Y,--mirror-y}'[Eliminate vertically mirrored tiles from output]'
|
||||
'(-Z --columns)'{-Z,--columns}'[Read the image in column-major order]'
|
||||
'(-v --verbose)'{-v,--verbose}'[Enable verbose output]'
|
||||
|
||||
'(-a --attr-map -A --auto-attr-map)'{-a,--attr-map}'+[Generate a map of tile attributes (mirroring)]:attrmap file:_files'
|
||||
'(-b --base-tiles)'{-b,--base-tiles}'+[Base tile IDs for tile map output]:base tile IDs:'
|
||||
'(-c --colors)'{-c,--colors}'+[Specify color palettes]:palette spec:'
|
||||
'(-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'
|
||||
'(-i --input-tileset)'{-i,--input-tileset}'+[Use specific tiles]:tileset file:_files -g "*.2bpp"'
|
||||
'(-L --slice)'{-L,--slice}'+[Only process a portion of the image]:input slice:'
|
||||
'(-N --nb-tiles)'{-N,--nb-tiles}'+[Limit number of tiles]:tile count:'
|
||||
'(-n --nb-palettes)'{-n,--nb-palettes}'+[Limit number of palettes]:palette count:'
|
||||
'(-o --output)'{-o,--output}'+[Set output file]:output file:_files'
|
||||
'(-p --palette -P --auto-palette)'{-p,--palette}"+[Output the image's palette in little-endian native RGB555 format]:palette file:_files"
|
||||
'(-q --palette-map -Q --auto-palette-map)'{-q,--palette-map}"+[Output the image's palette map]:palette map file:_files"
|
||||
'(-r --reverse)'{-r,--reverse}'+[Yield an image from binary data]:image width (in tiles):'
|
||||
'(-s --palette-size)'{-s,--palette-size}'+[Limit palette size]:palette size:'
|
||||
'(-t --tilemap -T --auto-tilemap)'{-t,--tilemap}'+[Generate a map of tile indices]:tilemap 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 file:_files -g '*.png'"
|
||||
|
||||
@@ -11,13 +11,13 @@ local args=(
|
||||
'(-x --nopad)'{-x,--nopad}'[Disable padding the end of the final file]'
|
||||
|
||||
'(-l --linkerscript)'{-l,--linkerscript}"+[Use a linker script]:linker script:_files -g '*.link'"
|
||||
'(-M --no-sym-in-map)'{-M,--no-sym-in-map}'[Do not output symbol names in map file]'
|
||||
'(-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 --scramble)'{-s,--scramble}'+[Activate scrambling]:scramble spec'
|
||||
'(-s --smart)'{-s,--smart}'+[!BROKEN! Perform smart linking from this symbol]:symbol name:'
|
||||
|
||||
'*'":object files:_files -g '*.o'"
|
||||
)
|
||||
|
||||
23
include/asm/charmap.h
Normal file
23
include/asm/charmap.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_CHARMAP_H
|
||||
#define RGBDS_ASM_CHARMAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct Charmap *charmap_New(char const *name, char const *baseName);
|
||||
void charmap_Delete(struct Charmap *charmap);
|
||||
void charmap_Set(char const *name);
|
||||
void charmap_Push(void);
|
||||
void charmap_Pop(void);
|
||||
void charmap_Add(char *mapping, uint8_t value);
|
||||
size_t charmap_Convert(char const *input, uint8_t *output);
|
||||
size_t charmap_ConvertNext(char const **input, uint8_t **output);
|
||||
|
||||
#endif /* RGBDS_ASM_CHARMAP_H */
|
||||
@@ -1,26 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_CHARMAP_HPP
|
||||
#define RGBDS_ASM_CHARMAP_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#define DEFAULT_CHARMAP_NAME "main"
|
||||
|
||||
bool charmap_ForEach(
|
||||
void (*mapFunc)(std::string const &),
|
||||
void (*charFunc)(std::string const &, std::vector<int32_t>)
|
||||
);
|
||||
void charmap_New(std::string const &name, std::string const *baseName);
|
||||
void charmap_Set(std::string const &name);
|
||||
void charmap_Push();
|
||||
void charmap_Pop();
|
||||
void charmap_Add(std::string const &mapping, std::vector<int32_t> &&value);
|
||||
bool charmap_HasChar(std::string const &input);
|
||||
std::vector<int32_t> charmap_Convert(std::string const &input);
|
||||
size_t charmap_ConvertNext(std::string_view &input, std::vector<int32_t> *output);
|
||||
|
||||
#endif // RGBDS_ASM_CHARMAP_HPP
|
||||
31
include/asm/fixpoint.h
Normal file
31
include/asm/fixpoint.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_FIXPOINT_H
|
||||
#define RGBDS_ASM_FIXPOINT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int32_t fix_Callback_PI(void);
|
||||
void fix_Print(int32_t i);
|
||||
int32_t fix_Sin(int32_t i);
|
||||
int32_t fix_Cos(int32_t i);
|
||||
int32_t fix_Tan(int32_t i);
|
||||
int32_t fix_ASin(int32_t i);
|
||||
int32_t fix_ACos(int32_t i);
|
||||
int32_t fix_ATan(int32_t i);
|
||||
int32_t fix_ATan2(int32_t i, int32_t j);
|
||||
int32_t fix_Mul(int32_t i, int32_t j);
|
||||
int32_t fix_Div(int32_t i, int32_t j);
|
||||
int32_t fix_Pow(int32_t i, int32_t j);
|
||||
int32_t fix_Log(int32_t i, int32_t j);
|
||||
int32_t fix_Round(int32_t i);
|
||||
int32_t fix_Ceil(int32_t i);
|
||||
int32_t fix_Floor(int32_t i);
|
||||
|
||||
#endif /* RGBDS_ASM_FIXPOINT_H */
|
||||
@@ -1,28 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_FIXPOINT_HPP
|
||||
#define RGBDS_ASM_FIXPOINT_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint8_t fixPrecision;
|
||||
|
||||
uint8_t fix_Precision();
|
||||
double fix_PrecisionFactor();
|
||||
int32_t fix_Sin(int32_t i, int32_t q);
|
||||
int32_t fix_Cos(int32_t i, int32_t q);
|
||||
int32_t fix_Tan(int32_t i, int32_t q);
|
||||
int32_t fix_ASin(int32_t i, int32_t q);
|
||||
int32_t fix_ACos(int32_t i, int32_t q);
|
||||
int32_t fix_ATan(int32_t i, int32_t q);
|
||||
int32_t fix_ATan2(int32_t i, int32_t j, int32_t q);
|
||||
int32_t fix_Mul(int32_t i, int32_t j, int32_t q);
|
||||
int32_t fix_Mod(int32_t i, int32_t j, int32_t q);
|
||||
int32_t fix_Div(int32_t i, int32_t j, int32_t q);
|
||||
int32_t fix_Pow(int32_t i, int32_t j, int32_t q);
|
||||
int32_t fix_Log(int32_t i, int32_t j, int32_t q);
|
||||
int32_t fix_Round(int32_t i, int32_t q);
|
||||
int32_t fix_Ceil(int32_t i, int32_t q);
|
||||
int32_t fix_Floor(int32_t i, int32_t q);
|
||||
|
||||
#endif // RGBDS_ASM_FIXPOINT_HPP
|
||||
63
include/asm/format.h
Normal file
63
include/asm/format.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2020, RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_FORMAT_SPEC_H
|
||||
#define RGBDS_FORMAT_SPEC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum FormatState {
|
||||
FORMAT_SIGN, // expects '+' or ' ' (optional)
|
||||
FORMAT_PREFIX, // expects '#' (optional)
|
||||
FORMAT_ALIGN, // expects '-' (optional)
|
||||
FORMAT_WIDTH, // expects '0'-'9', max 255 (optional) (leading '0' indicates pad)
|
||||
FORMAT_FRAC, // got '.', expects '0'-'9', max 255 (optional)
|
||||
FORMAT_DONE, // got [duXxbofs] (required)
|
||||
FORMAT_INVALID, // got unexpected character
|
||||
};
|
||||
|
||||
struct FormatSpec {
|
||||
enum FormatState state;
|
||||
int sign;
|
||||
bool prefix;
|
||||
bool alignLeft;
|
||||
bool padZero;
|
||||
size_t width;
|
||||
bool hasFrac;
|
||||
size_t fracWidth;
|
||||
int type;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
struct StrFmtArg {
|
||||
union {
|
||||
uint32_t number;
|
||||
char *string;
|
||||
};
|
||||
bool isNumeric;
|
||||
};
|
||||
|
||||
#define INITIAL_STRFMT_ARG_SIZE 4
|
||||
struct StrFmtArgList {
|
||||
char *format;
|
||||
size_t nbArgs;
|
||||
size_t capacity;
|
||||
struct StrFmtArg *args;
|
||||
};
|
||||
|
||||
struct FormatSpec fmt_NewSpec(void);
|
||||
bool fmt_IsEmpty(struct FormatSpec const *fmt);
|
||||
bool fmt_IsValid(struct FormatSpec const *fmt);
|
||||
bool fmt_IsFinished(struct FormatSpec const *fmt);
|
||||
void fmt_UseCharacter(struct FormatSpec *fmt, int c);
|
||||
void fmt_FinishCharacters(struct FormatSpec *fmt);
|
||||
void fmt_PrintString(char *buf, size_t bufLen, struct FormatSpec const *fmt, char const *value);
|
||||
void fmt_PrintNumber(char *buf, size_t bufLen, struct FormatSpec const *fmt, uint32_t value);
|
||||
|
||||
#endif /* RGBDS_FORMAT_SPEC_H */
|
||||
@@ -1,47 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_FORMAT_HPP
|
||||
#define RGBDS_ASM_FORMAT_HPP
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
enum FormatState {
|
||||
FORMAT_SIGN, // expects '+' or ' ' (optional)
|
||||
FORMAT_EXACT, // expects '#' (optional)
|
||||
FORMAT_ALIGN, // expects '-' (optional)
|
||||
FORMAT_WIDTH, // expects '0'-'9', max 255 (optional) (leading '0' indicates pad)
|
||||
FORMAT_FRAC, // got '.', expects '0'-'9', max 255 (optional)
|
||||
FORMAT_PREC, // got 'q', expects '0'-'9', range 1-31 (optional)
|
||||
FORMAT_DONE, // got [duXxbofs] (required)
|
||||
FORMAT_INVALID, // got unexpected character
|
||||
};
|
||||
|
||||
class FormatSpec {
|
||||
FormatState state;
|
||||
int sign;
|
||||
bool exact;
|
||||
bool alignLeft;
|
||||
bool padZero;
|
||||
size_t width;
|
||||
bool hasFrac;
|
||||
size_t fracWidth;
|
||||
bool hasPrec;
|
||||
size_t precision;
|
||||
int type;
|
||||
bool valid;
|
||||
|
||||
public:
|
||||
bool isEmpty() const { return !state; }
|
||||
bool isValid() const { return valid || state == FORMAT_DONE; }
|
||||
bool isFinished() const { return state >= FORMAT_DONE; }
|
||||
|
||||
void useCharacter(int c);
|
||||
void finishCharacters();
|
||||
|
||||
void appendString(std::string &str, std::string const &value) const;
|
||||
void appendNumber(std::string &str, uint32_t value) const;
|
||||
};
|
||||
|
||||
#endif // RGBDS_ASM_FORMAT_HPP
|
||||
83
include/asm/fstack.h
Normal file
83
include/asm/fstack.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
* Contains some assembler-wide defines and externs
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_FSTACK_H
|
||||
#define RGBDS_ASM_FSTACK_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "asm/lexer.h"
|
||||
|
||||
|
||||
struct FileStackNode {
|
||||
struct FileStackNode *parent; /* Pointer to parent node, for error reporting */
|
||||
/* Line at which the parent context was exited; meaningless for the root level */
|
||||
uint32_t lineNo;
|
||||
|
||||
struct FileStackNode *next; /* Next node in the output linked list */
|
||||
bool referenced; /* If referenced, don't free! */
|
||||
uint32_t ID; /* Set only if referenced: ID within the object file, -1 if not output yet */
|
||||
|
||||
enum {
|
||||
NODE_REPT,
|
||||
NODE_FILE,
|
||||
NODE_MACRO,
|
||||
} type;
|
||||
};
|
||||
|
||||
struct FileStackReptNode { /* NODE_REPT */
|
||||
struct FileStackNode node;
|
||||
uint32_t reptDepth;
|
||||
/* WARNING: if changing this type, change overflow check in `fstk_Init` */
|
||||
uint32_t iters[]; /* REPT iteration counts since last named node, in reverse depth order */
|
||||
};
|
||||
|
||||
struct FileStackNamedNode { /* NODE_FILE, NODE_MACRO */
|
||||
struct FileStackNode node;
|
||||
char name[]; /* File name for files, file::macro name for macros */
|
||||
};
|
||||
|
||||
extern size_t maxRecursionDepth;
|
||||
|
||||
struct MacroArgs;
|
||||
|
||||
void fstk_Dump(struct FileStackNode const *node, uint32_t lineNo);
|
||||
void fstk_DumpCurrent(void);
|
||||
struct FileStackNode *fstk_GetFileStack(void);
|
||||
/* The lifetime of the returned chars is until reaching the end of that file */
|
||||
char const *fstk_GetFileName(void);
|
||||
|
||||
void fstk_AddIncludePath(char const *s);
|
||||
/**
|
||||
* @param path The user-provided file name
|
||||
* @param fullPath The address of a pointer, which will be made to point at the full path
|
||||
* The pointer's value must be a valid argument to `realloc`, including NULL
|
||||
* @param size Current size of the buffer, or 0 if the pointer is NULL
|
||||
* @return True if the file was found, false if no path worked
|
||||
*/
|
||||
bool fstk_FindFile(char const *path, char **fullPath, size_t *size);
|
||||
|
||||
bool yywrap(void);
|
||||
void fstk_RunInclude(char const *path);
|
||||
void fstk_RunMacro(char const *macroName, struct MacroArgs *args);
|
||||
void fstk_RunRept(uint32_t count, int32_t reptLineNo, char *body, size_t size);
|
||||
void fstk_RunFor(char const *symName, int32_t start, int32_t stop, int32_t step,
|
||||
int32_t reptLineNo, char *body, size_t size);
|
||||
void fstk_StopRept(void);
|
||||
bool fstk_Break(void);
|
||||
|
||||
void fstk_NewRecursionDepth(size_t newDepth);
|
||||
void fstk_Init(char const *mainPath, size_t maxDepth);
|
||||
|
||||
#endif /* RGBDS_ASM_FSTACK_H */
|
||||
@@ -1,84 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
// Contains some assembler-wide defines and externs
|
||||
|
||||
#ifndef RGBDS_ASM_FSTACK_HPP
|
||||
#define RGBDS_ASM_FSTACK_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "either.hpp"
|
||||
#include "linkdefs.hpp"
|
||||
|
||||
#include "asm/lexer.hpp"
|
||||
|
||||
struct FileStackNode {
|
||||
FileStackNodeType type;
|
||||
Either<
|
||||
std::vector<uint32_t>, // NODE_REPT
|
||||
std::string // NODE_FILE, NODE_MACRO
|
||||
>
|
||||
data;
|
||||
|
||||
std::shared_ptr<FileStackNode> parent; // Pointer to parent node, for error reporting
|
||||
// Line at which the parent context was exited
|
||||
// Meaningless at the root level, but gets written to the object file anyway, so init it
|
||||
uint32_t lineNo = 0;
|
||||
|
||||
// Set only if referenced: ID within the object file, -1 if not output yet
|
||||
uint32_t ID = -1;
|
||||
|
||||
// REPT iteration counts since last named node, in reverse depth order
|
||||
std::vector<uint32_t> &iters() { return data.get<std::vector<uint32_t>>(); }
|
||||
std::vector<uint32_t> const &iters() const { return data.get<std::vector<uint32_t>>(); }
|
||||
// File name for files, file::macro name for macros
|
||||
std::string &name() { return data.get<std::string>(); }
|
||||
std::string const &name() const { return data.get<std::string>(); }
|
||||
|
||||
FileStackNode(FileStackNodeType type_, Either<std::vector<uint32_t>, std::string> data_)
|
||||
: type(type_), data(data_){};
|
||||
|
||||
std::string const &dump(uint32_t curLineNo) const;
|
||||
|
||||
// If true, entering this context generates a new unique ID.
|
||||
bool generatesUniqueID() const { return type == NODE_REPT || type == NODE_MACRO; }
|
||||
};
|
||||
|
||||
#define DEFAULT_MAX_DEPTH 64
|
||||
extern size_t maxRecursionDepth;
|
||||
|
||||
struct MacroArgs;
|
||||
|
||||
void fstk_DumpCurrent();
|
||||
std::shared_ptr<FileStackNode> fstk_GetFileStack();
|
||||
std::shared_ptr<std::string> fstk_GetUniqueIDStr();
|
||||
MacroArgs *fstk_GetCurrentMacroArgs();
|
||||
|
||||
void fstk_AddIncludePath(std::string const &path);
|
||||
void fstk_SetPreIncludeFile(std::string const &path);
|
||||
std::optional<std::string> fstk_FindFile(std::string const &path);
|
||||
|
||||
bool yywrap();
|
||||
void fstk_RunInclude(std::string const &path, bool updateStateNow);
|
||||
void fstk_RunMacro(std::string const ¯oName, std::shared_ptr<MacroArgs> macroArgs);
|
||||
void fstk_RunRept(uint32_t count, int32_t reptLineNo, ContentSpan const &span);
|
||||
void fstk_RunFor(
|
||||
std::string const &symName,
|
||||
int32_t start,
|
||||
int32_t stop,
|
||||
int32_t step,
|
||||
int32_t reptLineNo,
|
||||
ContentSpan const &span
|
||||
);
|
||||
void fstk_StopRept();
|
||||
bool fstk_Break();
|
||||
|
||||
void fstk_NewRecursionDepth(size_t newDepth);
|
||||
void fstk_Init(std::string const &mainPath, size_t maxDepth);
|
||||
|
||||
#endif // RGBDS_ASM_FSTACK_HPP
|
||||
102
include/asm/lexer.h
Normal file
102
include/asm/lexer.h
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_LEXER_H
|
||||
#define RGBDS_ASM_LEXER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAXSTRLEN 255
|
||||
|
||||
struct LexerState;
|
||||
extern struct LexerState *lexerState;
|
||||
extern struct LexerState *lexerStateEOL;
|
||||
|
||||
static inline struct LexerState *lexer_GetState(void)
|
||||
{
|
||||
return lexerState;
|
||||
}
|
||||
|
||||
static inline void lexer_SetState(struct LexerState *state)
|
||||
{
|
||||
lexerState = state;
|
||||
}
|
||||
|
||||
static inline void lexer_SetStateAtEOL(struct LexerState *state)
|
||||
{
|
||||
lexerStateEOL = state;
|
||||
}
|
||||
|
||||
extern char binDigits[2];
|
||||
extern char gfxDigits[4];
|
||||
|
||||
static inline void lexer_SetBinDigits(char const digits[2])
|
||||
{
|
||||
binDigits[0] = digits[0];
|
||||
binDigits[1] = digits[1];
|
||||
}
|
||||
|
||||
static inline void lexer_SetGfxDigits(char const digits[4])
|
||||
{
|
||||
gfxDigits[0] = digits[0];
|
||||
gfxDigits[1] = digits[1];
|
||||
gfxDigits[2] = digits[2];
|
||||
gfxDigits[3] = digits[3];
|
||||
}
|
||||
|
||||
/*
|
||||
* `path` is referenced, but not held onto..!
|
||||
*/
|
||||
struct LexerState *lexer_OpenFile(char const *path);
|
||||
struct LexerState *lexer_OpenFileView(char const *path, char *buf, size_t size, uint32_t lineNo);
|
||||
void lexer_RestartRept(uint32_t lineNo);
|
||||
void lexer_DeleteState(struct LexerState *state);
|
||||
void lexer_Init(void);
|
||||
|
||||
enum LexerMode {
|
||||
LEXER_NORMAL,
|
||||
LEXER_RAW,
|
||||
LEXER_SKIP_TO_ELIF,
|
||||
LEXER_SKIP_TO_ENDC,
|
||||
LEXER_SKIP_TO_ENDR
|
||||
};
|
||||
|
||||
void lexer_SetMode(enum LexerMode mode);
|
||||
void lexer_ToggleStringExpansion(bool enable);
|
||||
|
||||
uint32_t lexer_GetIFDepth(void);
|
||||
void lexer_IncIFDepth(void);
|
||||
void lexer_DecIFDepth(void);
|
||||
bool lexer_RanIFBlock(void);
|
||||
bool lexer_ReachedELSEBlock(void);
|
||||
void lexer_RunIFBlock(void);
|
||||
void lexer_ReachELSEBlock(void);
|
||||
|
||||
struct CaptureBody {
|
||||
uint32_t lineNo;
|
||||
char *body;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
void lexer_CheckRecursionDepth(void);
|
||||
char const *lexer_GetFileName(void);
|
||||
uint32_t lexer_GetLineNo(void);
|
||||
uint32_t lexer_GetColNo(void);
|
||||
void lexer_DumpStringExpansions(void);
|
||||
int yylex(void);
|
||||
bool lexer_CaptureRept(struct CaptureBody *capture);
|
||||
bool lexer_CaptureMacroBody(struct CaptureBody *capture);
|
||||
|
||||
#define INITIAL_DS_ARG_SIZE 2
|
||||
struct DsArgList {
|
||||
size_t nbArgs;
|
||||
size_t capacity;
|
||||
struct Expression *args;
|
||||
};
|
||||
|
||||
#endif /* RGBDS_ASM_LEXER_H */
|
||||
@@ -1,161 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_LEXER_HPP
|
||||
#define RGBDS_ASM_LEXER_HPP
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "either.hpp"
|
||||
#include "platform.hpp" // SSIZE_MAX
|
||||
|
||||
// This value is a compromise between `LexerState` allocation performance when `mmap` works, and
|
||||
// buffering performance when it doesn't/can't (e.g. when piping a file into RGBASM).
|
||||
#define LEXER_BUF_SIZE 64
|
||||
// The buffer needs to be large enough for the maximum `lexerState->peek()` lookahead distance
|
||||
static_assert(LEXER_BUF_SIZE > 1, "Lexer buffer size is too small");
|
||||
// This caps the size of buffer reads, and according to POSIX, passing more than SSIZE_MAX is UB
|
||||
static_assert(LEXER_BUF_SIZE <= SSIZE_MAX, "Lexer buffer size is too large");
|
||||
|
||||
enum LexerMode {
|
||||
LEXER_NORMAL,
|
||||
LEXER_RAW,
|
||||
LEXER_SKIP_TO_ELIF,
|
||||
LEXER_SKIP_TO_ENDC,
|
||||
LEXER_SKIP_TO_ENDR,
|
||||
NB_LEXER_MODES
|
||||
};
|
||||
|
||||
struct Expansion {
|
||||
std::optional<std::string> name;
|
||||
std::shared_ptr<std::string> contents;
|
||||
size_t offset; // Cursor into `contents`
|
||||
|
||||
size_t size() const { return contents->size(); }
|
||||
bool advance(); // Increment `offset`; return whether it then exceeds `contents`
|
||||
};
|
||||
|
||||
struct ContentSpan {
|
||||
std::shared_ptr<char[]> ptr;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct ViewedContent {
|
||||
ContentSpan span; // Span of chars
|
||||
size_t offset = 0; // Cursor into `span.ptr`
|
||||
|
||||
ViewedContent(ContentSpan const &span_) : span(span_) {}
|
||||
ViewedContent(std::shared_ptr<char[]> ptr, size_t size) : span({.ptr = ptr, .size = size}) {}
|
||||
|
||||
std::shared_ptr<char[]> makeSharedContentPtr() const {
|
||||
return std::shared_ptr<char[]>(span.ptr, &span.ptr[offset]);
|
||||
}
|
||||
};
|
||||
|
||||
struct BufferedContent {
|
||||
int fd; // File from which to read chars
|
||||
char buf[LEXER_BUF_SIZE] = {}; // Circular buffer of chars
|
||||
size_t offset = 0; // Cursor into `buf`
|
||||
size_t size = 0; // Number of "fresh" chars in `buf`
|
||||
|
||||
BufferedContent(int fd_) : fd(fd_) {}
|
||||
~BufferedContent();
|
||||
|
||||
void advance(); // Increment `offset` circularly, decrement `size`
|
||||
void refill(); // Read from `fd` to fill `buf`
|
||||
|
||||
private:
|
||||
size_t readMore(size_t startIndex, size_t nbChars);
|
||||
};
|
||||
|
||||
struct IfStackEntry {
|
||||
bool ranIfBlock; // Whether an IF/ELIF/ELSE block ran already
|
||||
bool reachedElseBlock; // Whether an ELSE block ran already
|
||||
};
|
||||
|
||||
struct LexerState {
|
||||
std::string path;
|
||||
|
||||
LexerMode mode;
|
||||
bool atLineStart;
|
||||
uint32_t lineNo;
|
||||
uint32_t colNo;
|
||||
int lastToken;
|
||||
|
||||
std::deque<IfStackEntry> ifStack;
|
||||
|
||||
bool capturing; // Whether the text being lexed should be captured
|
||||
size_t captureSize; // Amount of text captured
|
||||
std::shared_ptr<std::vector<char>> captureBuf; // Buffer to send the captured text to if set
|
||||
|
||||
bool disableMacroArgs;
|
||||
bool disableInterpolation;
|
||||
size_t macroArgScanDistance; // Max distance already scanned for macro args
|
||||
bool expandStrings;
|
||||
std::deque<Expansion> expansions; // Front is the innermost current expansion
|
||||
|
||||
Either<ViewedContent, BufferedContent> content;
|
||||
|
||||
~LexerState();
|
||||
|
||||
int peekChar();
|
||||
int peekCharAhead();
|
||||
|
||||
std::shared_ptr<char[]> makeSharedCaptureBufPtr() const {
|
||||
return std::shared_ptr<char[]>(captureBuf, captureBuf->data());
|
||||
}
|
||||
|
||||
void setAsCurrentState();
|
||||
bool setFileAsNextState(std::string const &filePath, bool updateStateNow);
|
||||
void setViewAsNextState(char const *name, ContentSpan const &span, uint32_t lineNo_);
|
||||
|
||||
void clear(uint32_t lineNo_);
|
||||
};
|
||||
|
||||
extern char binDigits[2];
|
||||
extern char gfxDigits[4];
|
||||
|
||||
static inline void lexer_SetBinDigits(char const digits[2]) {
|
||||
binDigits[0] = digits[0];
|
||||
binDigits[1] = digits[1];
|
||||
}
|
||||
|
||||
static inline void lexer_SetGfxDigits(char const digits[4]) {
|
||||
gfxDigits[0] = digits[0];
|
||||
gfxDigits[1] = digits[1];
|
||||
gfxDigits[2] = digits[2];
|
||||
gfxDigits[3] = digits[3];
|
||||
}
|
||||
|
||||
bool lexer_AtTopLevel();
|
||||
void lexer_RestartRept(uint32_t lineNo);
|
||||
void lexer_Init();
|
||||
void lexer_SetMode(LexerMode mode);
|
||||
void lexer_ToggleStringExpansion(bool enable);
|
||||
|
||||
uint32_t lexer_GetIFDepth();
|
||||
void lexer_IncIFDepth();
|
||||
void lexer_DecIFDepth();
|
||||
bool lexer_RanIFBlock();
|
||||
bool lexer_ReachedELSEBlock();
|
||||
void lexer_RunIFBlock();
|
||||
void lexer_ReachELSEBlock();
|
||||
|
||||
void lexer_CheckRecursionDepth();
|
||||
uint32_t lexer_GetLineNo();
|
||||
uint32_t lexer_GetColNo();
|
||||
void lexer_DumpStringExpansions();
|
||||
|
||||
struct Capture {
|
||||
uint32_t lineNo;
|
||||
ContentSpan span;
|
||||
};
|
||||
|
||||
Capture lexer_CaptureRept();
|
||||
Capture lexer_CaptureMacro();
|
||||
|
||||
#endif // RGBDS_ASM_LEXER_HPP
|
||||
37
include/asm/macro.h
Normal file
37
include/asm/macro.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2020, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_MACRO_H
|
||||
#define RGBDS_MACRO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "asm/warning.h"
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
struct MacroArgs;
|
||||
|
||||
struct MacroArgs *macro_GetCurrentArgs(void);
|
||||
struct MacroArgs *macro_NewArgs(void);
|
||||
void macro_AppendArg(struct MacroArgs **args, char *s);
|
||||
void macro_UseNewArgs(struct MacroArgs *args);
|
||||
void macro_FreeArgs(struct MacroArgs *args);
|
||||
char const *macro_GetArg(uint32_t i);
|
||||
char const *macro_GetAllArgs(void);
|
||||
|
||||
uint32_t macro_GetUniqueID(void);
|
||||
char const *macro_GetUniqueIDStr(void);
|
||||
void macro_SetUniqueID(uint32_t id);
|
||||
uint32_t macro_UseNewUniqueID(void);
|
||||
void macro_ShiftCurrentArgs(int32_t count);
|
||||
uint32_t macro_NbArgs(void);
|
||||
|
||||
#endif
|
||||
@@ -1,23 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_MACRO_HPP
|
||||
#define RGBDS_ASM_MACRO_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct MacroArgs {
|
||||
unsigned int shift;
|
||||
std::vector<std::shared_ptr<std::string>> args;
|
||||
|
||||
uint32_t nbArgs() const { return args.size() - shift; }
|
||||
std::shared_ptr<std::string> getArg(uint32_t i) const;
|
||||
std::shared_ptr<std::string> getAllArgs() const;
|
||||
|
||||
void appendArg(std::shared_ptr<std::string> arg);
|
||||
void shiftArgs(int32_t count);
|
||||
};
|
||||
|
||||
#endif // RGBDS_ASM_MACRO_HPP
|
||||
29
include/asm/main.h
Normal file
29
include/asm/main.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2021, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_MAIN_H
|
||||
#define RGBDS_MAIN_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
extern bool haltnop;
|
||||
extern bool optimizeLoads;
|
||||
extern bool verbose;
|
||||
extern bool warnings; /* True to enable warnings, false to disable them. */
|
||||
|
||||
extern FILE *dependfile;
|
||||
extern char *targetFileName;
|
||||
extern bool generatedMissingIncludes;
|
||||
extern bool failedOnMissingInclude;
|
||||
extern bool generatePhonyDeps;
|
||||
|
||||
#endif /* RGBDS_MAIN_H */
|
||||
@@ -1,18 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_MAIN_HPP
|
||||
#define RGBDS_ASM_MAIN_HPP
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
extern bool verbose;
|
||||
extern bool warnings; // True to enable warnings, false to disable them.
|
||||
|
||||
extern FILE *dependFile;
|
||||
extern std::string targetFileName;
|
||||
extern bool generatedMissingIncludes;
|
||||
extern bool failedOnMissingInclude;
|
||||
extern bool generatePhonyDeps;
|
||||
|
||||
#endif // RGBDS_ASM_MAIN_HPP
|
||||
25
include/asm/opt.h
Normal file
25
include/asm/opt.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2021, Eldred Habert and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_OPT_H
|
||||
#define RGBDS_OPT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void opt_B(char const chars[2]);
|
||||
void opt_G(char const chars[4]);
|
||||
void opt_P(uint8_t fill);
|
||||
void opt_L(bool optimize);
|
||||
void opt_W(char const *flag);
|
||||
void opt_Parse(char const *option);
|
||||
|
||||
void opt_Push(void);
|
||||
void opt_Pop(void);
|
||||
|
||||
#endif
|
||||
@@ -1,18 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_OPT_HPP
|
||||
#define RGBDS_ASM_OPT_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void opt_B(char const chars[2]);
|
||||
void opt_G(char const chars[4]);
|
||||
void opt_P(uint8_t padByte);
|
||||
void opt_Q(uint8_t precision);
|
||||
void opt_W(char const *flag);
|
||||
void opt_Parse(char const *option);
|
||||
|
||||
void opt_Push();
|
||||
void opt_Pop();
|
||||
|
||||
#endif // RGBDS_ASM_OPT_HPP
|
||||
30
include/asm/output.h
Normal file
30
include/asm/output.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_OUTPUT_H
|
||||
#define RGBDS_ASM_OUTPUT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "linkdefs.h"
|
||||
|
||||
struct Expression;
|
||||
struct FileStackNode;
|
||||
|
||||
extern char *objectName;
|
||||
extern struct Section *sectionList;
|
||||
|
||||
void out_RegisterNode(struct FileStackNode *node);
|
||||
void out_ReplaceNode(struct FileStackNode *node);
|
||||
void out_SetFileName(char *s);
|
||||
void out_CreatePatch(uint32_t type, struct Expression const *expr, uint32_t ofs, uint32_t pcShift);
|
||||
bool out_CreateAssert(enum AssertionType type, struct Expression const *expr,
|
||||
char const *message, uint32_t ofs);
|
||||
void out_WriteObject(void);
|
||||
|
||||
#endif /* RGBDS_ASM_OUTPUT_H */
|
||||
@@ -1,37 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_OUTPUT_HPP
|
||||
#define RGBDS_ASM_OUTPUT_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "linkdefs.hpp"
|
||||
|
||||
struct Expression;
|
||||
struct FileStackNode;
|
||||
|
||||
enum StateFeature {
|
||||
STATE_EQU,
|
||||
STATE_VAR,
|
||||
STATE_EQUS,
|
||||
STATE_CHAR,
|
||||
STATE_MACRO,
|
||||
NB_STATE_FEATURES
|
||||
};
|
||||
|
||||
extern std::string objectFileName;
|
||||
|
||||
void out_RegisterNode(std::shared_ptr<FileStackNode> node);
|
||||
void out_SetFileName(std::string const &name);
|
||||
void out_CreatePatch(uint32_t type, Expression const &expr, uint32_t ofs, uint32_t pcShift);
|
||||
void out_CreateAssert(
|
||||
AssertionType type, Expression const &expr, std::string const &message, uint32_t ofs
|
||||
);
|
||||
void out_WriteObject();
|
||||
void out_WriteState(std::string name, std::vector<StateFeature> const &features);
|
||||
|
||||
#endif // RGBDS_ASM_OUTPUT_HPP
|
||||
70
include/asm/rpn.h
Normal file
70
include/asm/rpn.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2018, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ASM_RPN_H
|
||||
#define RGBDS_ASM_RPN_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "linkdefs.h"
|
||||
|
||||
#define MAXRPNLEN 1048576
|
||||
|
||||
struct Expression {
|
||||
int32_t val; // If the expression's value is known, it's here
|
||||
char *reason; // Why the expression is not known, if it isn't
|
||||
bool isKnown; // Whether the expression's value is known
|
||||
bool isSymbol; // Whether the expression represents a symbol
|
||||
uint8_t *rpn; // Array of bytes serializing the RPN expression
|
||||
uint32_t rpnCapacity; // Size of the `rpn` buffer
|
||||
uint32_t rpnLength; // Used size of the `rpn` buffer
|
||||
uint32_t rpnPatchSize; // Size the expression will take in the object file
|
||||
};
|
||||
|
||||
/*
|
||||
* Determines if an expression is known at assembly time
|
||||
*/
|
||||
static inline bool rpn_isKnown(struct Expression const *expr)
|
||||
{
|
||||
return expr->isKnown;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determines if an expression is a symbol suitable for const diffing
|
||||
*/
|
||||
static inline bool rpn_isSymbol(const struct Expression *expr)
|
||||
{
|
||||
return expr->isSymbol;
|
||||
}
|
||||
|
||||
void rpn_Symbol(struct Expression *expr, char const *symName);
|
||||
void rpn_Number(struct Expression *expr, uint32_t i);
|
||||
void rpn_LOGNOT(struct Expression *expr, const struct Expression *src);
|
||||
struct Symbol const *rpn_SymbolOf(struct Expression const *expr);
|
||||
bool rpn_IsDiffConstant(struct Expression const *src, struct Symbol const *symName);
|
||||
void rpn_BinaryOp(enum RPNCommand op, struct Expression *expr,
|
||||
const struct Expression *src1,
|
||||
const struct Expression *src2);
|
||||
void rpn_HIGH(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_LOW(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_ISCONST(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_UNNEG(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_UNNOT(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_BankSymbol(struct Expression *expr, char const *symName);
|
||||
void rpn_BankSection(struct Expression *expr, char const *sectionName);
|
||||
void rpn_BankSelf(struct Expression *expr);
|
||||
void rpn_SizeOfSection(struct Expression *expr, char const *sectionName);
|
||||
void rpn_StartOfSection(struct Expression *expr, char const *sectionName);
|
||||
void rpn_Free(struct Expression *expr);
|
||||
void rpn_CheckHRAM(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_CheckRST(struct Expression *expr, const struct Expression *src);
|
||||
void rpn_CheckNBit(struct Expression const *expr, uint8_t n);
|
||||
int32_t rpn_GetConstVal(struct Expression const *expr);
|
||||
|
||||
#endif /* RGBDS_ASM_RPN_H */
|
||||
@@ -1,69 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_RPN_HPP
|
||||
#define RGBDS_ASM_RPN_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "either.hpp"
|
||||
#include "linkdefs.hpp"
|
||||
|
||||
struct Symbol;
|
||||
|
||||
struct Expression {
|
||||
Either<
|
||||
int32_t, // If the expression's value is known, it's here
|
||||
std::string // Why the expression is not known, if it isn't
|
||||
>
|
||||
data = 0;
|
||||
bool isSymbol = false; // Whether the expression represents a symbol suitable for const diffing
|
||||
std::vector<uint8_t> rpn{}; // Bytes serializing the RPN expression
|
||||
uint32_t rpnPatchSize = 0; // Size the expression will take in the object file
|
||||
|
||||
Expression() = default;
|
||||
Expression(Expression &&) = default;
|
||||
#ifdef _MSC_VER
|
||||
// MSVC and WinFlexBison won't build without this...
|
||||
Expression(Expression const &) = default;
|
||||
#endif
|
||||
|
||||
Expression &operator=(Expression &&) = default;
|
||||
|
||||
bool isKnown() const {
|
||||
return data.holds<int32_t>();
|
||||
}
|
||||
int32_t value() const {
|
||||
return data.get<int32_t>();
|
||||
}
|
||||
|
||||
int32_t getConstVal() const;
|
||||
Symbol const *symbolOf() const;
|
||||
bool isDiffConstant(Symbol const *symName) const;
|
||||
|
||||
void makeNumber(uint32_t value);
|
||||
void makeSymbol(std::string const &symName);
|
||||
void makeBankSymbol(std::string const &symName);
|
||||
void makeBankSection(std::string const §Name);
|
||||
void makeSizeOfSection(std::string const §Name);
|
||||
void makeStartOfSection(std::string const §Name);
|
||||
void makeSizeOfSectionType(SectionType type);
|
||||
void makeStartOfSectionType(SectionType type);
|
||||
void makeUnaryOp(RPNCommand op, Expression &&src);
|
||||
void makeBinaryOp(RPNCommand op, Expression &&src1, Expression const &src2);
|
||||
|
||||
void makeCheckHRAM();
|
||||
void makeCheckRST();
|
||||
|
||||
void checkNBit(uint8_t n) const;
|
||||
|
||||
private:
|
||||
void clear();
|
||||
uint8_t *reserveSpace(uint32_t size);
|
||||
uint8_t *reserveSpace(uint32_t size, uint32_t patchSize);
|
||||
};
|
||||
|
||||
bool checkNBit(int32_t v, uint8_t n, char const *name);
|
||||
|
||||
#endif // RGBDS_ASM_RPN_HPP
|
||||
82
include/asm/section.h
Normal file
82
include/asm/section.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2020, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_SECTION_H
|
||||
#define RGBDS_SECTION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "linkdefs.h"
|
||||
#include "platform.h" // NONNULL
|
||||
|
||||
extern uint8_t fillByte;
|
||||
|
||||
struct Expression;
|
||||
|
||||
struct Section {
|
||||
char *name;
|
||||
enum SectionType type;
|
||||
enum SectionModifier modifier;
|
||||
struct FileStackNode *src; /* Where the section was defined */
|
||||
uint32_t fileLine; /* Line where the section was defined */
|
||||
uint32_t size;
|
||||
uint32_t org;
|
||||
uint32_t bank;
|
||||
uint8_t align; // Exactly as specified in `ALIGN[]`
|
||||
uint16_t alignOfs;
|
||||
struct Section *next;
|
||||
struct Patch *patches;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
struct SectionSpec {
|
||||
uint32_t bank;
|
||||
uint8_t alignment;
|
||||
uint16_t alignOfs;
|
||||
};
|
||||
|
||||
extern struct Section *currentSection;
|
||||
|
||||
struct Section *sect_FindSectionByName(char const *name);
|
||||
void sect_NewSection(char const *name, uint32_t secttype, uint32_t org,
|
||||
struct SectionSpec const *attributes, enum SectionModifier mod);
|
||||
void sect_SetLoadSection(char const *name, uint32_t secttype, uint32_t org,
|
||||
struct SectionSpec const *attributes, enum SectionModifier mod);
|
||||
void sect_EndLoadSection(void);
|
||||
|
||||
struct Section *sect_GetSymbolSection(void);
|
||||
uint32_t sect_GetSymbolOffset(void);
|
||||
uint32_t sect_GetOutputOffset(void);
|
||||
void sect_AlignPC(uint8_t alignment, uint16_t offset);
|
||||
|
||||
void sect_StartUnion(void);
|
||||
void sect_NextUnionMember(void);
|
||||
void sect_EndUnion(void);
|
||||
void sect_CheckUnionClosed(void);
|
||||
|
||||
void sect_AbsByte(uint8_t b);
|
||||
void sect_AbsByteGroup(uint8_t const *s, size_t length);
|
||||
void sect_AbsWordGroup(uint8_t const *s, size_t length);
|
||||
void sect_AbsLongGroup(uint8_t const *s, size_t length);
|
||||
void sect_Skip(uint32_t skip, bool ds);
|
||||
void sect_String(char const *s);
|
||||
void sect_RelByte(struct Expression *expr, uint32_t pcShift);
|
||||
void sect_RelBytes(uint32_t n, struct Expression *exprs, size_t size);
|
||||
void sect_RelWord(struct Expression *expr, uint32_t pcShift);
|
||||
void sect_RelLong(struct Expression *expr, uint32_t pcShift);
|
||||
void sect_PCRelByte(struct Expression *expr, uint32_t pcShift);
|
||||
void sect_BinaryFile(char const *s, int32_t startPos);
|
||||
void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
|
||||
|
||||
void sect_PushSection(void);
|
||||
void sect_PopSection(void);
|
||||
|
||||
bool sect_IsSizeKnown(struct Section const NONNULL(name));
|
||||
|
||||
#endif
|
||||
@@ -1,105 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_SECTION_HPP
|
||||
#define RGBDS_ASM_SECTION_HPP
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "linkdefs.hpp"
|
||||
|
||||
extern uint8_t fillByte;
|
||||
|
||||
struct Expression;
|
||||
struct FileStackNode;
|
||||
struct Section;
|
||||
|
||||
struct Patch {
|
||||
std::shared_ptr<FileStackNode> src;
|
||||
uint32_t lineNo;
|
||||
uint32_t offset;
|
||||
Section *pcSection;
|
||||
uint32_t pcOffset;
|
||||
uint8_t type;
|
||||
std::vector<uint8_t> rpn;
|
||||
};
|
||||
|
||||
struct Section {
|
||||
std::string name;
|
||||
SectionType type;
|
||||
SectionModifier modifier;
|
||||
std::shared_ptr<FileStackNode> src; // Where the section was defined
|
||||
uint32_t fileLine; // Line where the section was defined
|
||||
uint32_t size;
|
||||
uint32_t org;
|
||||
uint32_t bank;
|
||||
uint8_t align; // Exactly as specified in `ALIGN[]`
|
||||
uint16_t alignOfs;
|
||||
std::deque<Patch> patches;
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
bool isSizeKnown() const;
|
||||
};
|
||||
|
||||
struct SectionSpec {
|
||||
uint32_t bank;
|
||||
uint8_t alignment;
|
||||
uint16_t alignOfs;
|
||||
};
|
||||
|
||||
extern std::deque<Section> sectionList;
|
||||
extern std::unordered_map<std::string, size_t> sectionMap; // Indexes into `sectionList`
|
||||
extern Section *currentSection;
|
||||
|
||||
Section *sect_FindSectionByName(std::string const &name);
|
||||
void sect_NewSection(
|
||||
std::string const &name,
|
||||
SectionType type,
|
||||
uint32_t org,
|
||||
SectionSpec const &attrs,
|
||||
SectionModifier mod
|
||||
);
|
||||
void sect_SetLoadSection(
|
||||
std::string const &name,
|
||||
SectionType type,
|
||||
uint32_t org,
|
||||
SectionSpec const &attrs,
|
||||
SectionModifier mod
|
||||
);
|
||||
void sect_EndLoadSection();
|
||||
|
||||
Section *sect_GetSymbolSection();
|
||||
uint32_t sect_GetSymbolOffset();
|
||||
uint32_t sect_GetOutputOffset();
|
||||
uint32_t sect_GetAlignBytes(uint8_t alignment, uint16_t offset);
|
||||
void sect_AlignPC(uint8_t alignment, uint16_t offset);
|
||||
|
||||
void sect_CheckSizes();
|
||||
|
||||
void sect_StartUnion();
|
||||
void sect_NextUnionMember();
|
||||
void sect_EndUnion();
|
||||
void sect_CheckUnionClosed();
|
||||
|
||||
void sect_ConstByte(uint8_t byte);
|
||||
void sect_ByteString(std::vector<int32_t> const &string);
|
||||
void sect_WordString(std::vector<int32_t> const &string);
|
||||
void sect_LongString(std::vector<int32_t> const &string);
|
||||
void sect_Skip(uint32_t skip, bool ds);
|
||||
void sect_RelByte(Expression &expr, uint32_t pcShift);
|
||||
void sect_RelBytes(uint32_t n, std::vector<Expression> &exprs);
|
||||
void sect_RelWord(Expression &expr, uint32_t pcShift);
|
||||
void sect_RelLong(Expression &expr, uint32_t pcShift);
|
||||
void sect_PCRelByte(Expression &expr, uint32_t pcShift);
|
||||
void sect_BinaryFile(std::string const &name, int32_t startPos);
|
||||
void sect_BinaryFileSlice(std::string const &name, int32_t startPos, int32_t length);
|
||||
|
||||
void sect_EndSection();
|
||||
void sect_PushSection();
|
||||
void sect_PopSection();
|
||||
|
||||
#endif // RGBDS_ASM_SECTION_HPP
|
||||
150
include/asm/symbol.h
Normal file
150
include/asm/symbol.h
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2020, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_SYMBOL_H
|
||||
#define RGBDS_SYMBOL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "asm/section.h"
|
||||
|
||||
#include "platform.h" // MIN_NB_ELMS
|
||||
|
||||
#define MAXSYMLEN 255
|
||||
|
||||
enum SymbolType {
|
||||
SYM_LABEL,
|
||||
SYM_EQU,
|
||||
SYM_VAR,
|
||||
SYM_MACRO,
|
||||
SYM_EQUS,
|
||||
SYM_REF // Forward reference to a label
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
char name[MAXSYMLEN + 1];
|
||||
enum SymbolType type;
|
||||
bool isExported; /* Whether the symbol is to be exported */
|
||||
bool isBuiltin; /* Whether the symbol is a built-in */
|
||||
struct Section *section;
|
||||
struct FileStackNode *src; /* Where the symbol was defined */
|
||||
uint32_t fileLine; /* Line where the symbol was defined */
|
||||
|
||||
bool hasCallback;
|
||||
union {
|
||||
/* If sym_IsNumeric */
|
||||
int32_t value;
|
||||
int32_t (*numCallback)(void);
|
||||
/* For SYM_MACRO and SYM_EQUS; TODO: have separate fields */
|
||||
struct {
|
||||
size_t macroSize;
|
||||
char *macro;
|
||||
};
|
||||
/* For SYM_EQUS */
|
||||
char const *(*strCallback)(void);
|
||||
};
|
||||
|
||||
uint32_t ID; /* ID of the symbol in the object file (-1 if none) */
|
||||
struct Symbol *next; /* Next object to output in the object file */
|
||||
};
|
||||
|
||||
bool sym_IsPC(struct Symbol const *sym);
|
||||
|
||||
static inline bool sym_IsDefined(struct Symbol const *sym)
|
||||
{
|
||||
return sym->type != SYM_REF;
|
||||
}
|
||||
|
||||
static inline struct Section *sym_GetSection(struct Symbol const *sym)
|
||||
{
|
||||
return sym_IsPC(sym) ? sect_GetSymbolSection() : sym->section;
|
||||
}
|
||||
|
||||
static inline bool sym_IsConstant(struct Symbol const *sym)
|
||||
{
|
||||
if (sym->type == SYM_LABEL) {
|
||||
struct Section const *sect = sym_GetSection(sym);
|
||||
|
||||
return sect && sect->org != (uint32_t)-1;
|
||||
}
|
||||
return sym->type == SYM_EQU || sym->type == SYM_VAR;
|
||||
}
|
||||
|
||||
static inline bool sym_IsNumeric(struct Symbol const *sym)
|
||||
{
|
||||
return sym->type == SYM_LABEL || sym->type == SYM_EQU || sym->type == SYM_VAR;
|
||||
}
|
||||
|
||||
static inline bool sym_IsLabel(struct Symbol const *sym)
|
||||
{
|
||||
return sym->type == SYM_LABEL || sym->type == SYM_REF;
|
||||
}
|
||||
|
||||
static inline bool sym_IsLocal(struct Symbol const *sym)
|
||||
{
|
||||
return sym_IsLabel(sym) && strchr(sym->name, '.');
|
||||
}
|
||||
|
||||
static inline bool sym_IsExported(struct Symbol const *sym)
|
||||
{
|
||||
return sym->isExported;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a string equate's value
|
||||
*/
|
||||
static inline char const *sym_GetStringValue(struct Symbol const *sym)
|
||||
{
|
||||
if (sym->hasCallback)
|
||||
return sym->strCallback();
|
||||
return sym->macro;
|
||||
}
|
||||
|
||||
void sym_ForEach(void (*func)(struct Symbol *, void *), void *arg);
|
||||
|
||||
int32_t sym_GetValue(struct Symbol const *sym);
|
||||
void sym_SetExportAll(bool set);
|
||||
struct Symbol *sym_AddLocalLabel(char const *symName);
|
||||
struct Symbol *sym_AddLabel(char const *symName);
|
||||
struct Symbol *sym_AddAnonLabel(void);
|
||||
void sym_WriteAnonLabelName(char buf[MIN_NB_ELMS(MAXSYMLEN + 1)], uint32_t ofs, bool neg);
|
||||
void sym_Export(char const *symName);
|
||||
struct Symbol *sym_AddEqu(char const *symName, int32_t value);
|
||||
struct Symbol *sym_RedefEqu(char const *symName, int32_t value);
|
||||
struct Symbol *sym_AddVar(char const *symName, int32_t value);
|
||||
uint32_t sym_GetPCValue(void);
|
||||
uint32_t sym_GetConstantSymValue(struct Symbol const *sym);
|
||||
uint32_t sym_GetConstantValue(char const *symName);
|
||||
/*
|
||||
* Find a symbol by exact name, bypassing expansion checks
|
||||
*/
|
||||
struct Symbol *sym_FindExactSymbol(char const *symName);
|
||||
/*
|
||||
* Find a symbol by exact name; may not be scoped, produces an error if it is
|
||||
*/
|
||||
struct Symbol *sym_FindUnscopedSymbol(char const *symName);
|
||||
/*
|
||||
* Find a symbol, possibly scoped, by name
|
||||
*/
|
||||
struct Symbol *sym_FindScopedSymbol(char const *symName);
|
||||
struct Symbol const *sym_GetPC(void);
|
||||
struct Symbol *sym_AddMacro(char const *symName, int32_t defLineNo, char *body, size_t size);
|
||||
struct Symbol *sym_Ref(char const *symName);
|
||||
struct Symbol *sym_AddString(char const *symName, char const *value);
|
||||
struct Symbol *sym_RedefString(char const *symName, char const *value);
|
||||
void sym_Purge(char const *symName);
|
||||
void sym_Init(time_t now);
|
||||
|
||||
/* Functions to save and restore the current symbol scope. */
|
||||
char const *sym_GetCurrentSymbolScope(void);
|
||||
void sym_SetCurrentSymbolScope(char const *newScope);
|
||||
|
||||
#endif /* RGBDS_SYMBOL_H */
|
||||
@@ -1,107 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_SYMBOL_HPP
|
||||
#define RGBDS_ASM_SYMBOL_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <time.h>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
#include "asm/lexer.hpp"
|
||||
#include "asm/section.hpp"
|
||||
|
||||
enum SymbolType {
|
||||
SYM_LABEL,
|
||||
SYM_EQU,
|
||||
SYM_VAR,
|
||||
SYM_MACRO,
|
||||
SYM_EQUS,
|
||||
SYM_REF // Forward reference to a label
|
||||
};
|
||||
|
||||
struct Symbol; // For the `sym_IsPC` forward declaration
|
||||
bool sym_IsPC(Symbol const *sym); // For the inline `getSection` method
|
||||
|
||||
struct Symbol {
|
||||
std::string name;
|
||||
SymbolType type;
|
||||
bool isExported; // Whether the symbol is to be exported
|
||||
bool isBuiltin; // Whether the symbol is a built-in
|
||||
Section *section;
|
||||
std::shared_ptr<FileStackNode> src; // Where the symbol was defined
|
||||
uint32_t fileLine; // Line where the symbol was defined
|
||||
|
||||
std::variant<
|
||||
int32_t, // If isNumeric()
|
||||
int32_t (*)(), // If isNumeric() via a callback
|
||||
ContentSpan, // For SYM_MACRO
|
||||
std::shared_ptr<std::string>, // For SYM_EQUS
|
||||
std::shared_ptr<std::string> (*)() // For SYM_EQUS via a callback
|
||||
>
|
||||
data;
|
||||
|
||||
uint32_t ID; // ID of the symbol in the object file (-1 if none)
|
||||
uint32_t defIndex; // Ordering of the symbol in the state file
|
||||
|
||||
bool isDefined() const { return type != SYM_REF; }
|
||||
bool isNumeric() const { return type == SYM_LABEL || type == SYM_EQU || type == SYM_VAR; }
|
||||
bool isLabel() const { return type == SYM_LABEL || type == SYM_REF; }
|
||||
|
||||
bool isConstant() const {
|
||||
if (type == SYM_LABEL) {
|
||||
Section const *sect = getSection();
|
||||
return sect && sect->org != (uint32_t)-1;
|
||||
}
|
||||
return type == SYM_EQU || type == SYM_VAR;
|
||||
}
|
||||
|
||||
Section *getSection() const { return sym_IsPC(this) ? sect_GetSymbolSection() : section; }
|
||||
|
||||
int32_t getValue() const;
|
||||
int32_t getOutputValue() const;
|
||||
ContentSpan const &getMacro() const;
|
||||
std::shared_ptr<std::string> getEqus() const;
|
||||
uint32_t getConstantValue() const;
|
||||
};
|
||||
|
||||
void sym_ForEach(void (*callback)(Symbol &));
|
||||
|
||||
void sym_SetExportAll(bool set);
|
||||
Symbol *sym_AddLocalLabel(std::string const &symName);
|
||||
Symbol *sym_AddLabel(std::string const &symName);
|
||||
Symbol *sym_AddAnonLabel();
|
||||
std::string sym_MakeAnonLabelName(uint32_t ofs, bool neg);
|
||||
void sym_Export(std::string const &symName);
|
||||
Symbol *sym_AddEqu(std::string const &symName, int32_t value);
|
||||
Symbol *sym_RedefEqu(std::string const &symName, int32_t value);
|
||||
Symbol *sym_AddVar(std::string const &symName, int32_t value);
|
||||
int32_t sym_GetRSValue();
|
||||
void sym_SetRSValue(int32_t value);
|
||||
uint32_t sym_GetConstantValue(std::string const &symName);
|
||||
// Find a symbol by exact name, bypassing expansion checks
|
||||
Symbol *sym_FindExactSymbol(std::string const &symName);
|
||||
// Find a symbol, possibly scoped, by name
|
||||
Symbol *sym_FindScopedSymbol(std::string const &symName);
|
||||
// Find a scoped symbol by name; do not return `@` or `_NARG` when they have no value
|
||||
Symbol *sym_FindScopedValidSymbol(std::string const &symName);
|
||||
Symbol const *sym_GetPC();
|
||||
Symbol *sym_AddMacro(std::string const &symName, int32_t defLineNo, ContentSpan const &span);
|
||||
Symbol *sym_Ref(std::string const &symName);
|
||||
Symbol *sym_AddString(std::string const &symName, std::shared_ptr<std::string> value);
|
||||
Symbol *sym_RedefString(std::string const &symName, std::shared_ptr<std::string> value);
|
||||
void sym_Purge(std::string const &symName);
|
||||
bool sym_IsPurgedExact(std::string const &symName);
|
||||
bool sym_IsPurgedScoped(std::string const &symName);
|
||||
void sym_Init(time_t now);
|
||||
|
||||
// Functions to save and restore the current label scopes.
|
||||
std::pair<Symbol const *, Symbol const *> sym_GetCurrentLabelScopes();
|
||||
void sym_SetCurrentLabelScopes(std::pair<Symbol const *, Symbol const *> newScopes);
|
||||
void sym_ResetCurrentLabelScopes();
|
||||
|
||||
#endif // RGBDS_ASM_SYMBOL_HPP
|
||||
21
include/asm/util.h
Normal file
21
include/asm/util.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_UTIL_H
|
||||
#define RGBDS_UTIL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
char const *printChar(int c);
|
||||
|
||||
/*
|
||||
* @return The number of bytes read, or 0 if invalid data was found
|
||||
*/
|
||||
size_t readUTF8Char(uint8_t *dest, char const *src);
|
||||
|
||||
#endif /* RGBDS_UTIL_H */
|
||||
93
include/asm/warning.h
Normal file
93
include/asm/warning.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2019, Eldred Habert and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef WARNING_H
|
||||
#define WARNING_H
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
extern unsigned int nbErrors;
|
||||
|
||||
enum WarningState {
|
||||
WARNING_DEFAULT,
|
||||
WARNING_DISABLED,
|
||||
WARNING_ENABLED,
|
||||
WARNING_ERROR
|
||||
};
|
||||
|
||||
enum WarningID {
|
||||
WARNING_ASSERT, // Assertions
|
||||
WARNING_BACKWARDS_FOR, // `for` loop with backwards range
|
||||
WARNING_BUILTIN_ARG, // Invalid args to builtins
|
||||
WARNING_CHARMAP_REDEF, // Charmap entry re-definition
|
||||
WARNING_DIV, // Division undefined behavior
|
||||
WARNING_EMPTY_DATA_DIRECTIVE, // `db`, `dw` or `dl` directive without data in ROM
|
||||
WARNING_EMPTY_MACRO_ARG, // Empty macro argument
|
||||
WARNING_EMPTY_STRRPL, // Empty second argument in `STRRPL`
|
||||
WARNING_LARGE_CONSTANT, // Constants too large
|
||||
WARNING_LONG_STR, // String too long for internal buffers
|
||||
WARNING_MACRO_SHIFT, // Shift past available arguments in macro
|
||||
WARNING_NESTED_COMMENT, // Comment-start delimiter in a block comment
|
||||
WARNING_OBSOLETE, // Obsolete things
|
||||
WARNING_SHIFT, // Shifting undefined behavior
|
||||
WARNING_SHIFT_AMOUNT, // Strange shift amount
|
||||
WARNING_USER, // User warnings
|
||||
|
||||
NB_PLAIN_WARNINGS,
|
||||
|
||||
// Warnings past this point are "parametric" warnings, only mapping to a single flag
|
||||
#define PARAM_WARNINGS_START NB_PLAIN_WARNINGS
|
||||
// Treating string as number may lose some bits
|
||||
WARNING_NUMERIC_STRING_1 = PARAM_WARNINGS_START,
|
||||
WARNING_NUMERIC_STRING_2,
|
||||
// Implicit truncation loses some bits
|
||||
WARNING_TRUNCATION_1,
|
||||
WARNING_TRUNCATION_2,
|
||||
|
||||
NB_PLAIN_AND_PARAM_WARNINGS,
|
||||
#define NB_PARAM_WARNINGS (NB_PLAIN_AND_PARAM_WARNINGS - PARAM_WARNINGS_START)
|
||||
|
||||
// Warnings past this point are "meta" warnings
|
||||
#define META_WARNINGS_START NB_PLAIN_AND_PARAM_WARNINGS
|
||||
WARNING_ALL = META_WARNINGS_START,
|
||||
WARNING_EXTRA,
|
||||
WARNING_EVERYTHING,
|
||||
|
||||
NB_WARNINGS,
|
||||
#define NB_META_WARNINGS (NB_WARNINGS - META_WARNINGS_START)
|
||||
};
|
||||
|
||||
extern enum WarningState warningStates[NB_PLAIN_AND_PARAM_WARNINGS];
|
||||
extern bool warningsAreErrors;
|
||||
|
||||
void processWarningFlag(char *flag);
|
||||
|
||||
/*
|
||||
* Used to warn the user about problems that don't prevent the generation of
|
||||
* valid code.
|
||||
*/
|
||||
void warning(enum WarningID id, char const *fmt, ...) format_(printf, 2, 3);
|
||||
|
||||
/*
|
||||
* Used for errors that compromise the whole assembly process by affecting the
|
||||
* following code, potencially making the assembler generate errors caused by
|
||||
* the first one and unrelated to the code that the assembler complains about.
|
||||
* It is also used when the assembler goes into an invalid state (for example,
|
||||
* when it fails to allocate memory).
|
||||
*/
|
||||
_Noreturn void fatalerror(char const *fmt, ...) format_(printf, 1, 2);
|
||||
|
||||
/*
|
||||
* Used for errors that make it impossible to assemble correctly, but don't
|
||||
* affect the following code. The code will fail to assemble but the user will
|
||||
* get a list of all errors at the end, making it easier to fix all of them at
|
||||
* once.
|
||||
*/
|
||||
void error(char const *fmt, ...) format_(printf, 1, 2);
|
||||
|
||||
#endif
|
||||
@@ -1,85 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ASM_WARNING_HPP
|
||||
#define RGBDS_ASM_WARNING_HPP
|
||||
|
||||
extern unsigned int nbErrors, maxErrors;
|
||||
|
||||
enum WarningState { WARNING_DEFAULT, WARNING_DISABLED, WARNING_ENABLED, WARNING_ERROR };
|
||||
|
||||
enum WarningID {
|
||||
WARNING_ASSERT, // Assertions
|
||||
WARNING_BACKWARDS_FOR, // `for` loop with backwards range
|
||||
WARNING_BUILTIN_ARG, // Invalid args to builtins
|
||||
WARNING_CHARMAP_REDEF, // Charmap entry re-definition
|
||||
WARNING_DIV, // Division undefined behavior
|
||||
WARNING_EMPTY_DATA_DIRECTIVE, // `db`, `dw` or `dl` directive without data in ROM
|
||||
WARNING_EMPTY_MACRO_ARG, // Empty macro argument
|
||||
WARNING_EMPTY_STRRPL, // Empty second argument in `STRRPL`
|
||||
WARNING_LARGE_CONSTANT, // Constants too large
|
||||
WARNING_MACRO_SHIFT, // Shift past available arguments in macro
|
||||
WARNING_NESTED_COMMENT, // Comment-start delimiter in a block comment
|
||||
WARNING_OBSOLETE, // Obsolete things
|
||||
WARNING_SHIFT, // Shifting undefined behavior
|
||||
WARNING_SHIFT_AMOUNT, // Strange shift amount
|
||||
WARNING_USER, // User warnings
|
||||
|
||||
NB_PLAIN_WARNINGS,
|
||||
|
||||
// Warnings past this point are "parametric" warnings, only mapping to a single flag
|
||||
#define PARAM_WARNINGS_START NB_PLAIN_WARNINGS
|
||||
// Treating string as number may lose some bits
|
||||
WARNING_NUMERIC_STRING_1 = PARAM_WARNINGS_START,
|
||||
WARNING_NUMERIC_STRING_2,
|
||||
// Purging an exported symbol or label
|
||||
WARNING_PURGE_1,
|
||||
WARNING_PURGE_2,
|
||||
// Implicit truncation loses some bits
|
||||
WARNING_TRUNCATION_1,
|
||||
WARNING_TRUNCATION_2,
|
||||
// Character without charmap entry
|
||||
WARNING_UNMAPPED_CHAR_1,
|
||||
WARNING_UNMAPPED_CHAR_2,
|
||||
|
||||
NB_PLAIN_AND_PARAM_WARNINGS,
|
||||
#define NB_PARAM_WARNINGS (NB_PLAIN_AND_PARAM_WARNINGS - PARAM_WARNINGS_START)
|
||||
|
||||
// Warnings past this point are "meta" warnings
|
||||
#define META_WARNINGS_START NB_PLAIN_AND_PARAM_WARNINGS
|
||||
WARNING_ALL = META_WARNINGS_START,
|
||||
WARNING_EXTRA,
|
||||
WARNING_EVERYTHING,
|
||||
|
||||
NB_WARNINGS,
|
||||
#define NB_META_WARNINGS (NB_WARNINGS - META_WARNINGS_START)
|
||||
};
|
||||
|
||||
extern WarningState warningStates[NB_PLAIN_AND_PARAM_WARNINGS];
|
||||
extern bool warningsAreErrors;
|
||||
|
||||
void processWarningFlag(char const *flag);
|
||||
|
||||
/*
|
||||
* Used to warn the user about problems that don't prevent the generation of
|
||||
* valid code.
|
||||
*/
|
||||
[[gnu::format(printf, 2, 3)]] void warning(WarningID id, char const *fmt, ...);
|
||||
|
||||
/*
|
||||
* Used for errors that compromise the whole assembly process by affecting the
|
||||
* following code, potencially making the assembler generate errors caused by
|
||||
* the first one and unrelated to the code that the assembler complains about.
|
||||
* It is also used when the assembler goes into an invalid state (for example,
|
||||
* when it fails to allocate memory).
|
||||
*/
|
||||
[[gnu::format(printf, 1, 2), noreturn]] void fatalerror(char const *fmt, ...);
|
||||
|
||||
/*
|
||||
* Used for errors that make it impossible to assemble correctly, but don't
|
||||
* affect the following code. The code will fail to assemble but the user will
|
||||
* get a list of all errors at the end, making it easier to fix all of them at
|
||||
* once.
|
||||
*/
|
||||
[[gnu::format(printf, 1, 2)]] void error(char const *fmt, ...);
|
||||
|
||||
#endif // RGBDS_ASM_WARNING_HPP
|
||||
@@ -1,41 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_DEFAULT_INIT_ALLOC_HPP
|
||||
#define RGBDS_DEFAULT_INIT_ALLOC_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
* Allocator adaptor that interposes construct() calls to convert value-initialization
|
||||
* (which is what you get with e.g. `vector::resize`) into default-initialization (which does not
|
||||
* zero out non-class types).
|
||||
* From
|
||||
* https://stackoverflow.com/questions/21028299/is-this-behavior-of-vectorresizesize-type-n-under-c11-and-boost-container/21028912#21028912
|
||||
*/
|
||||
|
||||
template<typename T, typename A = std::allocator<T>>
|
||||
class default_init_allocator : public A {
|
||||
using a_t = std::allocator_traits<A>;
|
||||
public:
|
||||
template<typename U>
|
||||
struct rebind {
|
||||
using other = default_init_allocator<U, typename a_t::template rebind_alloc<U>>;
|
||||
};
|
||||
|
||||
using A::A; // Inherit the allocator's constructors
|
||||
|
||||
template<typename U>
|
||||
void construct(U *ptr) noexcept(std::is_nothrow_default_constructible_v<U>) {
|
||||
::new (static_cast<void *>(ptr)) U;
|
||||
}
|
||||
template<typename U, typename... Args>
|
||||
void construct(U *ptr, Args &&...args) {
|
||||
a_t::construct(static_cast<A &>(*this), ptr, std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using DefaultInitVec = std::vector<T, default_init_allocator<T>>;
|
||||
|
||||
#endif // RGBDS_DEFAULT_INIT_ALLOC_HPP
|
||||
@@ -1,176 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_EITHER_HPP
|
||||
#define RGBDS_EITHER_HPP
|
||||
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include "helpers.hpp" // assume
|
||||
|
||||
template<typename T1, typename T2>
|
||||
union Either {
|
||||
typedef T1 type1;
|
||||
typedef T2 type2;
|
||||
|
||||
private:
|
||||
template<typename T, unsigned V>
|
||||
struct Field {
|
||||
constexpr static unsigned tag_value = V;
|
||||
|
||||
unsigned tag = tag_value;
|
||||
T value;
|
||||
|
||||
Field() : value() {}
|
||||
Field(T &value_) : value(value_) {}
|
||||
Field(T const &value_) : value(value_) {}
|
||||
Field(T &&value_) : value(std::move(value_)) {}
|
||||
};
|
||||
|
||||
// The `_tag` unifies with the first `tag` member of each `struct`.
|
||||
constexpr static unsigned nulltag = 0;
|
||||
unsigned _tag = nulltag;
|
||||
Field<T1, 1> _t1;
|
||||
Field<T2, 2> _t2;
|
||||
|
||||
// Value accessors; the function parameters are dummies for overload resolution.
|
||||
// Only used to implement `field()` below.
|
||||
auto &pick(T1 *) { return _t1; }
|
||||
auto const &pick(T1 *) const { return _t1; }
|
||||
auto &pick(T2 *) { return _t2; }
|
||||
auto const &pick(T2 *) const { return _t2; }
|
||||
|
||||
// Generic field accessors; for internal use only.
|
||||
template<typename T>
|
||||
auto &field() {
|
||||
return pick((T *)nullptr);
|
||||
}
|
||||
template<typename T>
|
||||
auto const &field() const {
|
||||
return pick((T *)nullptr);
|
||||
}
|
||||
|
||||
public:
|
||||
// Equivalent of `std::monostate` for `std::variant`s.
|
||||
Either() : _tag() {}
|
||||
// These constructors cannot be generic over the value type, because that would prevent
|
||||
// constructible values from being inferred, e.g. a `const char *` string literal for an
|
||||
// `std::string` field value.
|
||||
Either(T1 &value) : _t1(value) {}
|
||||
Either(T2 &value) : _t2(value) {}
|
||||
Either(T1 const &value) : _t1(value) {}
|
||||
Either(T2 const &value) : _t2(value) {}
|
||||
Either(T1 &&value) : _t1(std::move(value)) {}
|
||||
Either(T2 &&value) : _t2(std::move(value)) {}
|
||||
|
||||
// Destructor manually calls the appropriate value destructor.
|
||||
~Either() {
|
||||
if (_tag == _t1.tag_value) {
|
||||
_t1.value.~T1();
|
||||
} else if (_tag == _t2.tag_value) {
|
||||
_t2.value.~T2();
|
||||
}
|
||||
}
|
||||
|
||||
// Copy assignment operators for each possible value.
|
||||
Either &operator=(T1 const &value) {
|
||||
_t1.tag = _t1.tag_value;
|
||||
new (&_t1.value) T1(value);
|
||||
return *this;
|
||||
}
|
||||
Either &operator=(T2 const &value) {
|
||||
_t2.tag = _t2.tag_value;
|
||||
new (&_t2.value) T2(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Move assignment operators for each possible value.
|
||||
Either &operator=(T1 &&value) {
|
||||
_t1.tag = _t1.tag_value;
|
||||
new (&_t1.value) T1(std::move(value));
|
||||
return *this;
|
||||
}
|
||||
Either &operator=(T2 &&value) {
|
||||
_t2.tag = _t2.tag_value;
|
||||
new (&_t2.value) T2(std::move(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy assignment operator from another `Either`.
|
||||
Either &operator=(Either other) {
|
||||
if (other._tag == other._t1.tag_value) {
|
||||
*this = other._t1.value;
|
||||
} else if (other._tag == other._t2.tag_value) {
|
||||
*this = other._t2.value;
|
||||
} else {
|
||||
_tag = nulltag;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Copy constructor from another `Either`; implemented in terms of value assignment operators.
|
||||
Either(Either const &other) {
|
||||
if (other._tag == other._t1.tag_value) {
|
||||
*this = other._t1.value;
|
||||
} else if (other._tag == other._t2.tag_value) {
|
||||
*this = other._t2.value;
|
||||
} else {
|
||||
_tag = nulltag;
|
||||
}
|
||||
}
|
||||
|
||||
// Move constructor from another `Either`; implemented in terms of value assignment operators.
|
||||
Either(Either &&other) {
|
||||
if (other._tag == other._t1.tag_value) {
|
||||
*this = std::move(other._t1.value);
|
||||
} else if (other._tag == other._t2.tag_value) {
|
||||
*this = std::move(other._t2.value);
|
||||
} else {
|
||||
_tag = nulltag;
|
||||
}
|
||||
}
|
||||
|
||||
// Equivalent of `.emplace<T>()` for `std::variant`s.
|
||||
template<typename T, typename... Args>
|
||||
void emplace(Args &&...args) {
|
||||
this->~Either();
|
||||
if constexpr (std::is_same_v<T, T1>) {
|
||||
_t1.tag = _t1.tag_value;
|
||||
new (&_t1.value) T1(std::forward<Args>(args)...);
|
||||
} else if constexpr (std::is_same_v<T, T2>) {
|
||||
_t2.tag = _t2.tag_value;
|
||||
new (&_t2.value) T2(std::forward<Args>(args)...);
|
||||
} else {
|
||||
_tag = nulltag;
|
||||
}
|
||||
}
|
||||
|
||||
// Equivalent of `std::holds_alternative<std::monostate>()` for `std::variant`s.
|
||||
bool empty() const { return _tag == nulltag; }
|
||||
|
||||
// Equivalent of `std::holds_alternative<T>()` for `std::variant`s.
|
||||
template<typename T>
|
||||
bool holds() const {
|
||||
if constexpr (std::is_same_v<T, T1>) {
|
||||
return _tag == _t1.tag_value;
|
||||
} else if constexpr (std::is_same_v<T, T2>) {
|
||||
return _tag == _t2.tag_value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Equivalent of `std::get<T>()` for `std::variant`s.
|
||||
template<typename T>
|
||||
auto &get() {
|
||||
assume(holds<T>());
|
||||
return field<T>().value;
|
||||
}
|
||||
template<typename T>
|
||||
auto const &get() const {
|
||||
assume(holds<T>());
|
||||
return field<T>().value;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RGBDS_EITHER_HPP
|
||||
21
include/error.h
Normal file
21
include/error.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2021, RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_ERROR_H
|
||||
#define RGBDS_ERROR_H
|
||||
|
||||
#include "helpers.h"
|
||||
#include "platform.h"
|
||||
|
||||
void warn(char const NONNULL(fmt), ...) format_(printf, 1, 2);
|
||||
void warnx(char const NONNULL(fmt), ...) format_(printf, 1, 2);
|
||||
|
||||
_Noreturn void err(char const NONNULL(fmt), ...) format_(printf, 1, 2);
|
||||
_Noreturn void errx(char const NONNULL(fmt), ...) format_(printf, 1, 2);
|
||||
|
||||
#endif /* RGBDS_ERROR_H */
|
||||
@@ -1,15 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ERROR_HPP
|
||||
#define RGBDS_ERROR_HPP
|
||||
|
||||
extern "C" {
|
||||
|
||||
[[gnu::format(printf, 1, 2)]] void warn(char const *fmt...);
|
||||
[[gnu::format(printf, 1, 2)]] void warnx(char const *fmt, ...);
|
||||
|
||||
[[gnu::format(printf, 1, 2), noreturn]] void err(char const *fmt, ...);
|
||||
[[gnu::format(printf, 1, 2), noreturn]] void errx(char const *fmt, ...);
|
||||
}
|
||||
|
||||
#endif // RGBDS_ERROR_HPP
|
||||
46
include/extern/getopt.h
vendored
Normal file
46
include/extern/getopt.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright © 2005-2020 Rich Felker, et al.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* This implementation was taken from musl and modified for RGBDS */
|
||||
|
||||
#ifndef RGBDS_EXTERN_GETOPT_H
|
||||
#define RGBDS_EXTERN_GETOPT_H
|
||||
|
||||
extern char *musl_optarg;
|
||||
extern int musl_optind, musl_opterr, musl_optopt, musl_optreset;
|
||||
|
||||
struct option {
|
||||
char const *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
int musl_getopt_long_only(int argc, char **argv, char const *optstring,
|
||||
const struct option *longopts, int *idx);
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
#endif
|
||||
30
include/extern/getopt.hpp
vendored
30
include/extern/getopt.hpp
vendored
@@ -1,30 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
/* This implementation was taken from musl and modified for RGBDS */
|
||||
|
||||
#ifndef RGBDS_EXTERN_GETOPT_HPP
|
||||
#define RGBDS_EXTERN_GETOPT_HPP
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern char *musl_optarg;
|
||||
extern int musl_optind, musl_opterr, musl_optopt, musl_optreset;
|
||||
|
||||
struct option {
|
||||
char const *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
|
||||
int musl_getopt_long_only(
|
||||
int argc, char **argv, char const *optstring, option const *longopts, int *idx
|
||||
);
|
||||
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
} // extern "C"
|
||||
|
||||
#endif // RGBDS_EXTERN_GETOPT_HPP
|
||||
14
include/extern/utf8decoder.h
vendored
Normal file
14
include/extern/utf8decoder.h
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2018, Antonio Nino Diaz and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef EXTERN_UTF8DECODER_H
|
||||
#define EXTERN_UTF8DECODER_H
|
||||
|
||||
uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte);
|
||||
|
||||
#endif /* EXTERN_UTF8DECODER_H */
|
||||
10
include/extern/utf8decoder.hpp
vendored
10
include/extern/utf8decoder.hpp
vendored
@@ -1,10 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_EXTERN_UTF8DECODER_HPP
|
||||
#define RGBDS_EXTERN_UTF8DECODER_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t decode(uint32_t *state, uint32_t *codep, uint8_t byte);
|
||||
|
||||
#endif // RGBDS_EXTERN_UTF8DECODER_HPP
|
||||
@@ -1,87 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_FILE_HPP
|
||||
#define RGBDS_FILE_HPP
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fstream>
|
||||
#include <ios>
|
||||
#include <iostream>
|
||||
#include <streambuf>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
|
||||
#include "either.hpp"
|
||||
#include "helpers.hpp" // assume
|
||||
#include "platform.hpp"
|
||||
|
||||
#include "gfx/main.hpp"
|
||||
|
||||
class File {
|
||||
// Construct a `std::streambuf *` by default, since it's probably lighter than a `filebuf`.
|
||||
Either<std::streambuf *, std::filebuf> _file;
|
||||
|
||||
public:
|
||||
File() {}
|
||||
~File() { close(); }
|
||||
|
||||
/**
|
||||
* This should only be called once, and before doing any `->` operations.
|
||||
* Returns `nullptr` on error, and a non-null pointer otherwise.
|
||||
*/
|
||||
File *open(std::string const &path, std::ios_base::openmode mode) {
|
||||
if (path != "-") {
|
||||
_file.emplace<std::filebuf>();
|
||||
return _file.get<std::filebuf>().open(path, mode) ? this : nullptr;
|
||||
} else if (mode & std::ios_base::in) {
|
||||
assume(!(mode & std::ios_base::out));
|
||||
_file.emplace<std::streambuf *>(std::cin.rdbuf());
|
||||
if (setmode(STDIN_FILENO, (mode & std::ios_base::binary) ? O_BINARY : O_TEXT) == -1) {
|
||||
fatal(
|
||||
"Failed to set stdin to %s mode: %s",
|
||||
mode & std::ios_base::binary ? "binary" : "text",
|
||||
strerror(errno)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
assume(mode & std::ios_base::out);
|
||||
_file.emplace<std::streambuf *>(std::cout.rdbuf());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
std::streambuf &operator*() {
|
||||
return _file.holds<std::filebuf>() ? _file.get<std::filebuf>()
|
||||
: *_file.get<std::streambuf *>();
|
||||
}
|
||||
std::streambuf const &operator*() const {
|
||||
// The non-`const` version does not perform any modifications, so it's okay.
|
||||
return **const_cast<File *>(this);
|
||||
}
|
||||
std::streambuf *operator->() { return &**this; }
|
||||
std::streambuf const *operator->() const {
|
||||
// See the `operator*` equivalent.
|
||||
return const_cast<File *>(this)->operator->();
|
||||
}
|
||||
|
||||
File *close() {
|
||||
if (_file.holds<std::filebuf>()) {
|
||||
// This is called by the destructor, and an explicit `close` shouldn't close twice.
|
||||
std::filebuf fileBuf = std::move(_file.get<std::filebuf>());
|
||||
_file.emplace<std::streambuf *>(nullptr);
|
||||
if (fileBuf.close() != nullptr) {
|
||||
return this;
|
||||
}
|
||||
} else if (_file.get<std::streambuf *>() != nullptr) {
|
||||
return this;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char const *c_str(std::string const &path) const {
|
||||
return _file.holds<std::filebuf>() ? path.c_str()
|
||||
: _file.get<std::streambuf *>() == std::cin.rdbuf() ? "<stdin>"
|
||||
: "<stdout>";
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RGBDS_FILE_HPP
|
||||
36
include/gfx/gb.h
Normal file
36
include/gfx/gb.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2013-2018, stag019 and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_GFX_GB_H
|
||||
#define RGBDS_GFX_GB_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gfx/main.h"
|
||||
|
||||
#define XFLIP 0x40
|
||||
#define YFLIP 0x20
|
||||
|
||||
void raw_to_gb(const struct RawIndexedImage *raw_image, struct GBImage *gb);
|
||||
void output_file(const struct Options *opts, const struct GBImage *gb);
|
||||
int get_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
|
||||
int tile_size);
|
||||
uint8_t reverse_bits(uint8_t b);
|
||||
void xflip(uint8_t *tile, uint8_t *tile_xflip, int tile_size);
|
||||
void yflip(uint8_t *tile, uint8_t *tile_yflip, int tile_size);
|
||||
int get_mirrored_tile_index(uint8_t *tile, uint8_t **tiles, int num_tiles,
|
||||
int tile_size, int *flags);
|
||||
void create_mapfiles(const struct Options *opts, struct GBImage *gb,
|
||||
struct Mapfile *tilemap, struct Mapfile *attrmap);
|
||||
void output_tilemap_file(const struct Options *opts,
|
||||
const struct Mapfile *tilemap);
|
||||
void output_attrmap_file(const struct Options *opts,
|
||||
const struct Mapfile *attrmap);
|
||||
void output_palette_file(const struct Options *opts,
|
||||
const struct RawIndexedImage *raw_image);
|
||||
|
||||
#endif
|
||||
91
include/gfx/main.h
Normal file
91
include/gfx/main.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2013-2018, stag019 and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_GFX_MAIN_H
|
||||
#define RGBDS_GFX_MAIN_H
|
||||
|
||||
#include <png.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "error.h"
|
||||
|
||||
struct Options {
|
||||
bool debug;
|
||||
bool verbose;
|
||||
bool hardfix;
|
||||
bool fix;
|
||||
bool horizontal;
|
||||
bool mirror;
|
||||
bool unique;
|
||||
bool colorcurve;
|
||||
unsigned int trim;
|
||||
char *tilemapfile;
|
||||
bool tilemapout;
|
||||
char *attrmapfile;
|
||||
bool attrmapout;
|
||||
char *palfile;
|
||||
bool palout;
|
||||
char *outfile;
|
||||
char *infile;
|
||||
};
|
||||
|
||||
struct RGBColor {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
};
|
||||
|
||||
struct ImageOptions {
|
||||
bool horizontal;
|
||||
unsigned int trim;
|
||||
char *tilemapfile;
|
||||
bool tilemapout;
|
||||
char *attrmapfile;
|
||||
bool attrmapout;
|
||||
char *palfile;
|
||||
bool palout;
|
||||
};
|
||||
|
||||
struct PNGImage {
|
||||
png_struct *png;
|
||||
png_info *info;
|
||||
|
||||
png_byte **data;
|
||||
int width;
|
||||
int height;
|
||||
png_byte depth;
|
||||
png_byte type;
|
||||
};
|
||||
|
||||
struct RawIndexedImage {
|
||||
uint8_t **data;
|
||||
struct RGBColor *palette;
|
||||
int num_colors;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
};
|
||||
|
||||
struct GBImage {
|
||||
uint8_t *data;
|
||||
int size;
|
||||
bool horizontal;
|
||||
int trim;
|
||||
};
|
||||
|
||||
struct Mapfile {
|
||||
uint8_t *data;
|
||||
int size;
|
||||
};
|
||||
|
||||
extern int depth, colors;
|
||||
|
||||
#include "gfx/makepng.h"
|
||||
#include "gfx/gb.h"
|
||||
|
||||
#endif /* RGBDS_GFX_MAIN_H */
|
||||
@@ -1,126 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_MAIN_HPP
|
||||
#define RGBDS_GFX_MAIN_HPP
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "gfx/rgba.hpp"
|
||||
|
||||
struct Options {
|
||||
bool useColorCurve = false; // -C
|
||||
bool allowDedup = false; // -u
|
||||
bool allowMirroringX = false; // -X, -m
|
||||
bool allowMirroringY = false; // -Y, -m
|
||||
bool columnMajor = false; // -Z
|
||||
uint8_t verbosity = 0; // -v
|
||||
|
||||
std::string attrmap{}; // -a, -A
|
||||
std::array<uint8_t, 2> baseTileIDs{0, 0}; // -b
|
||||
enum {
|
||||
NO_SPEC,
|
||||
EXPLICIT,
|
||||
EMBEDDED,
|
||||
} palSpecType = NO_SPEC; // -c
|
||||
std::vector<std::array<std::optional<Rgba>, 4>> palSpec{};
|
||||
uint8_t bitDepth = 2; // -d
|
||||
std::string inputTileset{}; // -i
|
||||
struct {
|
||||
uint16_t left;
|
||||
uint16_t top;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
} inputSlice{0, 0, 0, 0}; // -L (margins in clockwise order, like CSS)
|
||||
std::array<uint16_t, 2> maxNbTiles{UINT16_MAX, 0}; // -N
|
||||
uint16_t nbPalettes = 8; // -n
|
||||
std::string output{}; // -o
|
||||
std::string palettes{}; // -p, -P
|
||||
std::string palmap{}; // -q, -Q
|
||||
uint16_t reversedWidth = 0; // -r, in tiles
|
||||
uint8_t nbColorsPerPal = 0; // -s; 0 means "auto" = 1 << bitDepth;
|
||||
std::string tilemap{}; // -t, -T
|
||||
uint64_t trim = 0; // -x
|
||||
|
||||
std::string input{}; // positional arg
|
||||
|
||||
static constexpr uint8_t VERB_NONE = 0; // Normal, no extra output
|
||||
static constexpr uint8_t VERB_CFG = 1; // Print configuration after parsing options
|
||||
static constexpr uint8_t VERB_LOG_ACT = 2; // Log actions before doing them
|
||||
static constexpr uint8_t VERB_INTERM = 3; // Print some intermediate results
|
||||
static constexpr uint8_t VERB_DEBUG = 4; // Internals are logged
|
||||
static constexpr uint8_t VERB_UNMAPPED = 5; // Unused so far
|
||||
static constexpr uint8_t VERB_VVVVVV = 6; // What, can't I have a little fun?
|
||||
[[gnu::format(printf, 3, 4)]] void verbosePrint(uint8_t level, char const *fmt, ...) const;
|
||||
|
||||
mutable bool hasTransparentPixels = false;
|
||||
uint8_t maxOpaqueColors() const { return nbColorsPerPal - hasTransparentPixels; }
|
||||
};
|
||||
|
||||
extern Options options;
|
||||
|
||||
/*
|
||||
* Prints the error count, and exits with failure
|
||||
*/
|
||||
[[noreturn]] void giveUp();
|
||||
/*
|
||||
* If any error has been emitted thus far, calls `giveUp()`.
|
||||
*/
|
||||
void requireZeroErrors();
|
||||
/*
|
||||
* Prints a warning, and does not change the error count
|
||||
*/
|
||||
[[gnu::format(printf, 1, 2)]] void warning(char const *fmt, ...);
|
||||
/*
|
||||
* Prints an error, and increments the error count
|
||||
*/
|
||||
[[gnu::format(printf, 1, 2)]] void error(char const *fmt, ...);
|
||||
/*
|
||||
* Prints an error, and increments the error count
|
||||
* Does not take format arguments so `format_` and `-Wformat-security` won't complain about
|
||||
* calling `errorMessage(msg)`.
|
||||
*/
|
||||
void errorMessage(char const *msg);
|
||||
/*
|
||||
* Prints a fatal error, increments the error count, and gives up
|
||||
*/
|
||||
[[gnu::format(printf, 1, 2), noreturn]] void fatal(char const *fmt, ...);
|
||||
|
||||
struct Palette {
|
||||
// An array of 4 GBC-native (RGB555) colors
|
||||
std::array<uint16_t, 4> colors{UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX};
|
||||
|
||||
void addColor(uint16_t color);
|
||||
uint8_t indexOf(uint16_t color) const;
|
||||
uint16_t &operator[](size_t index) { return colors[index]; }
|
||||
uint16_t const &operator[](size_t index) const { return colors[index]; }
|
||||
|
||||
decltype(colors)::iterator begin();
|
||||
decltype(colors)::iterator end();
|
||||
decltype(colors)::const_iterator begin() const;
|
||||
decltype(colors)::const_iterator end() const;
|
||||
|
||||
uint8_t size() const;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename T, T... i>
|
||||
static constexpr auto flipTable(std::integer_sequence<T, i...>) {
|
||||
return std::array{[](uint8_t byte) {
|
||||
// To flip all the bits, we'll flip both nibbles, then each nibble half, etc.
|
||||
byte = (byte & 0b0000'1111) << 4 | (byte & 0b1111'0000) >> 4;
|
||||
byte = (byte & 0b0011'0011) << 2 | (byte & 0b1100'1100) >> 2;
|
||||
byte = (byte & 0b0101'0101) << 1 | (byte & 0b1010'1010) >> 1;
|
||||
return byte;
|
||||
}(i)...};
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// Flipping tends to happen fairly often, so take a bite out of dcache to speed it up
|
||||
static constexpr auto flipTable = detail::flipTable(std::make_integer_sequence<uint16_t, 256>());
|
||||
|
||||
#endif // RGBDS_GFX_MAIN_HPP
|
||||
21
include/gfx/makepng.h
Normal file
21
include/gfx/makepng.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2013-2018, stag019 and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RGBDS_GFX_PNG_H
|
||||
#define RGBDS_GFX_PNG_H
|
||||
|
||||
#include "gfx/main.h"
|
||||
|
||||
struct RawIndexedImage *input_png_file(const struct Options *opts,
|
||||
struct ImageOptions *png_options);
|
||||
void output_png_file(const struct Options *opts,
|
||||
const struct ImageOptions *png_options,
|
||||
const struct RawIndexedImage *raw_image);
|
||||
void destroy_raw_image(struct RawIndexedImage **raw_image_ptr_ptr);
|
||||
|
||||
#endif /* RGBDS_GFX_PNG_H */
|
||||
@@ -1,24 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_PAL_PACKING_HPP
|
||||
#define RGBDS_GFX_PAL_PACKING_HPP
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "defaultinitalloc.hpp"
|
||||
|
||||
struct Palette;
|
||||
class ProtoPalette;
|
||||
|
||||
namespace packing {
|
||||
|
||||
/*
|
||||
* Returns which palette each proto-palette maps to, and how many palettes are necessary
|
||||
*/
|
||||
std::tuple<DefaultInitVec<size_t>, size_t>
|
||||
overloadAndRemove(std::vector<ProtoPalette> const &protoPalettes);
|
||||
|
||||
} // namespace packing
|
||||
|
||||
#endif // RGBDS_GFX_PAL_PACKING_HPP
|
||||
@@ -1,31 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_PAL_SORTING_HPP
|
||||
#define RGBDS_GFX_PAL_SORTING_HPP
|
||||
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <png.h>
|
||||
#include <vector>
|
||||
|
||||
#include "gfx/rgba.hpp"
|
||||
|
||||
struct Palette;
|
||||
|
||||
namespace sorting {
|
||||
|
||||
void indexed(
|
||||
std::vector<Palette> &palettes,
|
||||
int palSize,
|
||||
png_color const *palRGB,
|
||||
int palAlphaSize,
|
||||
png_byte *palAlpha
|
||||
);
|
||||
void grayscale(
|
||||
std::vector<Palette> &palettes, std::array<std::optional<Rgba>, 0x8001> const &colors
|
||||
);
|
||||
void rgb(std::vector<Palette> &palettes);
|
||||
|
||||
} // namespace sorting
|
||||
|
||||
#endif // RGBDS_GFX_PAL_SORTING_HPP
|
||||
@@ -1,9 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_PAL_SPEC_HPP
|
||||
#define RGBDS_GFX_PAL_SPEC_HPP
|
||||
|
||||
void parseInlinePalSpec(char const * const arg);
|
||||
void parseExternalPalSpec(char const *arg);
|
||||
|
||||
#endif // RGBDS_GFX_PAL_SPEC_HPP
|
||||
@@ -1,9 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_PROCESS_HPP
|
||||
#define RGBDS_GFX_PROCESS_HPP
|
||||
|
||||
void processPalettes();
|
||||
void process();
|
||||
|
||||
#endif // RGBDS_GFX_PROCESS_HPP
|
||||
@@ -1,42 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_PROTO_PALETTE_HPP
|
||||
#define RGBDS_GFX_PROTO_PALETTE_HPP
|
||||
|
||||
#include <array>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class ProtoPalette {
|
||||
public:
|
||||
static constexpr size_t capacity = 4;
|
||||
|
||||
private:
|
||||
// Up to 4 colors, sorted, and where SIZE_MAX means the slot is empty
|
||||
// (OK because it's not a valid color index)
|
||||
// Sorting is done on the raw numerical values to lessen `compare`'s complexity
|
||||
std::array<uint16_t, capacity> _colorIndices{UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX};
|
||||
|
||||
public:
|
||||
/*
|
||||
* Adds the specified color to the set, or **silently drops it** if the set is full.
|
||||
*
|
||||
* Returns whether the color was unique.
|
||||
*/
|
||||
bool add(uint16_t color);
|
||||
|
||||
enum ComparisonResult {
|
||||
NEITHER,
|
||||
WE_BIGGER,
|
||||
THEY_BIGGER = -1,
|
||||
};
|
||||
ComparisonResult compare(ProtoPalette const &other) const;
|
||||
|
||||
size_t size() const;
|
||||
bool empty() const;
|
||||
|
||||
decltype(_colorIndices)::const_iterator begin() const;
|
||||
decltype(_colorIndices)::const_iterator end() const;
|
||||
};
|
||||
|
||||
#endif // RGBDS_GFX_PROTO_PALETTE_HPP
|
||||
@@ -1,8 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_REVERSE_HPP
|
||||
#define RGBDS_GFX_REVERSE_HPP
|
||||
|
||||
void reverse();
|
||||
|
||||
#endif // RGBDS_GFX_REVERSE_HPP
|
||||
@@ -1,65 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_GFX_RGBA_HPP
|
||||
#define RGBDS_GFX_RGBA_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct Rgba {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
uint8_t alpha;
|
||||
|
||||
constexpr Rgba(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
: red(r), green(g), blue(b), alpha(a) {}
|
||||
/*
|
||||
* Constructs the color from a "packed" RGBA representation (0xRRGGBBAA)
|
||||
*/
|
||||
explicit constexpr Rgba(uint32_t rgba = 0)
|
||||
: red(rgba >> 24), green(rgba >> 16), blue(rgba >> 8), alpha(rgba) {}
|
||||
|
||||
static constexpr Rgba fromCGBColor(uint16_t cgbColor) {
|
||||
constexpr auto _5to8 = [](uint8_t fiveBpp) -> uint8_t {
|
||||
fiveBpp &= 0b11111; // For caller's convenience
|
||||
return fiveBpp << 3 | fiveBpp >> 2;
|
||||
};
|
||||
return {
|
||||
_5to8(cgbColor),
|
||||
_5to8(cgbColor >> 5),
|
||||
_5to8(cgbColor >> 10),
|
||||
(uint8_t)(cgbColor & 0x8000 ? 0x00 : 0xFF),
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns this RGBA as a 32-bit number that can be printed in hex (`%08x`) to yield its CSS
|
||||
* representation
|
||||
*/
|
||||
uint32_t toCSS() const {
|
||||
auto shl = [](uint8_t val, unsigned shift) { return static_cast<uint32_t>(val) << shift; };
|
||||
return shl(red, 24) | shl(green, 16) | shl(blue, 8) | shl(alpha, 0);
|
||||
}
|
||||
friend bool operator==(Rgba const &lhs, Rgba const &rhs) { return lhs.toCSS() == rhs.toCSS(); }
|
||||
friend bool operator!=(Rgba const &lhs, Rgba const &rhs) { return lhs.toCSS() != rhs.toCSS(); }
|
||||
|
||||
/*
|
||||
* CGB colors are RGB555, so we use bit 15 to signify that the color is transparent instead
|
||||
* Since the rest of the bits don't matter then, we return 0x8000 exactly.
|
||||
*/
|
||||
static constexpr uint16_t transparent = 0b1'00000'00000'00000;
|
||||
|
||||
static constexpr uint8_t transparency_threshold = 0x10;
|
||||
bool isTransparent() const { return alpha < transparency_threshold; }
|
||||
static constexpr uint8_t opacity_threshold = 0xF0;
|
||||
bool isOpaque() const { return alpha >= opacity_threshold; }
|
||||
/*
|
||||
* Computes the equivalent CGB color, respects the color curve depending on options
|
||||
*/
|
||||
uint16_t cgbColor() const;
|
||||
|
||||
bool isGray() const { return red == green && green == blue; }
|
||||
uint8_t grayIndex() const;
|
||||
};
|
||||
|
||||
#endif // RGBDS_GFX_RGBA_HPP
|
||||
77
include/hashmap.h
Normal file
77
include/hashmap.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 1997-2019, Carsten Sorensen and RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/* Generic hashmap implementation (C++ templates are calling...) */
|
||||
#ifndef RGBDS_LINK_HASHMAP_H
|
||||
#define RGBDS_LINK_HASHMAP_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define HASH_NB_BITS 32
|
||||
#define HALF_HASH_NB_BITS 16
|
||||
static_assert(HALF_HASH_NB_BITS * 2 == HASH_NB_BITS, "");
|
||||
#define HASHMAP_NB_BUCKETS (1 << HALF_HASH_NB_BITS)
|
||||
|
||||
/* HashMapEntry is internal, please do not attempt to use it */
|
||||
typedef struct HashMapEntry *HashMap[HASHMAP_NB_BUCKETS];
|
||||
|
||||
/**
|
||||
* Adds an element to a hashmap.
|
||||
* @warning Adding a new element with an already-present key will not cause an
|
||||
* error, this must be handled externally.
|
||||
* @warning Inserting a NULL will make `hash_GetElement`'s return ambiguous!
|
||||
* @param map The HashMap to add the element to
|
||||
* @param key The key with which the element will be stored and retrieved
|
||||
* @param element The element to add
|
||||
* @return A pointer to the pointer to the element.
|
||||
*/
|
||||
void **hash_AddElement(HashMap map, char const *key, void *element);
|
||||
|
||||
/**
|
||||
* Removes an element from a hashmap.
|
||||
* @param map The HashMap to remove the element from
|
||||
* @param key The key to search the element with
|
||||
* @return True if the element was found and removed
|
||||
*/
|
||||
bool hash_RemoveElement(HashMap map, char const *key);
|
||||
|
||||
/**
|
||||
* Finds an element in a hashmap, and returns a pointer to its value field.
|
||||
* @param map The map to consider the elements of
|
||||
* @param key The key to search an element for
|
||||
* @return A pointer to the pointer to the element, or NULL if not found.
|
||||
*/
|
||||
void **hash_GetNode(HashMap const map, char const *key);
|
||||
|
||||
/**
|
||||
* Finds an element in a hashmap.
|
||||
* @param map The map to consider the elements of
|
||||
* @param key The key to search an element for
|
||||
* @return A pointer to the element, or NULL if not found. (NULL can be returned
|
||||
* if such an element was added, but that sounds pretty silly.)
|
||||
*/
|
||||
void *hash_GetElement(HashMap const map, char const *key);
|
||||
|
||||
/**
|
||||
* Executes a function on each element in a hashmap.
|
||||
* @param map The map to consider the elements of
|
||||
* @param func The function to run. The first argument will be the element,
|
||||
* the second will be `arg`.
|
||||
* @param arg An argument to be passed to all function calls
|
||||
*/
|
||||
void hash_ForEach(HashMap const map, void (*func)(void *, void *), void *arg);
|
||||
|
||||
/**
|
||||
* Cleanly empties a hashmap from its contents.
|
||||
* This does not `free` the data structure itself!
|
||||
* @param map The map to empty
|
||||
*/
|
||||
void hash_EmptyMap(HashMap map);
|
||||
|
||||
#endif /* RGBDS_LINK_HASHMAP_H */
|
||||
96
include/helpers.h
Normal file
96
include/helpers.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* This file is part of RGBDS.
|
||||
*
|
||||
* Copyright (c) 2014-2020, RGBDS contributors.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef HELPERS_H
|
||||
#define HELPERS_H
|
||||
|
||||
// Of course, MSVC does not support C11, so no _Noreturn there...
|
||||
#ifdef _MSC_VER
|
||||
#define _Noreturn __declspec(noreturn)
|
||||
#endif
|
||||
|
||||
// Ideally, we'd use `__has_attribute` and `__has_builtin`, but these were only introduced in GCC 9
|
||||
#ifdef __GNUC__ // GCC or compatible
|
||||
#define format_(archetype, str_index, first_arg) \
|
||||
__attribute__ ((format (archetype, str_index, first_arg)))
|
||||
#define attr_(...) __attribute__ ((__VA_ARGS__))
|
||||
// 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)
|
||||
#define attr_(...)
|
||||
// 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
|
||||
|
||||
// Use builtins whenever possible, and shim them otherwise
|
||||
#ifdef __GNUC__ // GCC or compatible
|
||||
#define ctz __builtin_ctz
|
||||
#define clz __builtin_clz
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
#include <assert.h>
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanReverse, _BitScanForward)
|
||||
static inline int ctz(unsigned int x)
|
||||
{
|
||||
unsigned long cnt;
|
||||
|
||||
assert(x != 0);
|
||||
_BitScanForward(&cnt, x);
|
||||
return cnt;
|
||||
}
|
||||
static inline int clz(unsigned int x)
|
||||
{
|
||||
unsigned long cnt;
|
||||
|
||||
assert(x != 0);
|
||||
_BitScanReverse(&cnt, x);
|
||||
return 31 - cnt;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <limits.h>
|
||||
static inline int ctz(unsigned int x)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
while (!(x & 1)) {
|
||||
x >>= 1;
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static inline int clz(unsigned int x)
|
||||
{
|
||||
int cnt = 0;
|
||||
|
||||
while (x <= UINT_MAX / 2) {
|
||||
x <<= 1;
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Macros for stringification
|
||||
#define STR(x) #x
|
||||
#define EXPAND_AND_STR(x) STR(x)
|
||||
|
||||
// Obtaining the size of an array; `arr` must be an expression, not a type!
|
||||
// (Having two instances of `arr` is OK because the contents of `sizeof` are not evaluated.)
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof *(arr))
|
||||
|
||||
#endif /* HELPERS_H */
|
||||
@@ -1,114 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_HELPERS_HPP
|
||||
#define RGBDS_HELPERS_HPP
|
||||
|
||||
// Ideally we'd use `std::unreachable`, but it has insufficient compiler support
|
||||
#ifdef __GNUC__ // GCC or compatible
|
||||
#ifdef NDEBUG
|
||||
#define unreachable_ __builtin_unreachable
|
||||
#else
|
||||
// In release builds, define "unreachable" as such, but trap in debug builds
|
||||
#define unreachable_ __builtin_trap
|
||||
#endif
|
||||
#else
|
||||
// This seems to generate similar code to __builtin_unreachable, despite different semantics
|
||||
// Note that executing this is undefined behavior (declared [[noreturn]], but does return)
|
||||
[[noreturn]] static inline void unreachable_() {
|
||||
}
|
||||
#endif
|
||||
|
||||
// Ideally we'd use `[[assume()]]`, but it has insufficient compiler support
|
||||
#ifdef NDEBUG
|
||||
#ifdef _MSC_VER
|
||||
#define assume(x) __assume(x)
|
||||
#else
|
||||
// `[[gnu::assume()]]` for GCC or compatible also has insufficient support (GCC 13+ only)
|
||||
#define assume(x) \
|
||||
do { \
|
||||
if (!(x)) \
|
||||
unreachable_(); \
|
||||
} while (0)
|
||||
#endif
|
||||
#else
|
||||
// In release builds, define "assume" as such, but `assert` in debug builds
|
||||
#include <assert.h>
|
||||
#define assume assert
|
||||
#endif
|
||||
|
||||
// Ideally we'd use `std::bit_width`, but it has insufficient compiler support
|
||||
#ifdef __GNUC__ // GCC or compatible
|
||||
#define ctz __builtin_ctz
|
||||
#define clz __builtin_clz
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_BitScanReverse, _BitScanForward)
|
||||
|
||||
static inline int ctz(unsigned int x) {
|
||||
unsigned long cnt;
|
||||
|
||||
assume(x != 0);
|
||||
_BitScanForward(&cnt, x);
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static inline int clz(unsigned int x) {
|
||||
unsigned long cnt;
|
||||
|
||||
assume(x != 0);
|
||||
_BitScanReverse(&cnt, x);
|
||||
return 31 - cnt;
|
||||
}
|
||||
|
||||
#else
|
||||
#include <limits.h>
|
||||
|
||||
static inline int ctz(unsigned int x) {
|
||||
int cnt = 0;
|
||||
|
||||
while (!(x & 1)) {
|
||||
x >>= 1;
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static inline int clz(unsigned int x) {
|
||||
int cnt = 0;
|
||||
|
||||
while (x <= UINT_MAX / 2) {
|
||||
x <<= 1;
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Macros for stringification
|
||||
#define STR(x) #x
|
||||
#define EXPAND_AND_STR(x) STR(x)
|
||||
|
||||
// Macros for concatenation
|
||||
#define CAT(x, y) x##y
|
||||
#define EXPAND_AND_CAT(x, y) CAT(x, y)
|
||||
|
||||
// Obtaining the size of an array; `arr` must be an expression, not a type!
|
||||
// (Having two instances of `arr` is OK because the contents of `sizeof` are not evaluated.)
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof *(arr))
|
||||
|
||||
// For lack of <ranges>, this adds some more brevity
|
||||
#define RANGE(s) std::begin(s), std::end(s)
|
||||
|
||||
// MSVC does not inline `strlen()` or `.length()` of a constant string, so we use `sizeof`
|
||||
#define QUOTEDSTRLEN(s) (sizeof(s) - 1)
|
||||
|
||||
// For ad-hoc RAII in place of a `defer` statement or cross-platform `__attribute__((cleanup))`
|
||||
template<typename T>
|
||||
struct Defer {
|
||||
T deferred;
|
||||
Defer(T func) : deferred(func) {}
|
||||
~Defer() { deferred(); }
|
||||
};
|
||||
|
||||
#endif // RGBDS_HELPERS_HPP
|
||||
@@ -1,116 +0,0 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef RGBDS_ITERTOOLS_HPP
|
||||
#define RGBDS_ITERTOOLS_HPP
|
||||
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
template<typename T>
|
||||
class EnumSeqIterator {
|
||||
T _value;
|
||||
|
||||
public:
|
||||
explicit EnumSeqIterator(T value) : _value(value) {}
|
||||
|
||||
EnumSeqIterator &operator++() {
|
||||
_value = (T)(_value + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator*() const { return _value; }
|
||||
|
||||
friend auto operator==(EnumSeqIterator const &lhs, EnumSeqIterator const &rhs) {
|
||||
return lhs._value == rhs._value;
|
||||
}
|
||||
|
||||
friend auto operator!=(EnumSeqIterator const &lhs, EnumSeqIterator const &rhs) {
|
||||
return lhs._value != rhs._value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class EnumSeq {
|
||||
T _start;
|
||||
T _stop;
|
||||
|
||||
public:
|
||||
explicit EnumSeq(T stop) : _start((T)0), _stop(stop) {}
|
||||
explicit EnumSeq(T start, T stop) : _start(start), _stop(stop) {}
|
||||
|
||||
EnumSeqIterator<T> begin() { return EnumSeqIterator(_start); }
|
||||
EnumSeqIterator<T> end() { return EnumSeqIterator(_stop); }
|
||||
};
|
||||
|
||||
// This is not a fully generic implementation; its current use cases only require for-loop behavior.
|
||||
// We also assume that all iterators have the same length.
|
||||
template<typename... Iters>
|
||||
class Zip {
|
||||
std::tuple<Iters...> _iters;
|
||||
|
||||
public:
|
||||
explicit Zip(std::tuple<Iters...> &&iters) : _iters(iters) {}
|
||||
|
||||
Zip &operator++() {
|
||||
std::apply([](auto &&...it) { (++it, ...); }, _iters);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator*() const {
|
||||
return std::apply(
|
||||
[](auto &&...it) { return std::tuple<decltype(*it)...>(*it...); }, _iters
|
||||
);
|
||||
}
|
||||
|
||||
friend auto operator==(Zip const &lhs, Zip const &rhs) {
|
||||
return std::get<0>(lhs._iters) == std::get<0>(rhs._iters);
|
||||
}
|
||||
|
||||
friend auto operator!=(Zip const &lhs, Zip const &rhs) {
|
||||
return std::get<0>(lhs._iters) != std::get<0>(rhs._iters);
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
template<typename... Containers>
|
||||
class ZipContainer {
|
||||
std::tuple<Containers...> _containers;
|
||||
|
||||
public:
|
||||
explicit ZipContainer(Containers &&...containers)
|
||||
: _containers(std::forward<Containers>(containers)...) {}
|
||||
|
||||
auto begin() {
|
||||
return Zip(std::apply(
|
||||
[](auto &&...containers) {
|
||||
using std::begin;
|
||||
return std::make_tuple(begin(containers)...);
|
||||
},
|
||||
_containers
|
||||
));
|
||||
}
|
||||
|
||||
auto end() {
|
||||
return Zip(std::apply(
|
||||
[](auto &&...containers) {
|
||||
using std::end;
|
||||
return std::make_tuple(end(containers)...);
|
||||
},
|
||||
_containers
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
// Take ownership of objects and rvalue refs passed to us, but not lvalue refs
|
||||
template<typename T>
|
||||
using Holder = std::
|
||||
conditional_t<std::is_lvalue_reference_v<T>, T, std::remove_cv_t<std::remove_reference_t<T>>>;
|
||||
} // namespace detail
|
||||
|
||||
// Does the same number of iterations as the first container's iterator!
|
||||
template<typename... Containers>
|
||||
static constexpr auto zip(Containers &&...cs) {
|
||||
return detail::ZipContainer<detail::Holder<Containers>...>(std::forward<Containers>(cs)...);
|
||||
}
|
||||
|
||||
#endif // RGBDS_ITERTOOLS_HPP
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user