mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 10:42:07 +00:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69a573923f | ||
|
|
7eb4ecea8b | ||
|
|
599ce757a1 | ||
|
|
75a07a90f8 | ||
|
|
ec2d1312ef | ||
|
|
03b6dd9321 | ||
|
|
a16d3d6405 | ||
|
|
3e5cd8ce1a | ||
|
|
6902387991 | ||
|
|
62b4f2b264 | ||
|
|
79748afdc4 | ||
|
|
32cb0558e4 | ||
|
|
92b2ac3c8c | ||
|
|
0e67298dff | ||
|
|
f6d218ed36 | ||
|
|
1a9fc964df | ||
|
|
48248faab0 | ||
|
|
58181c2d73 | ||
|
|
0f86084e08 | ||
|
|
c8e602dec1 | ||
|
|
b168717e91 | ||
|
|
930c2ac328 | ||
|
|
28737d5778 | ||
|
|
12ba057b4f | ||
|
|
0e0876b17f | ||
|
|
b28eea24fc | ||
|
|
a1e59ddc3d | ||
|
|
3fbdba31bf | ||
|
|
d90a7e4302 | ||
|
|
7377a14245 | ||
|
|
e2136d60b2 | ||
|
|
74e40654e6 |
23
.github/scripts/get_win_deps.ps1
vendored
Normal file
23
.github/scripts/get_win_deps.ps1
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
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/zlib1213.zip' 'zlib.zip' 'd233fca7cf68db4c16dc5287af61f3cd01ab62495224c66639ca3da537701e42' .
|
||||||
|
getlibrary 'https://download.sourceforge.net/libpng/lpng1637.zip' 'libpng.zip' '3b4b1cbd0bae6822f749d39b1ccadd6297f05e2b85a83dd2ce6ecd7d09eabdf2' .
|
||||||
|
getlibrary 'https://github.com/lexxmark/winflexbison/releases/download/v2.5.24/win_flex_bison-2.5.24.zip' 'winflexbison.zip' '39c6086ce211d5415500acc5ed2d8939861ca1696aee48909c7f6daf5122b505' install_dir
|
||||||
|
|
||||||
|
Move-Item zlib-1.2.13 zlib
|
||||||
|
Move-Item lpng1637 libpng
|
||||||
6
.github/scripts/install.sh
vendored
Executable file
6
.github/scripts/install.sh
vendored
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/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/
|
||||||
@@ -9,7 +9,7 @@ arch="$1"
|
|||||||
|
|
||||||
wget http://downloads.sourceforge.net/project/libpng/libpng16/$pngver/libpng-$pngver.tar.xz
|
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
|
wget http://downloads.sourceforge.net/project/apng/libpng/libpng16/libpng-$pngver-apng.patch.gz
|
||||||
sha256sum -c .github/actions/mingw-w64-libpng-dev.sha256sums
|
sha256sum -c .github/scripts/mingw-w64-libpng-dev.sha256sums
|
||||||
|
|
||||||
## Extract sources and patch them
|
## Extract sources and patch them
|
||||||
|
|
||||||
159
.github/workflows/create-release-artifacts.yaml
vendored
159
.github/workflows/create-release-artifacts.yaml
vendored
@@ -7,77 +7,107 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
windows:
|
windows:
|
||||||
runs-on: windows-2022
|
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@v3
|
||||||
|
- name: Install deps
|
||||||
|
run: .github/scripts/get_win_deps.ps1
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
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 -DPNG_BUILD_ZLIB=ON -DZLIB_INCLUDE_DIR="$PWD"/install_dir/include -DZLIB_LIBRARY="$PWD"/install_dir/lib/zlib.lib
|
||||||
|
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 -DZLIB_LIBRARY="$PWD"/install_dir/lib/zlib.lib -DZLIB_INCLUDE_DIR="$PWD"/install_dir/include -DPNG_LIBRARY="$PWD"/install_dir/lib/libpng16.lib -DPNG_INCLUDE_DIR="$PWD"/install_dir/include
|
||||||
|
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@v3
|
||||||
|
with:
|
||||||
|
name: win${{ matrix.bits }}
|
||||||
|
path: rgbds-${{ env.version }}-win${{ matrix.bits }}.zip
|
||||||
|
|
||||||
|
macos:
|
||||||
|
runs-on: macos-12
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Get version from tag
|
- name: Get version from tag
|
||||||
shell: bash
|
shell: bash
|
||||||
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
|
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
|
||||||
VERSION="${{ github.ref }}"
|
VERSION="${{ github.ref_name }}"
|
||||||
echo "version=${VERSION##*/v}" >> $GITHUB_ENV
|
echo "version=${VERSION#v}" >> $GITHUB_ENV
|
||||||
- name: Get zlib, libpng and bison
|
- uses: actions/checkout@v3
|
||||||
run: | # TODO: use an array
|
- name: Install deps
|
||||||
$wc = New-Object System.Net.WebClient
|
shell: bash
|
||||||
$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: |
|
run: |
|
||||||
cmake -S libpng -B pngbuild32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
|
./.github/scripts/install_deps.sh macos-latest
|
||||||
cmake --build pngbuild32 --config Release
|
# We force linking libpng statically; the other libs are provided by macOS itself
|
||||||
cmake --install pngbuild32
|
- name: Build binaries
|
||||||
- name: Build 32-bit Windows binaries
|
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B build32 -A Win32 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
|
export PATH="/usr/local/opt/bison/bin:$PATH"
|
||||||
cmake --build build32 --config Release
|
make -j WARNFLAGS="-Wall -Wextra -mmacosx-version-min=10.9" PKG_CONFIG="pkg-config --static" PNGLDLIBS="$(pkg-config --static --libs-only-L libpng | cut -c 3-)/libpng.a $(pkg-config --static --libs-only-l libpng | sed s/-lpng[0-9]*//g)" Q=
|
||||||
cmake --install build32
|
- name: Package binaries
|
||||||
- name: Package 32-bit binaries
|
|
||||||
run: |
|
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"
|
zip --junk-paths rgbds-${{ env.version }}-macos-x86-64.zip rgb{asm,link,fix,gfx} man/* .github/scripts/install.sh
|
||||||
- name: Build 64-bit zlib
|
- name: Upload macOS binaries
|
||||||
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
|
uses: actions/upload-artifact@v3
|
||||||
cmake -S zlib -B zbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
with:
|
||||||
cmake --build zbuild64 --config Release
|
name: macos
|
||||||
cmake --install zbuild64
|
path: rgbds-${{ env.version }}-macos-x86-64.zip
|
||||||
- name: Build 64-bit libpng
|
|
||||||
run: |
|
release:
|
||||||
cmake -S libpng -B pngbuild64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
|
runs-on: ubuntu-latest
|
||||||
cmake --build pngbuild64 --config Release
|
needs: [windows, macos]
|
||||||
cmake --install pngbuild64
|
steps:
|
||||||
- name: Build 64-bit Windows binaries
|
- name: Get version from tag
|
||||||
run: |
|
shell: bash
|
||||||
cmake -S . -B build64 -A x64 -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
|
run: | # Turn "refs/tags/vX.Y.Z" into "X.Y.Z"
|
||||||
cmake --build build64 --config Release
|
VERSION="${{ github.ref_name }}"
|
||||||
cmake --install build64
|
echo "version=${VERSION#v}" >> $GITHUB_ENV
|
||||||
- name: Package 64-bit binaries
|
- uses: actions/checkout@v3
|
||||||
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
|
- name: Package sources
|
||||||
run: |
|
run: |
|
||||||
make dist
|
make dist Q=
|
||||||
|
ls
|
||||||
|
- uses: actions/download-artifact@v3
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: softprops/action-gh-release@v1
|
uses: softprops/action-gh-release@v1
|
||||||
with:
|
with:
|
||||||
@@ -88,8 +118,9 @@ jobs:
|
|||||||
draft: true # Don't publish the release quite yet...
|
draft: true # Don't publish the release quite yet...
|
||||||
prerelease: ${{ contains(github.ref, '-rc') }}
|
prerelease: ${{ contains(github.ref, '-rc') }}
|
||||||
files: |
|
files: |
|
||||||
rgbds-${{ env.version }}-win32.zip
|
win32/rgbds-${{ env.version }}-win32.zip
|
||||||
rgbds-${{ env.version }}-win64.zip
|
win64/rgbds-${{ env.version }}-win64.zip
|
||||||
|
macos/rgbds-${{ env.version }}-macos-x86-64.zip
|
||||||
rgbds-${{ env.version }}.tar.gz
|
rgbds-${{ env.version }}.tar.gz
|
||||||
fail_on_unmatched_files: true
|
fail_on_unmatched_files: true
|
||||||
env:
|
env:
|
||||||
|
|||||||
6
.github/workflows/create-release-docs.yml
vendored
6
.github/workflows/create-release-docs.yml
vendored
@@ -10,11 +10,11 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout rgbds@release
|
- name: Checkout rgbds@release
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
path: rgbds
|
path: rgbds
|
||||||
- name: Checkout rgbds-www@master
|
- name: Checkout rgbds-www@master
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: ${{ github.repository_owner }}/rgbds-www
|
repository: ${{ github.repository_owner }}/rgbds-www
|
||||||
path: rgbds-www
|
path: rgbds-www
|
||||||
@@ -25,7 +25,7 @@ jobs:
|
|||||||
- name: Update pages
|
- name: Update pages
|
||||||
working-directory: rgbds/man
|
working-directory: rgbds/man
|
||||||
run: | # The ref appears to be in the format "refs/tags/<version>", so strip that
|
run: | # The ref appears to be in the format "refs/tags/<version>", so strip that
|
||||||
../../rgbds-www/.github/actions/get-pages.sh ${GITHUB_REF##*/} *
|
../../rgbds-www/maintainer/man_to_html.sh ${GITHUB_REF##*/} *
|
||||||
- name: Push new pages
|
- name: Push new pages
|
||||||
working-directory: rgbds-www
|
working-directory: rgbds-www
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
108
.github/workflows/testing.yml
vendored
108
.github/workflows/testing.yml
vendored
@@ -24,11 +24,11 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
./.github/actions/install_deps.sh ${{ matrix.os }}
|
./.github/scripts/install_deps.sh ${{ matrix.os }}
|
||||||
# The `export` lines are to allow working on macOS...
|
# The `export` lines are to allow working on macOS...
|
||||||
# Apple's base version is severely outdated, not even supporting -Wall,
|
# Apple's base version is severely outdated, not even supporting -Wall,
|
||||||
# but it overrides Homebrew's version nonetheless...
|
# but it overrides Homebrew's version nonetheless...
|
||||||
@@ -55,6 +55,25 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: rgbds-canary-${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.buildsys }}
|
name: rgbds-canary-${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.buildsys }}
|
||||||
path: bins
|
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@v3
|
||||||
|
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: Test
|
- name: Test
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -75,32 +94,9 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Get zlib, libpng and bison
|
- name: Install deps
|
||||||
run: | # TODO: use an array; remember to update the versions being downloaded, *and* the paths being extracted! (`Move-Item`)
|
run: .github/scripts/get_win_deps.ps1
|
||||||
$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
|
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
id: cache
|
id: cache
|
||||||
with:
|
with:
|
||||||
@@ -110,23 +106,25 @@ jobs:
|
|||||||
key: ${{ matrix.arch }}-${{ hashFiles('zlib/**', 'libpng/**') }}
|
key: ${{ matrix.arch }}-${{ hashFiles('zlib/**', 'libpng/**') }}
|
||||||
- name: Build zlib
|
- name: Build zlib
|
||||||
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
|
run: | # BUILD_SHARED_LIBS causes the output DLL to be correctly called `zlib1.dll`
|
||||||
cmake -S zlib -B zbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
cmake -S zlib -B zbuild -A ${{ matrix.platform }} -Wno-dev -DCMAKE_INSTALL_PREFIX=install_dir -DBUILD_SHARED_LIBS=ON
|
||||||
cmake --build zbuild --config Release -j
|
cmake --build zbuild --config Release -j
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
if: steps.cache.outputs.cache-hit != 'true'
|
||||||
- name: Install zlib
|
- name: Install zlib
|
||||||
run: |
|
run: |
|
||||||
cmake --install zbuild
|
cmake --install zbuild
|
||||||
- name: Build libpng
|
- name: Build libpng
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cmake -S libpng -B pngbuild -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=ON -DPNG_TESTS=OFF
|
cmake -S libpng -B pngbuild -A ${{ matrix.platform }} -Wno-dev -DCMAKE_INSTALL_PREFIX=install_dir -DPNG_SHARED=ON -DPNG_STATIC=OFF -DPNG_TESTS=OFF -DPNG_BUILD_ZLIB=ON -DZLIB_INCLUDE_DIR="$PWD"/install_dir/include -DZLIB_LIBRARY="$PWD"/install_dir/lib/zlib.lib
|
||||||
cmake --build pngbuild --config Release -j
|
cmake --build pngbuild --config Release -j
|
||||||
if: steps.cache.outputs.cache-hit != 'true'
|
if: steps.cache.outputs.cache-hit != 'true'
|
||||||
- name: Install libpng
|
- name: Install libpng
|
||||||
run: |
|
run: |
|
||||||
cmake --install pngbuild
|
cmake --install pngbuild
|
||||||
- name: Build Windows binaries
|
- name: Build Windows binaries
|
||||||
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cmake -S . -B build -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release
|
cmake -S . -B build -A ${{ matrix.platform }} -DCMAKE_INSTALL_PREFIX=install_dir -DCMAKE_BUILD_TYPE=Release -DZLIB_LIBRARY="$PWD"/install_dir/lib/zlib.lib -DZLIB_INCLUDE_DIR="$PWD"/install_dir/include -DPNG_LIBRARY="$PWD"/install_dir/lib/libpng16.lib -DPNG_INCLUDE_DIR="$PWD"/install_dir/include
|
||||||
cmake --build build --config Release -j --verbose
|
cmake --build build --config Release -j --verbose
|
||||||
cmake --install build --verbose --prefix install_dir
|
cmake --install build --verbose --prefix install_dir
|
||||||
- name: Package binaries
|
- name: Package binaries
|
||||||
@@ -139,6 +137,26 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: rgbds-canary-win${{ matrix.bits }}
|
name: rgbds-canary-win${{ matrix.bits }}
|
||||||
path: bins
|
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@v3
|
||||||
|
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: Test
|
- name: Test
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -162,17 +180,17 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
DIST_DIR: win${{ matrix.bits }}
|
DIST_DIR: win${{ matrix.bits }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Install deps
|
- name: Install deps
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
./.github/actions/install_deps.sh ${{ matrix.os }}
|
./.github/scripts/install_deps.sh ${{ matrix.os }}
|
||||||
- name: Install MinGW
|
- name: Install MinGW
|
||||||
run: | # dpkg-dev is apparently required for pkg-config for cross-building
|
run: | # dpkg-dev is apparently required for pkg-config for cross-building
|
||||||
sudo apt-get install {gcc,g++}-mingw-w64-${{ matrix.arch }}-win32 mingw-w64-tools libz-mingw-w64-dev dpkg-dev
|
sudo apt-get install {gcc,g++}-mingw-w64-${{ matrix.arch }}-win32 mingw-w64-tools libz-mingw-w64-dev dpkg-dev
|
||||||
- name: Install libpng dev headers for MinGW
|
- name: Install libpng dev headers for MinGW
|
||||||
run: |
|
run: |
|
||||||
sudo ./.github/actions/mingw-w64-libpng-dev.sh ${{ matrix.triplet }}
|
sudo ./.github/scripts/mingw-w64-libpng-dev.sh ${{ matrix.triplet }}
|
||||||
- name: Cross-build Windows binaries
|
- name: Cross-build Windows binaries
|
||||||
run: |
|
run: |
|
||||||
make mingw${{ matrix.bits }} -j Q=
|
make mingw${{ matrix.bits }} -j Q=
|
||||||
@@ -205,7 +223,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Retrieve binaries
|
- name: Retrieve binaries
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
@@ -221,6 +239,26 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cp bins/* .
|
cp bins/* .
|
||||||
cp bins/*.dll test/gfx
|
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@v3
|
||||||
|
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: Run tests
|
- name: Run tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
4
.github/workflows/update-master-docs.yml
vendored
4
.github/workflows/update-master-docs.yml
vendored
@@ -20,13 +20,13 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout rgbds@master
|
- name: Checkout rgbds@master
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: gbdev/rgbds
|
repository: gbdev/rgbds
|
||||||
ref: master
|
ref: master
|
||||||
path: rgbds
|
path: rgbds
|
||||||
- name: Checkout rgbds-www@master
|
- name: Checkout rgbds-www@master
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
repository: gbdev/rgbds-www
|
repository: gbdev/rgbds-www
|
||||||
ref: master
|
ref: master
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ else()
|
|||||||
-fsanitize=alignment -fsanitize=null -fsanitize=address)
|
-fsanitize=alignment -fsanitize=null -fsanitize=address)
|
||||||
add_compile_options(${SAN_FLAGS})
|
add_compile_options(${SAN_FLAGS})
|
||||||
add_link_options(${SAN_FLAGS})
|
add_link_options(${SAN_FLAGS})
|
||||||
|
add_definitions(-D_GLIBCXX_ASSERTIONS)
|
||||||
# A non-zero optimization level is desired in debug mode, but allow overriding it nonetheless
|
# 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!
|
# TODO: this overrides anything previously set... that's a bit sloppy!
|
||||||
set(CMAKE_C_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)
|
||||||
|
|||||||
27
Makefile
27
Makefile
@@ -35,8 +35,8 @@ VERSION_STRING := `git describe --tags --dirty --always 2>/dev/null`
|
|||||||
WARNFLAGS := -Wall -pedantic
|
WARNFLAGS := -Wall -pedantic
|
||||||
|
|
||||||
# Overridable CFLAGS
|
# Overridable CFLAGS
|
||||||
CFLAGS ?= -O3 -flto=auto -DNDEBUG
|
CFLAGS ?= -O3 -flto -DNDEBUG
|
||||||
CXXFLAGS ?= -O3 -flto=auto -DNDEBUG
|
CXXFLAGS ?= -O3 -flto -DNDEBUG
|
||||||
# Non-overridable CFLAGS
|
# Non-overridable CFLAGS
|
||||||
# _ISOC11_SOURCE is required on certain platforms to get C11 on top of the C99-based POSIX 2008
|
# _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 \
|
REALCFLAGS := ${CFLAGS} ${WARNFLAGS} -std=gnu11 -I include \
|
||||||
@@ -130,7 +130,7 @@ rgbfix: ${rgbfix_obj}
|
|||||||
$Q${CC} ${REALLDFLAGS} -o $@ ${rgbfix_obj} ${REALCFLAGS} src/version.c
|
$Q${CC} ${REALLDFLAGS} -o $@ ${rgbfix_obj} ${REALCFLAGS} src/version.c
|
||||||
|
|
||||||
rgbgfx: ${rgbgfx_obj}
|
rgbgfx: ${rgbgfx_obj}
|
||||||
$Q${CXX} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${REALCXXFLAGS} -x c++ src/version.c ${PNGLDLIBS}
|
$Q${CXX} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${REALCXXFLAGS} ${PNGLDLIBS} -x c++ src/version.c
|
||||||
|
|
||||||
test/gfx/randtilegen: test/gfx/randtilegen.c
|
test/gfx/randtilegen: test/gfx/randtilegen.c
|
||||||
$Q${CC} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ $^ ${REALCFLAGS} ${PNGCFLAGS} ${PNGLDLIBS}
|
$Q${CC} ${REALLDFLAGS} ${PNGLDFLAGS} -o $@ $^ ${REALCFLAGS} ${PNGCFLAGS} ${PNGLDLIBS}
|
||||||
@@ -183,21 +183,11 @@ clean:
|
|||||||
# Target used to install the binaries and man pages.
|
# Target used to install the binaries and man pages.
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
$Qmkdir -p ${DESTDIR}${bindir}
|
$Qinstall -d ${DESTDIR}${bindir}/ ${DESTDIR}${mandir}/man1/ ${DESTDIR}${mandir}/man5/ ${DESTDIR}${mandir}/man7/
|
||||||
$Qinstall ${STRIP} -m ${BINMODE} rgbasm ${DESTDIR}${bindir}/rgbasm
|
$Qinstall ${STRIP} -m ${BINMODE} rgbasm rgblink rgbfix rgbgfx ${DESTDIR}${bindir}/
|
||||||
$Qinstall ${STRIP} -m ${BINMODE} rgbfix ${DESTDIR}${bindir}/rgbfix
|
$Qinstall -m ${MANMODE} man/rgbasm.1 man/rgblink.1 man/rgbfix.1 man/rgbgfx.1 ${DESTDIR}${mandir}/man1/
|
||||||
$Qinstall ${STRIP} -m ${BINMODE} rgblink ${DESTDIR}${bindir}/rgblink
|
$Qinstall -m ${MANMODE} man/rgbds.5 man/rgbasm.5 man/rgblink.5 ${DESTDIR}${mandir}/man5/
|
||||||
$Qinstall ${STRIP} -m ${BINMODE} rgbgfx ${DESTDIR}${bindir}/rgbgfx
|
$Qinstall -m ${MANMODE} man/rgbds.7 man/gbz80.7 ${DESTDIR}${mandir}/man7/
|
||||||
$Qmkdir -p ${DESTDIR}${mandir}/man1 ${DESTDIR}${mandir}/man5 ${DESTDIR}${mandir}/man7
|
|
||||||
$Qinstall -m ${MANMODE} man/rgbds.7 ${DESTDIR}${mandir}/man7/rgbds.7
|
|
||||||
$Qinstall -m ${MANMODE} man/gbz80.7 ${DESTDIR}${mandir}/man7/gbz80.7
|
|
||||||
$Qinstall -m ${MANMODE} man/rgbds.5 ${DESTDIR}${mandir}/man5/rgbds.5
|
|
||||||
$Qinstall -m ${MANMODE} man/rgbasm.1 ${DESTDIR}${mandir}/man1/rgbasm.1
|
|
||||||
$Qinstall -m ${MANMODE} man/rgbasm.5 ${DESTDIR}${mandir}/man5/rgbasm.5
|
|
||||||
$Qinstall -m ${MANMODE} man/rgbfix.1 ${DESTDIR}${mandir}/man1/rgbfix.1
|
|
||||||
$Qinstall -m ${MANMODE} man/rgblink.1 ${DESTDIR}${mandir}/man1/rgblink.1
|
|
||||||
$Qinstall -m ${MANMODE} man/rgblink.5 ${DESTDIR}${mandir}/man5/rgblink.5
|
|
||||||
$Qinstall -m ${MANMODE} man/rgbgfx.1 ${DESTDIR}${mandir}/man1/rgbgfx.1
|
|
||||||
|
|
||||||
# Target used to check the coding style of the whole codebase.
|
# Target used to check the coding style of the whole codebase.
|
||||||
# `extern/` is excluded, as it contains external code that should not be patched
|
# `extern/` is excluded, as it contains external code that should not be patched
|
||||||
@@ -244,6 +234,7 @@ develop:
|
|||||||
-Wno-type-limits -Wno-tautological-constant-out-of-range-compare \
|
-Wno-type-limits -Wno-tautological-constant-out-of-range-compare \
|
||||||
-Wvla \
|
-Wvla \
|
||||||
-Wno-unknown-warning-option \
|
-Wno-unknown-warning-option \
|
||||||
|
-D_GLIBCXX_ASSERTIONS \
|
||||||
-fsanitize=shift -fsanitize=integer-divide-by-zero \
|
-fsanitize=shift -fsanitize=integer-divide-by-zero \
|
||||||
-fsanitize=unreachable -fsanitize=vla-bound \
|
-fsanitize=unreachable -fsanitize=vla-bound \
|
||||||
-fsanitize=signed-integer-overflow -fsanitize=bounds \
|
-fsanitize=signed-integer-overflow -fsanitize=bounds \
|
||||||
|
|||||||
103
include/file.hpp
Normal file
103
include/file.hpp
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of RGBDS.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2022, Eldred Habert and RGBDS contributors.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RGBDS_FILE_HPP
|
||||||
|
#define RGBDS_FILE_HPP
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <cassert>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <ios>
|
||||||
|
#include <iostream>
|
||||||
|
#include <streambuf>
|
||||||
|
#include <string>
|
||||||
|
#include <string.h>
|
||||||
|
#include <string_view>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "gfx/main.hpp"
|
||||||
|
|
||||||
|
// Convenience feature for visiting the below.
|
||||||
|
template<typename... Ts>
|
||||||
|
struct Visitor : Ts... {
|
||||||
|
using Ts::operator()...;
|
||||||
|
};
|
||||||
|
template<typename... Ts>
|
||||||
|
Visitor(Ts...) -> Visitor<Ts...>;
|
||||||
|
|
||||||
|
class File {
|
||||||
|
// Construct a `std::streambuf *` by default, since it's probably lighter than a `filebuf`.
|
||||||
|
std::variant<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 != "-") {
|
||||||
|
return _file.emplace<std::filebuf>().open(path, mode) ? this : nullptr;
|
||||||
|
} else if (mode & std::ios_base::in) {
|
||||||
|
assert(!(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 {
|
||||||
|
assert(mode & std::ios_base::out);
|
||||||
|
_file.emplace<std::streambuf *>(std::cout.rdbuf());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
std::streambuf &operator*() {
|
||||||
|
return std::visit(Visitor{[](std::filebuf &file) -> std::streambuf & { return file; },
|
||||||
|
[](std::streambuf *buf) -> std::streambuf & { return *buf; }},
|
||||||
|
_file);
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
return std::visit(Visitor{[this](std::filebuf &file) {
|
||||||
|
// This is called by the destructor, and an explicit `close`
|
||||||
|
// shouldn't close twice.
|
||||||
|
_file.emplace<std::streambuf *>(nullptr);
|
||||||
|
return file.close() != nullptr;
|
||||||
|
},
|
||||||
|
[](std::streambuf *buf) { return buf != nullptr; }},
|
||||||
|
_file)
|
||||||
|
? this
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *c_str(std::string const &path) const {
|
||||||
|
return std::visit(Visitor{[&path](std::filebuf const &) { return path.c_str(); },
|
||||||
|
[](std::streambuf const *buf) {
|
||||||
|
return buf == std::cin.rdbuf() ? "<stdin>" : "<stdout>";
|
||||||
|
}},
|
||||||
|
_file);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RGBDS_FILE_HPP
|
||||||
@@ -63,8 +63,10 @@
|
|||||||
# define O_RDWR _O_RDWR
|
# define O_RDWR _O_RDWR
|
||||||
# define S_ISREG(field) ((field) & _S_IFREG)
|
# define S_ISREG(field) ((field) & _S_IFREG)
|
||||||
# define O_BINARY _O_BINARY
|
# define O_BINARY _O_BINARY
|
||||||
|
# define O_TEXT _O_TEXT
|
||||||
#elif !defined(O_BINARY) // Cross-compilers define O_BINARY
|
#elif !defined(O_BINARY) // Cross-compilers define O_BINARY
|
||||||
# define O_BINARY 0 // POSIX says we shouldn't care!
|
# define O_BINARY 0 // POSIX says we shouldn't care!
|
||||||
|
# define O_TEXT 0 // Assume that it's not defined either
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
// Windows has stdin and stdout open as text by default, which we may not want
|
// Windows has stdin and stdout open as text by default, which we may not want
|
||||||
@@ -72,7 +74,7 @@
|
|||||||
# include <io.h>
|
# include <io.h>
|
||||||
# define setmode(fd, mode) _setmode(fd, mode)
|
# define setmode(fd, mode) _setmode(fd, mode)
|
||||||
#else
|
#else
|
||||||
# define setmode(fd, mode) ((void)0)
|
# define setmode(fd, mode) (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // RGBDS_PLATFORM_H
|
#endif // RGBDS_PLATFORM_H
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ extern "C" {
|
|||||||
|
|
||||||
#define PACKAGE_VERSION_MAJOR 0
|
#define PACKAGE_VERSION_MAJOR 0
|
||||||
#define PACKAGE_VERSION_MINOR 6
|
#define PACKAGE_VERSION_MINOR 6
|
||||||
#define PACKAGE_VERSION_PATCH 0
|
#define PACKAGE_VERSION_PATCH 1
|
||||||
|
|
||||||
char const *get_package_version_string(void);
|
char const *get_package_version_string(void);
|
||||||
|
|
||||||
|
|||||||
16
man/rgbgfx.1
16
man/rgbgfx.1
@@ -72,6 +72,18 @@ All of these are equivalent:
|
|||||||
.Ql 0X2A ,
|
.Ql 0X2A ,
|
||||||
.Ql 0x2a .
|
.Ql 0x2a .
|
||||||
.Pp
|
.Pp
|
||||||
|
Unless otherwise noted, passing
|
||||||
|
.Ql -
|
||||||
|
(a single dash) as a file name makes
|
||||||
|
.Nm
|
||||||
|
use standard input (for input files) or standard output (for output files).
|
||||||
|
To suppress this behavior, and open a file in the current directory actually called
|
||||||
|
.Ql - ,
|
||||||
|
pass
|
||||||
|
.Ql ./-
|
||||||
|
instead.
|
||||||
|
Using standard input or output more than once in a single command will likely produce unexpected results.
|
||||||
|
.Pp
|
||||||
The following options are accepted:
|
The following options are accepted:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl a Ar attrmap , Fl Fl attr-map Ar attrmap
|
.It Fl a Ar attrmap , Fl Fl attr-map Ar attrmap
|
||||||
@@ -145,7 +157,9 @@ The expected format is
|
|||||||
.Ql format:path ,
|
.Ql format:path ,
|
||||||
where
|
where
|
||||||
.Ar path
|
.Ar path
|
||||||
is a path to a file, which will be processed according to the
|
is a path to a file
|
||||||
|
.Ql ( -
|
||||||
|
is not treated specially), which will be processed according to the
|
||||||
.Ar format .
|
.Ar format .
|
||||||
See
|
See
|
||||||
.Sx PALETTE SPECIFICATION FORMATS
|
.Sx PALETTE SPECIFICATION FORMATS
|
||||||
|
|||||||
@@ -14,21 +14,20 @@ set(common_src
|
|||||||
"_version.c"
|
"_version.c"
|
||||||
)
|
)
|
||||||
|
|
||||||
find_package(BISON REQUIRED)
|
find_package(BISON 3.0.0 REQUIRED)
|
||||||
set(BISON_FLAGS "-Wall")
|
set(BISON_FLAGS "-Wall")
|
||||||
# Set sompe optimization flags on versions that support them
|
# Set some optimization flags on versions that support them
|
||||||
if(BISON_VERSION VERSION_GREATER_EQUAL "3.5")
|
if(BISON_VERSION VERSION_GREATER_EQUAL "3.5")
|
||||||
set(BISON_FLAGS "${BISON_FLAGS} -Dapi.token.raw=true")
|
set(BISON_FLAGS "${BISON_FLAGS} -Dapi.token.raw=true")
|
||||||
endif()
|
endif()
|
||||||
if(BISON_VERSION VERSION_GREATER_EQUAL "3.6")
|
if(BISON_VERSION VERSION_GREATER_EQUAL "3.6")
|
||||||
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=detailed")
|
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=detailed")
|
||||||
elseif(BISON_VERSION VERSION_GREATER_EQUAL "3.0")
|
else()
|
||||||
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=verbose")
|
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.error=verbose")
|
||||||
endif()
|
endif()
|
||||||
if(BISON_VERSION VERSION_GREATER_EQUAL "3.0")
|
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.lac=full")
|
||||||
set(BISON_FLAGS "${BISON_FLAGS} -Dparse.lac=full")
|
set(BISON_FLAGS "${BISON_FLAGS} -Dlr.type=ielr")
|
||||||
set(BISON_FLAGS "${BISON_FLAGS} -Dlr.type=ielr")
|
|
||||||
endif()
|
|
||||||
BISON_TARGET(PARSER "asm/parser.y"
|
BISON_TARGET(PARSER "asm/parser.y"
|
||||||
"${PROJECT_SOURCE_DIR}/src/asm/parser.c"
|
"${PROJECT_SOURCE_DIR}/src/asm/parser.c"
|
||||||
COMPILE_FLAGS "${BISON_FLAGS}"
|
COMPILE_FLAGS "${BISON_FLAGS}"
|
||||||
|
|||||||
@@ -359,10 +359,10 @@ int main(int argc, char *argv[])
|
|||||||
targetFileName[targetFileNameLen - 1] = '\0'; // Overwrite the last space
|
targetFileName[targetFileNameLen - 1] = '\0'; // Overwrite the last space
|
||||||
|
|
||||||
if (argc == musl_optind) {
|
if (argc == musl_optind) {
|
||||||
fputs("FATAL: No input files\n", stderr);
|
fputs("FATAL: Please specify an input file (pass `-` to read from standard input)\n", stderr);
|
||||||
print_usage();
|
print_usage();
|
||||||
} else if (argc != musl_optind + 1) {
|
} else if (argc != musl_optind + 1) {
|
||||||
fputs("FATAL: More than one input file given\n", stderr);
|
fputs("FATAL: More than one input file specified\n", stderr);
|
||||||
print_usage();
|
print_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -690,17 +690,19 @@ asmfile : lines
|
|||||||
;
|
;
|
||||||
|
|
||||||
lines : %empty
|
lines : %empty
|
||||||
| lines line
|
| lines opt_diff_mark line
|
||||||
;
|
;
|
||||||
|
|
||||||
endofline : T_NEWLINE | T_EOB
|
endofline : T_NEWLINE | T_EOB
|
||||||
;
|
;
|
||||||
|
|
||||||
plain_directive : label
|
opt_diff_mark : %empty // OK
|
||||||
| label cpu_command
|
| T_OP_ADD {
|
||||||
| label macro
|
error("syntax error, unexpected + at the beginning of the line (is it a leftover diff mark?)\n");
|
||||||
| label directive
|
}
|
||||||
| assignment_directive
|
| T_OP_SUB {
|
||||||
|
error("syntax error, unexpected - at the beginning of the line (is it a leftover diff mark?)\n");
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
line : plain_directive endofline
|
line : plain_directive endofline
|
||||||
@@ -786,6 +788,13 @@ else : T_POP_ELSE T_NEWLINE {
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
plain_directive : label
|
||||||
|
| label cpu_command
|
||||||
|
| label macro
|
||||||
|
| label directive
|
||||||
|
| assignment_directive
|
||||||
|
;
|
||||||
|
|
||||||
endc : T_POP_ENDC {
|
endc : T_POP_ENDC {
|
||||||
lexer_DecIFDepth();
|
lexer_DecIFDepth();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1174,8 +1174,8 @@ static bool processFilename(char const *name)
|
|||||||
{
|
{
|
||||||
nbErrors = 0;
|
nbErrors = 0;
|
||||||
if (!strcmp(name, "-")) {
|
if (!strcmp(name, "-")) {
|
||||||
setmode(STDIN_FILENO, O_BINARY);
|
(void)setmode(STDIN_FILENO, O_BINARY);
|
||||||
setmode(STDOUT_FILENO, O_BINARY);
|
(void)setmode(STDOUT_FILENO, O_BINARY);
|
||||||
name = "<stdin>";
|
name = "<stdin>";
|
||||||
processFile(STDIN_FILENO, STDOUT_FILENO, name, 0);
|
processFile(STDIN_FILENO, STDOUT_FILENO, name, 0);
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#include "extern/getopt.h"
|
#include "extern/getopt.h"
|
||||||
|
#include "file.hpp"
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
@@ -253,10 +255,13 @@ static void registerInput(char const *arg) {
|
|||||||
* @param argPool Argument characters will be appended to this vector, for storage purposes.
|
* @param argPool Argument characters will be appended to this vector, for storage purposes.
|
||||||
*/
|
*/
|
||||||
static std::vector<size_t> readAtFile(std::string const &path, std::vector<char> &argPool) {
|
static std::vector<size_t> readAtFile(std::string const &path, std::vector<char> &argPool) {
|
||||||
std::filebuf file;
|
File file;
|
||||||
file.open(path, std::ios_base::in);
|
if (!file.open(path, std::ios_base::in)) {
|
||||||
|
fatal("Error reading @%s: %s", file.c_str(path), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
static_assert(decltype(file)::traits_type::eof() == EOF,
|
// We only filter out `EOF`, but calling `isblank()` on anything else is UB!
|
||||||
|
static_assert(std::remove_reference_t<decltype(*file)>::traits_type::eof() == EOF,
|
||||||
"isblank(char_traits<...>::eof()) is UB!");
|
"isblank(char_traits<...>::eof()) is UB!");
|
||||||
std::vector<size_t> argvOfs;
|
std::vector<size_t> argvOfs;
|
||||||
|
|
||||||
@@ -265,7 +270,7 @@ static std::vector<size_t> readAtFile(std::string const &path, std::vector<char>
|
|||||||
|
|
||||||
// First, discard any leading whitespace
|
// First, discard any leading whitespace
|
||||||
do {
|
do {
|
||||||
c = file.sbumpc();
|
c = file->sbumpc();
|
||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
return argvOfs;
|
return argvOfs;
|
||||||
}
|
}
|
||||||
@@ -273,7 +278,7 @@ static std::vector<size_t> readAtFile(std::string const &path, std::vector<char>
|
|||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '#': // If it's a comment, discard everything until EOL
|
case '#': // If it's a comment, discard everything until EOL
|
||||||
while ((c = file.sbumpc()) != '\n') {
|
while ((c = file->sbumpc()) != '\n') {
|
||||||
if (c == EOF) {
|
if (c == EOF) {
|
||||||
return argvOfs;
|
return argvOfs;
|
||||||
}
|
}
|
||||||
@@ -281,7 +286,7 @@ static std::vector<size_t> readAtFile(std::string const &path, std::vector<char>
|
|||||||
continue; // Start processing the next line
|
continue; // Start processing the next line
|
||||||
// If it's an empty line, ignore it
|
// If it's an empty line, ignore it
|
||||||
case '\r': // Assuming CRLF here
|
case '\r': // Assuming CRLF here
|
||||||
file.sbumpc(); // Discard the upcoming '\n'
|
file->sbumpc(); // Discard the upcoming '\n'
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case '\n':
|
case '\n':
|
||||||
continue; // Start processing the next line
|
continue; // Start processing the next line
|
||||||
@@ -296,11 +301,11 @@ static std::vector<size_t> readAtFile(std::string const &path, std::vector<char>
|
|||||||
// on `vector` and `sbumpc` to do the right thing here.
|
// on `vector` and `sbumpc` to do the right thing here.
|
||||||
argPool.push_back(c); // Push the character we've already read
|
argPool.push_back(c); // Push the character we've already read
|
||||||
for (;;) {
|
for (;;) {
|
||||||
c = file.sbumpc();
|
c = file->sbumpc();
|
||||||
if (isblank(c) || c == '\n' || c == EOF) {
|
if (c == EOF || c == '\n' || isblank(c)) {
|
||||||
break;
|
break;
|
||||||
} else if (c == '\r') {
|
} else if (c == '\r') {
|
||||||
file.sbumpc(); // Discard the '\n'
|
file->sbumpc(); // Discard the '\n'
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
argPool.push_back(c);
|
argPool.push_back(c);
|
||||||
@@ -309,10 +314,10 @@ static std::vector<size_t> readAtFile(std::string const &path, std::vector<char>
|
|||||||
|
|
||||||
// Discard whitespace until the next argument (candidate)
|
// Discard whitespace until the next argument (candidate)
|
||||||
while (isblank(c)) {
|
while (isblank(c)) {
|
||||||
c = file.sbumpc();
|
c = file->sbumpc();
|
||||||
}
|
}
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
c = file.sbumpc(); // Skip the '\n'
|
c = file->sbumpc(); // Skip the '\n'
|
||||||
}
|
}
|
||||||
} while (c != '\n' && c != EOF); // End if we reached EOL
|
} while (c != '\n' && c != EOF); // End if we reached EOL
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "defaultinitalloc.hpp"
|
#include "defaultinitalloc.hpp"
|
||||||
|
#include "file.hpp"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "itertools.hpp"
|
#include "itertools.hpp"
|
||||||
|
|
||||||
@@ -77,7 +78,7 @@ public:
|
|||||||
|
|
||||||
class Png {
|
class Png {
|
||||||
std::string const &path;
|
std::string const &path;
|
||||||
std::filebuf file{};
|
File file{};
|
||||||
png_structp png = nullptr;
|
png_structp png = nullptr;
|
||||||
png_infop info = nullptr;
|
png_infop info = nullptr;
|
||||||
|
|
||||||
@@ -93,25 +94,26 @@ class Png {
|
|||||||
[[noreturn]] static void handleError(png_structp png, char const *msg) {
|
[[noreturn]] static void handleError(png_structp png, char const *msg) {
|
||||||
Png *self = reinterpret_cast<Png *>(png_get_error_ptr(png));
|
Png *self = reinterpret_cast<Png *>(png_get_error_ptr(png));
|
||||||
|
|
||||||
fatal("Error reading input image (\"%s\"): %s", self->path.c_str(), msg);
|
fatal("Error reading input image (\"%s\"): %s", self->file.c_str(self->path), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleWarning(png_structp png, char const *msg) {
|
static void handleWarning(png_structp png, char const *msg) {
|
||||||
Png *self = reinterpret_cast<Png *>(png_get_error_ptr(png));
|
Png *self = reinterpret_cast<Png *>(png_get_error_ptr(png));
|
||||||
|
|
||||||
warning("In input image (\"%s\"): %s", self->path.c_str(), msg);
|
warning("In input image (\"%s\"): %s", self->file.c_str(self->path), msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void readData(png_structp png, png_bytep data, size_t length) {
|
static void readData(png_structp png, png_bytep data, size_t length) {
|
||||||
Png *self = reinterpret_cast<Png *>(png_get_io_ptr(png));
|
Png *self = reinterpret_cast<Png *>(png_get_io_ptr(png));
|
||||||
std::streamsize expectedLen = length;
|
std::streamsize expectedLen = length;
|
||||||
std::streamsize nbBytesRead = self->file.sgetn(reinterpret_cast<char *>(data), expectedLen);
|
std::streamsize nbBytesRead =
|
||||||
|
self->file->sgetn(reinterpret_cast<char *>(data), expectedLen);
|
||||||
|
|
||||||
if (nbBytesRead != expectedLen) {
|
if (nbBytesRead != expectedLen) {
|
||||||
fatal("Error reading input image (\"%s\"): file too short (expected at least %zd more "
|
fatal("Error reading input image (\"%s\"): file too short (expected at least %zd more "
|
||||||
"bytes after reading %lld)",
|
"bytes after reading %lld)",
|
||||||
self->path.c_str(), length - nbBytesRead,
|
self->file.c_str(self->path), length - nbBytesRead,
|
||||||
self->file.pubseekoff(0, std::ios_base::cur));
|
self->file->pubseekoff(0, std::ios_base::cur));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +144,7 @@ public:
|
|||||||
}
|
}
|
||||||
uint8_t bins = 0;
|
uint8_t bins = 0;
|
||||||
for (auto const &color : colors) {
|
for (auto const &color : colors) {
|
||||||
if (color->isTransparent()) {
|
if (!color.has_value() || color->isTransparent()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!color->isGray()) {
|
if (!color->isGray()) {
|
||||||
@@ -175,17 +177,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
explicit Png(std::string const &filePath) : path(filePath), colors() {
|
explicit Png(std::string const &filePath) : path(filePath), colors() {
|
||||||
if (file.open(path, std::ios_base::in | std::ios_base::binary) == nullptr) {
|
if (file.open(path, std::ios_base::in | std::ios_base::binary) == nullptr) {
|
||||||
fatal("Failed to open input image (\"%s\"): %s", path.c_str(), strerror(errno));
|
fatal("Failed to open input image (\"%s\"): %s", file.c_str(path), strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
options.verbosePrint(Options::VERB_LOG_ACT, "Opened input file\n");
|
options.verbosePrint(Options::VERB_LOG_ACT, "Opened input file\n");
|
||||||
|
|
||||||
std::array<unsigned char, 8> pngHeader;
|
std::array<unsigned char, 8> pngHeader;
|
||||||
|
|
||||||
if (file.sgetn(reinterpret_cast<char *>(pngHeader.data()), pngHeader.size())
|
if (file->sgetn(reinterpret_cast<char *>(pngHeader.data()), pngHeader.size())
|
||||||
!= static_cast<std::streamsize>(pngHeader.size()) // Not enough bytes?
|
!= static_cast<std::streamsize>(pngHeader.size()) // Not enough bytes?
|
||||||
|| png_sig_cmp(pngHeader.data(), 0, pngHeader.size()) != 0) {
|
|| png_sig_cmp(pngHeader.data(), 0, pngHeader.size()) != 0) {
|
||||||
fatal("Input file (\"%s\") is not a PNG image!", path.c_str());
|
fatal("Input file (\"%s\") is not a PNG image!", file.c_str(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
options.verbosePrint(Options::VERB_INTERM, "PNG header signature is OK\n");
|
options.verbosePrint(Options::VERB_INTERM, "PNG header signature is OK\n");
|
||||||
@@ -624,14 +626,16 @@ static std::tuple<DefaultInitVec<size_t>, std::vector<Palette>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void outputPalettes(std::vector<Palette> const &palettes) {
|
static void outputPalettes(std::vector<Palette> const &palettes) {
|
||||||
std::filebuf output;
|
File output;
|
||||||
output.open(options.palettes, std::ios_base::out | std::ios_base::binary);
|
if (!output.open(options.palettes, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to open \"%s\": %s", output.c_str(options.palettes), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
for (Palette const &palette : palettes) {
|
for (Palette const &palette : palettes) {
|
||||||
for (uint8_t i = 0; i < options.nbColorsPerPal; ++i) {
|
for (uint8_t i = 0; i < options.nbColorsPerPal; ++i) {
|
||||||
uint16_t color = palette.colors[i]; // Will return `UINT16_MAX` for unused slots
|
uint16_t color = palette.colors[i]; // Will return `UINT16_MAX` for unused slots
|
||||||
output.sputc(color & 0xFF);
|
output->sputc(color & 0xFF);
|
||||||
output.sputc(color >> 8);
|
output->sputc(color >> 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -750,8 +754,10 @@ namespace unoptimized {
|
|||||||
static void outputTileData(Png const &png, DefaultInitVec<AttrmapEntry> const &attrmap,
|
static void outputTileData(Png const &png, DefaultInitVec<AttrmapEntry> const &attrmap,
|
||||||
std::vector<Palette> const &palettes,
|
std::vector<Palette> const &palettes,
|
||||||
DefaultInitVec<size_t> const &mappings) {
|
DefaultInitVec<size_t> const &mappings) {
|
||||||
std::filebuf output;
|
File output;
|
||||||
output.open(options.output, std::ios_base::out | std::ios_base::binary);
|
if (!output.open(options.output, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to open \"%s\": %s", output.c_str(options.output), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t remainingTiles = (png.getWidth() / 8) * (png.getHeight() / 8);
|
uint64_t remainingTiles = (png.getWidth() / 8) * (png.getHeight() / 8);
|
||||||
if (remainingTiles <= options.trim) {
|
if (remainingTiles <= options.trim) {
|
||||||
@@ -764,9 +770,9 @@ static void outputTileData(Png const &png, DefaultInitVec<AttrmapEntry> const &a
|
|||||||
Palette const &palette = palettes[attr.getPalID(mappings)];
|
Palette const &palette = palettes[attr.getPalID(mappings)];
|
||||||
for (uint32_t y = 0; y < 8; ++y) {
|
for (uint32_t y = 0; y < 8; ++y) {
|
||||||
uint16_t bitplanes = TileData::rowBitplanes(tile, palette, y);
|
uint16_t bitplanes = TileData::rowBitplanes(tile, palette, y);
|
||||||
output.sputc(bitplanes & 0xFF);
|
output->sputc(bitplanes & 0xFF);
|
||||||
if (options.bitDepth == 2) {
|
if (options.bitDepth == 2) {
|
||||||
output.sputc(bitplanes >> 8);
|
output->sputc(bitplanes >> 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,18 +786,27 @@ static void outputTileData(Png const &png, DefaultInitVec<AttrmapEntry> const &a
|
|||||||
|
|
||||||
static void outputMaps(DefaultInitVec<AttrmapEntry> const &attrmap,
|
static void outputMaps(DefaultInitVec<AttrmapEntry> const &attrmap,
|
||||||
DefaultInitVec<size_t> const &mappings) {
|
DefaultInitVec<size_t> const &mappings) {
|
||||||
std::optional<std::filebuf> tilemapOutput, attrmapOutput, palmapOutput;
|
std::optional<File> tilemapOutput, attrmapOutput, palmapOutput;
|
||||||
if (!options.tilemap.empty()) {
|
if (!options.tilemap.empty()) {
|
||||||
tilemapOutput.emplace();
|
tilemapOutput.emplace();
|
||||||
tilemapOutput->open(options.tilemap, std::ios_base::out | std::ios_base::binary);
|
if (!tilemapOutput->open(options.tilemap, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to open \"%s\": %s", tilemapOutput->c_str(options.tilemap),
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!options.attrmap.empty()) {
|
if (!options.attrmap.empty()) {
|
||||||
attrmapOutput.emplace();
|
attrmapOutput.emplace();
|
||||||
attrmapOutput->open(options.attrmap, std::ios_base::out | std::ios_base::binary);
|
if (!attrmapOutput->open(options.attrmap, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to open \"%s\": %s", attrmapOutput->c_str(options.attrmap),
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!options.palmap.empty()) {
|
if (!options.palmap.empty()) {
|
||||||
palmapOutput.emplace();
|
palmapOutput.emplace();
|
||||||
palmapOutput->open(options.palmap, std::ios_base::out | std::ios_base::binary);
|
if (!palmapOutput->open(options.palmap, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to open \"%s\": %s", palmapOutput->c_str(options.palmap),
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t tileID = 0;
|
uint8_t tileID = 0;
|
||||||
@@ -804,14 +819,14 @@ static void outputMaps(DefaultInitVec<AttrmapEntry> const &attrmap,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tilemapOutput.has_value()) {
|
if (tilemapOutput.has_value()) {
|
||||||
tilemapOutput->sputc(tileID + options.baseTileIDs[bank]);
|
(*tilemapOutput)->sputc(tileID + options.baseTileIDs[bank]);
|
||||||
}
|
}
|
||||||
if (attrmapOutput.has_value()) {
|
if (attrmapOutput.has_value()) {
|
||||||
uint8_t palID = attr.getPalID(mappings) & 7;
|
uint8_t palID = attr.getPalID(mappings) & 7;
|
||||||
attrmapOutput->sputc(palID | bank << 3); // The other flags are all 0
|
(*attrmapOutput)->sputc(palID | bank << 3); // The other flags are all 0
|
||||||
}
|
}
|
||||||
if (palmapOutput.has_value()) {
|
if (palmapOutput.has_value()) {
|
||||||
palmapOutput->sputc(attr.getPalID(mappings));
|
(*palmapOutput)->sputc(attr.getPalID(mappings));
|
||||||
}
|
}
|
||||||
++tileID;
|
++tileID;
|
||||||
}
|
}
|
||||||
@@ -886,47 +901,55 @@ static UniqueTiles dedupTiles(Png const &png, DefaultInitVec<AttrmapEntry> &attr
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void outputTileData(UniqueTiles const &tiles) {
|
static void outputTileData(UniqueTiles const &tiles) {
|
||||||
std::filebuf output;
|
File output;
|
||||||
output.open(options.output, std::ios_base::out | std::ios_base::binary);
|
if (!output.open(options.output, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to create \"%s\": %s", output.c_str(options.output), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t tileID = 0;
|
uint16_t tileID = 0;
|
||||||
for (auto iter = tiles.begin(), end = tiles.end() - options.trim; iter != end; ++iter) {
|
for (auto iter = tiles.begin(), end = tiles.end() - options.trim; iter != end; ++iter) {
|
||||||
TileData const *tile = *iter;
|
TileData const *tile = *iter;
|
||||||
assert(tile->tileID == tileID);
|
assert(tile->tileID == tileID);
|
||||||
++tileID;
|
++tileID;
|
||||||
output.sputn(reinterpret_cast<char const *>(tile->data().data()), options.bitDepth * 8);
|
output->sputn(reinterpret_cast<char const *>(tile->data().data()), options.bitDepth * 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outputTilemap(DefaultInitVec<AttrmapEntry> const &attrmap) {
|
static void outputTilemap(DefaultInitVec<AttrmapEntry> const &attrmap) {
|
||||||
std::filebuf output;
|
File output;
|
||||||
output.open(options.tilemap, std::ios_base::out | std::ios_base::binary);
|
if (!output.open(options.tilemap, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to create \"%s\": %s", output.c_str(options.tilemap), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
for (AttrmapEntry const &entry : attrmap) {
|
for (AttrmapEntry const &entry : attrmap) {
|
||||||
output.sputc(entry.tileID); // The tile ID has already been converted
|
output->sputc(entry.tileID); // The tile ID has already been converted
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outputAttrmap(DefaultInitVec<AttrmapEntry> const &attrmap,
|
static void outputAttrmap(DefaultInitVec<AttrmapEntry> const &attrmap,
|
||||||
DefaultInitVec<size_t> const &mappings) {
|
DefaultInitVec<size_t> const &mappings) {
|
||||||
std::filebuf output;
|
File output;
|
||||||
output.open(options.attrmap, std::ios_base::out | std::ios_base::binary);
|
if (!output.open(options.attrmap, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to create \"%s\": %s", output.c_str(options.attrmap), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
for (AttrmapEntry const &entry : attrmap) {
|
for (AttrmapEntry const &entry : attrmap) {
|
||||||
uint8_t attr = entry.xFlip << 5 | entry.yFlip << 6;
|
uint8_t attr = entry.xFlip << 5 | entry.yFlip << 6;
|
||||||
attr |= entry.bank << 3;
|
attr |= entry.bank << 3;
|
||||||
attr |= entry.getPalID(mappings) & 7;
|
attr |= entry.getPalID(mappings) & 7;
|
||||||
output.sputc(attr);
|
output->sputc(attr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void outputPalmap(DefaultInitVec<AttrmapEntry> const &attrmap,
|
static void outputPalmap(DefaultInitVec<AttrmapEntry> const &attrmap,
|
||||||
DefaultInitVec<size_t> const &mappings) {
|
DefaultInitVec<size_t> const &mappings) {
|
||||||
std::filebuf output;
|
File output;
|
||||||
output.open(options.attrmap, std::ios_base::out | std::ios_base::binary);
|
if (!output.open(options.attrmap, std::ios_base::out | std::ios_base::binary)) {
|
||||||
|
fatal("Failed to create \"%s\": %s", output.c_str(options.attrmap), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
for (AttrmapEntry const &entry : attrmap) {
|
for (AttrmapEntry const &entry : attrmap) {
|
||||||
output.sputc(entry.getPalID(mappings));
|
output->sputc(entry.getPalID(mappings));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,15 +21,16 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "defaultinitalloc.hpp"
|
#include "defaultinitalloc.hpp"
|
||||||
|
#include "file.hpp"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "itertools.hpp"
|
#include "itertools.hpp"
|
||||||
|
|
||||||
#include "gfx/main.hpp"
|
#include "gfx/main.hpp"
|
||||||
|
|
||||||
static DefaultInitVec<uint8_t> readInto(std::string path) {
|
static DefaultInitVec<uint8_t> readInto(std::string path) {
|
||||||
std::filebuf file;
|
File file;
|
||||||
if (!file.open(path, std::ios::in | std::ios::binary)) {
|
if (!file.open(path, std::ios::in | std::ios::binary)) {
|
||||||
fatal("Failed to open \"%s\": %s", path.c_str(), strerror(errno));
|
fatal("Failed to open \"%s\": %s", file.c_str(path), strerror(errno));
|
||||||
}
|
}
|
||||||
DefaultInitVec<uint8_t> data(128 * 16); // Begin with some room pre-allocated
|
DefaultInitVec<uint8_t> data(128 * 16); // Begin with some room pre-allocated
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ static DefaultInitVec<uint8_t> readInto(std::string path) {
|
|||||||
|
|
||||||
// Fill the new area ([oldSize; curSize[) with bytes
|
// Fill the new area ([oldSize; curSize[) with bytes
|
||||||
size_t nbRead =
|
size_t nbRead =
|
||||||
file.sgetn(reinterpret_cast<char *>(&data.data()[oldSize]), curSize - oldSize);
|
file->sgetn(reinterpret_cast<char *>(&data.data()[oldSize]), curSize - oldSize);
|
||||||
if (nbRead != curSize - oldSize) {
|
if (nbRead != curSize - oldSize) {
|
||||||
// Shrink the vector to discard bytes that weren't read
|
// Shrink the vector to discard bytes that weren't read
|
||||||
data.resize(oldSize + nbRead);
|
data.resize(oldSize + nbRead);
|
||||||
@@ -68,13 +69,13 @@ static void pngWarning(png_structp png, char const *msg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writePng(png_structp png, png_bytep data, size_t length) {
|
void writePng(png_structp png, png_bytep data, size_t length) {
|
||||||
auto &pngFile = *static_cast<std::filebuf *>(png_get_io_ptr(png));
|
auto &pngFile = *static_cast<File *>(png_get_io_ptr(png));
|
||||||
pngFile.sputn(reinterpret_cast<char *>(data), length);
|
pngFile->sputn(reinterpret_cast<char *>(data), length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void flushPng(png_structp png) {
|
void flushPng(png_structp png) {
|
||||||
auto &pngFile = *static_cast<std::filebuf *>(png_get_io_ptr(png));
|
auto &pngFile = *static_cast<File *>(png_get_io_ptr(png));
|
||||||
pngFile.pubsync();
|
pngFile->pubsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reverse() {
|
void reverse() {
|
||||||
@@ -146,14 +147,16 @@ void reverse() {
|
|||||||
{Rgba(0xffffffff), Rgba(0xaaaaaaff), Rgba(0x555555ff), Rgba(0x000000ff)}
|
{Rgba(0xffffffff), Rgba(0xaaaaaaff), Rgba(0x555555ff), Rgba(0x000000ff)}
|
||||||
};
|
};
|
||||||
if (!options.palettes.empty()) {
|
if (!options.palettes.empty()) {
|
||||||
std::filebuf file;
|
File file;
|
||||||
file.open(options.palettes, std::ios::in | std::ios::binary);
|
if (!file.open(options.palettes, std::ios::in | std::ios::binary)) {
|
||||||
|
fatal("Failed to open \"%s\": %s", file.c_str(options.palettes), strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
palettes.clear();
|
palettes.clear();
|
||||||
std::array<uint8_t, sizeof(uint16_t) * 4> buf; // 4 colors
|
std::array<uint8_t, sizeof(uint16_t) * 4> buf; // 4 colors
|
||||||
size_t nbRead;
|
size_t nbRead;
|
||||||
do {
|
do {
|
||||||
nbRead = file.sgetn(reinterpret_cast<char *>(buf.data()), buf.size());
|
nbRead = file->sgetn(reinterpret_cast<char *>(buf.data()), buf.size());
|
||||||
if (nbRead == buf.size()) {
|
if (nbRead == buf.size()) {
|
||||||
// Expand the colors
|
// Expand the colors
|
||||||
auto &palette = palettes.emplace_back();
|
auto &palette = palettes.emplace_back();
|
||||||
@@ -231,11 +234,13 @@ void reverse() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
options.verbosePrint(Options::VERB_LOG_ACT, "Writing image...\n");
|
options.verbosePrint(Options::VERB_LOG_ACT, "Writing image...\n");
|
||||||
std::filebuf pngFile;
|
File pngFile;
|
||||||
pngFile.open(options.input, std::ios::out | std::ios::binary);
|
if (!pngFile.open(options.input, std::ios::out | std::ios::binary)) {
|
||||||
|
fatal("Failed to create \"%s\": %s", pngFile.c_str(options.input), strerror(errno));
|
||||||
|
}
|
||||||
png_structp png = png_create_write_struct(
|
png_structp png = png_create_write_struct(
|
||||||
PNG_LIBPNG_VER_STRING,
|
PNG_LIBPNG_VER_STRING,
|
||||||
const_cast<png_voidp>(static_cast<void const *>(options.input.c_str())), pngError,
|
const_cast<png_voidp>(static_cast<void const *>(pngFile.c_str(options.input))), pngError,
|
||||||
pngWarning);
|
pngWarning);
|
||||||
if (!png) {
|
if (!png) {
|
||||||
fatal("Couldn't create PNG write struct: %s", strerror(errno));
|
fatal("Couldn't create PNG write struct: %s", strerror(errno));
|
||||||
|
|||||||
@@ -398,6 +398,8 @@ static void readSection(FILE *file, struct Section *section, char const *fileNam
|
|||||||
for (uint32_t i = 0; i < section->nbPatches; i++)
|
for (uint32_t i = 0; i < section->nbPatches; i++)
|
||||||
readPatch(file, &patches[i], fileName, section->name, i, fileNodes);
|
readPatch(file, &patches[i], fileName, section->name, i, fileNodes);
|
||||||
section->patches = patches;
|
section->patches = patches;
|
||||||
|
} else {
|
||||||
|
section->data = NULL; // `mergeSections()` expects to be able to always read the ptr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -404,6 +404,16 @@ static void writeSymBank(struct SortedSections const *bankSections,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void writeEmptySpace(uint16_t begin, uint16_t end)
|
||||||
|
{
|
||||||
|
if (begin < end) {
|
||||||
|
uint16_t len = end - begin;
|
||||||
|
|
||||||
|
fprintf(mapFile, "\tEMPTY: $%04x-$%04x ($%04" PRIx16 " byte%s)\n",
|
||||||
|
begin, end - 1, len, len == 1 ? "" : "s");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Write a bank's contents to the map file
|
* Write a bank's contents to the map file
|
||||||
* @param bankSections The bank's sections
|
* @param bankSections The bank's sections
|
||||||
@@ -432,12 +442,7 @@ static uint16_t writeMapBank(struct SortedSections const *sectList,
|
|||||||
used += sect->size;
|
used += sect->size;
|
||||||
assert(sect->offset == 0);
|
assert(sect->offset == 0);
|
||||||
|
|
||||||
if (prevEndAddr < sect->org) {
|
writeEmptySpace(prevEndAddr, sect->org);
|
||||||
uint16_t empty = sect->org - prevEndAddr;
|
|
||||||
|
|
||||||
fprintf(mapFile, "\tEMPTY: $%04" PRIx16 " byte%s\n", empty,
|
|
||||||
empty == 1 ? "" : "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
prevEndAddr = sect->org + sect->size;
|
prevEndAddr = sect->org + sect->size;
|
||||||
|
|
||||||
@@ -455,16 +460,22 @@ static uint16_t writeMapBank(struct SortedSections const *sectList,
|
|||||||
uint16_t org = sect->org;
|
uint16_t org = sect->org;
|
||||||
|
|
||||||
while (sect) {
|
while (sect) {
|
||||||
if (sect->modifier == SECTION_UNION)
|
|
||||||
fprintf(mapFile, "\t\t; New union\n");
|
|
||||||
else if (sect->modifier == SECTION_FRAGMENT)
|
|
||||||
fprintf(mapFile, "\t\t; New fragment\n");
|
|
||||||
for (size_t i = 0; i < sect->nbSymbols; i++)
|
for (size_t i = 0; i < sect->nbSymbols; i++)
|
||||||
// "\tSECTION: $xxxx ..."
|
// Space matches "\tSECTION: $xxxx ..."
|
||||||
fprintf(mapFile, "\t $%04" PRIx32 " = %s\n",
|
fprintf(mapFile, "\t $%04" PRIx32 " = %s\n",
|
||||||
sect->symbols[i]->offset + org,
|
sect->symbols[i]->offset + org,
|
||||||
sect->symbols[i]->name);
|
sect->symbols[i]->name);
|
||||||
|
|
||||||
|
if (sect->nextu) {
|
||||||
|
// Announce the following "piece"
|
||||||
|
if (sect->nextu->modifier == SECTION_UNION)
|
||||||
|
fprintf(mapFile,
|
||||||
|
"\t ; Next union\n");
|
||||||
|
else if (sect->nextu->modifier == SECTION_FRAGMENT)
|
||||||
|
fprintf(mapFile,
|
||||||
|
"\t ; Next fragment\n");
|
||||||
|
}
|
||||||
|
|
||||||
sect = sect->nextu; // Also print symbols in the following "pieces"
|
sect = sect->nextu; // Also print symbols in the following "pieces"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,19 +485,14 @@ static uint16_t writeMapBank(struct SortedSections const *sectList,
|
|||||||
|
|
||||||
uint16_t bankEndAddr = sectionTypeInfo[type].startAddr + sectionTypeInfo[type].size;
|
uint16_t bankEndAddr = sectionTypeInfo[type].startAddr + sectionTypeInfo[type].size;
|
||||||
|
|
||||||
if (prevEndAddr < bankEndAddr) {
|
|
||||||
uint16_t empty = bankEndAddr - prevEndAddr;
|
|
||||||
|
|
||||||
fprintf(mapFile, "\tEMPTY: $%04" PRIx16 " byte%s\n", empty,
|
|
||||||
empty == 1 ? "" : "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (used == 0) {
|
if (used == 0) {
|
||||||
fputs(" EMPTY\n\n", mapFile);
|
fputs("\tEMPTY\n\n", mapFile);
|
||||||
} else {
|
} else {
|
||||||
|
writeEmptySpace(prevEndAddr, bankEndAddr);
|
||||||
|
|
||||||
uint16_t slack = sectionTypeInfo[type].size - used;
|
uint16_t slack = sectionTypeInfo[type].size - used;
|
||||||
|
|
||||||
fprintf(mapFile, "\tSLACK: $%04" PRIx16 " byte%s\n\n", slack,
|
fprintf(mapFile, "\tTOTAL EMPTY: $%04" PRIx16 " byte%s\n\n", slack,
|
||||||
slack == 1 ? "" : "s");
|
slack == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -272,14 +272,12 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
|
|||||||
|
|
||||||
getToken(line, "'A' line is too short");
|
getToken(line, "'A' line is too short");
|
||||||
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
|
assert(strlen(token) != 0); // This should be impossible, tokens are non-empty
|
||||||
curSection->name = strdup(token); // We need a pointer that will live longer
|
|
||||||
if (!curSection->name)
|
|
||||||
fatal(where, lineNo, "Failed to alloc new area's name: %s", strerror(errno));
|
|
||||||
// The following is required for fragment offsets to be reliably predicted
|
// The following is required for fragment offsets to be reliably predicted
|
||||||
for (size_t i = 0; i < nbSections; ++i) {
|
for (size_t i = 0; i < nbSections; ++i) {
|
||||||
if (!strcmp(token, fileSections[i].section->name))
|
if (!strcmp(token, fileSections[i].section->name))
|
||||||
fatal(where, lineNo, "Area \"%s\" already defined earlier", token);
|
fatal(where, lineNo, "Area \"%s\" already defined earlier", token);
|
||||||
}
|
}
|
||||||
|
char const *sectionName = token; // We'll deal with the section's name depending on type
|
||||||
|
|
||||||
expectToken("size", 'A');
|
expectToken("size", 'A');
|
||||||
|
|
||||||
@@ -299,6 +297,19 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
|
|||||||
curSection->isBankFixed = curSection->isAddressFixed;
|
curSection->isBankFixed = curSection->isAddressFixed;
|
||||||
curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE))
|
curSection->modifier = curSection->isAddressFixed || (tmp & (1 << AREA_TYPE))
|
||||||
? SECTION_NORMAL : SECTION_FRAGMENT;
|
? SECTION_NORMAL : SECTION_FRAGMENT;
|
||||||
|
// If the section is absolute, its name might not be unique; thus, mangle the name
|
||||||
|
if (curSection->modifier == SECTION_NORMAL) {
|
||||||
|
size_t len = strlen(where->name) + 1 + strlen(token);
|
||||||
|
|
||||||
|
curSection->name = malloc(len + 1);
|
||||||
|
if (!curSection->name)
|
||||||
|
fatal(where, lineNo, "Failed to alloc new area's name: %s", strerror(errno));
|
||||||
|
sprintf(curSection->name, "%s %s", where->name, sectionName);
|
||||||
|
} else {
|
||||||
|
curSection->name = strdup(sectionName); // We need a pointer that will live longer
|
||||||
|
if (!curSection->name)
|
||||||
|
fatal(where, lineNo, "Failed to alloc new area's name: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
expectToken("addr", 'A');
|
expectToken("addr", 'A');
|
||||||
|
|
||||||
|
|||||||
38
test/fetch-test-deps.sh
Executable file
38
test/fetch-test-deps.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
--get-hash)
|
||||||
|
action() { # owner/repo shallow-since commit
|
||||||
|
printf "%s@%s-" "${1##*/}" "$3"
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
|
||||||
|
--get-paths)
|
||||||
|
action() { # owner/repo shallow-since commit
|
||||||
|
printf "test/%s," "${1##*/}"
|
||||||
|
}
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Fetching test dependency repositories"
|
||||||
|
|
||||||
|
action() { # owner/repo shallow-since commit
|
||||||
|
if [ ! -d ${1##*/} ]; then
|
||||||
|
git clone https://github.com/$1.git --shallow-since=$2 --single-branch
|
||||||
|
fi
|
||||||
|
pushd ${1##*/}
|
||||||
|
git checkout -f $3
|
||||||
|
if [ -f ../patches/${1##*/}.patch ]; then
|
||||||
|
git apply --ignore-whitespace ../patches/${1##*/}.patch
|
||||||
|
fi
|
||||||
|
popd
|
||||||
|
}
|
||||||
|
esac
|
||||||
|
|
||||||
|
action pret/pokecrystal 2022-09-29 70a3ec1accb6de1c1c273470af0ddfa2edc1b0a9
|
||||||
|
action pret/pokered 2022-09-29 2b52ceb718b55dce038db24d177715ae4281d065
|
||||||
|
action AntonioND/ucity 2022-04-20 d8878233da7a6569f09f87b144cb5bf140146a0f
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
[[ -e ./rgbgfx_test ]] || make -C ../.. test/gfx/rgbgfx_test
|
[[ -e ./rgbgfx_test ]] || make -C ../.. test/gfx/rgbgfx_test || exit
|
||||||
[[ -e ./randtilegen ]] || make -C ../.. test/gfx/randtilegen
|
[[ -e ./randtilegen ]] || make -C ../.. test/gfx/randtilegen || exit
|
||||||
|
|
||||||
trap 'rm -f "$errtmp"' EXIT
|
trap 'rm -f "$errtmp"' EXIT
|
||||||
errtmp="$(mktemp)"
|
errtmp="$(mktemp)"
|
||||||
@@ -12,9 +12,11 @@ red="$(tput setaf 1)"
|
|||||||
green="$(tput setaf 2)"
|
green="$(tput setaf 2)"
|
||||||
rescolors="$(tput op)"
|
rescolors="$(tput op)"
|
||||||
|
|
||||||
|
RGBGFX=../../rgbgfx
|
||||||
|
|
||||||
rc=0
|
rc=0
|
||||||
new_test() {
|
new_test() {
|
||||||
cmdline="${*@Q}"
|
cmdline="$*"
|
||||||
echo "$bold${green}Testing: $cmdline$rescolors$resbold" >&2
|
echo "$bold${green}Testing: $cmdline$rescolors$resbold" >&2
|
||||||
}
|
}
|
||||||
test() {
|
test() {
|
||||||
@@ -42,14 +44,22 @@ rm -f out*.png result.png
|
|||||||
|
|
||||||
for f in *.png; do
|
for f in *.png; do
|
||||||
flags="$([[ -e "${f%.png}.flags" ]] && echo "@${f%.png}.flags")"
|
flags="$([[ -e "${f%.png}.flags" ]] && echo "@${f%.png}.flags")"
|
||||||
new_test ../../rgbgfx $flags "$f"
|
|
||||||
|
|
||||||
|
new_test "$RGBGFX" $flags "$f"
|
||||||
if [[ -e "${f%.png}.err" ]]; then
|
if [[ -e "${f%.png}.err" ]]; then
|
||||||
test 2>"$errtmp"
|
test 2>"$errtmp"
|
||||||
diff -u --strip-trailing-cr "${f%.png}.err" "$errtmp" || fail
|
diff -u --strip-trailing-cr "${f%.png}.err" "$errtmp" || fail
|
||||||
else
|
else
|
||||||
test || fail $?
|
test || fail $?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
new_test "$RGBGFX" $flags - "<$f"
|
||||||
|
if [[ -e "${f%.png}.err" ]]; then
|
||||||
|
test 2>"$errtmp"
|
||||||
|
diff -u --strip-trailing-cr <(sed "s/$f/<stdin>/g" "${f%.png}.err") "$errtmp" || fail
|
||||||
|
else
|
||||||
|
test || fail $?
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
exit $rc
|
exit $rc
|
||||||
|
|||||||
@@ -25,20 +25,16 @@ done
|
|||||||
# When updating subprojects, change the commit being checked out, and set the `shallow-since`
|
# When updating subprojects, change the commit being checked out, and set the `shallow-since`
|
||||||
# to the day before, to reduce the amount of refs being transferred and thus speed up CI.
|
# to the day before, to reduce the amount of refs being transferred and thus speed up CI.
|
||||||
|
|
||||||
test_downstream() { # owner/repo shallow-since commit make-target
|
test_downstream() { # owner/repo make-target
|
||||||
if [ ! -d ${1##*/} ]; then
|
if ! pushd ${1##*/}; then
|
||||||
git clone https://github.com/$1.git --shallow-since=$2 --single-branch
|
echo >&2 'Please run `fetch-test-deps.sh` before running the test suite'
|
||||||
fi
|
return 1
|
||||||
pushd ${1##*/}
|
|
||||||
git checkout -f $3
|
|
||||||
if [ -f ../patches/${1##*/}.patch ]; then
|
|
||||||
git apply --ignore-whitespace ../patches/${1##*/}.patch
|
|
||||||
fi
|
fi
|
||||||
make clean
|
make clean
|
||||||
make -j4 $4 RGBDS=../../
|
make -j4 $2 RGBDS=../../
|
||||||
popd
|
popd
|
||||||
}
|
}
|
||||||
|
|
||||||
test_downstream pret/pokecrystal 2022-09-29 70a3ec1accb6de1c1c273470af0ddfa2edc1b0a9 compare
|
test_downstream pret/pokecrystal compare
|
||||||
test_downstream pret/pokered 2022-09-29 2b52ceb718b55dce038db24d177715ae4281d065 compare
|
test_downstream pret/pokered compare
|
||||||
test_downstream AntonioND/ucity 2022-04-20 d8878233da7a6569f09f87b144cb5bf140146a0f ''
|
test_downstream AntonioND/ucity ''
|
||||||
|
|||||||
Reference in New Issue
Block a user