mirror of
https://github.com/gbdev/rgbds.git
synced 2026-10-06 04:05:38 +00:00
Merge branch 'master' into features-1.1.0
This commit is contained in:
commit
ad4e399018
26 files changed
+241
-203
No files matched your search
+3
-3
@@ -1048,17 +1048,17 @@ include:
|
||||
|
||||
incbin:
|
||||
POP_INCBIN string {
|
||||
if (sect_BinaryFile($2, 0)) {
|
||||
if (sect_BinaryFile($2, 0, std::nullopt)) {
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
| POP_INCBIN string COMMA uconst {
|
||||
if (sect_BinaryFile($2, $4)) {
|
||||
if (sect_BinaryFile($2, $4, std::nullopt)) {
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
| POP_INCBIN string COMMA uconst COMMA uconst {
|
||||
if (sect_BinaryFileSlice($2, $4, $6)) {
|
||||
if (sect_BinaryFile($2, $4, $6)) {
|
||||
YYACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
+34
-80
@@ -998,10 +998,13 @@ void sect_PCRelByte(Expression const &expr, uint32_t pcShift) {
|
||||
}
|
||||
}
|
||||
|
||||
bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
|
||||
bool sect_BinaryFile(std::string const &name, uint32_t startPos, std::optional<uint32_t> length) {
|
||||
if (!requireCodeSection()) {
|
||||
return false;
|
||||
}
|
||||
if (length.has_value() && *length == 0) { // Don't even bother with 0-byte slices
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *file = nullptr;
|
||||
if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath) {
|
||||
@@ -1022,6 +1025,16 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
|
||||
*fileSize
|
||||
);
|
||||
return false;
|
||||
} else if (length.has_value() && *length > *fileSize - startPos) {
|
||||
error(
|
||||
"Specified range in `INCBIN` file \"%s\" is out of bounds (%" PRIu32 " + %" PRIu32
|
||||
" > %" PRIu64 ")",
|
||||
name.c_str(),
|
||||
startPos,
|
||||
*length,
|
||||
*fileSize
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// The file is seekable; skip to the specified start position
|
||||
fseek(file, startPos, SEEK_SET);
|
||||
@@ -1044,8 +1057,26 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
for (int byte; (byte = fgetc(file)) != EOF;) {
|
||||
writeByte(byte);
|
||||
if (length.has_value()) {
|
||||
uint32_t remaining = *length;
|
||||
for (; remaining; --remaining) {
|
||||
if (int byte = fgetc(file); byte == EOF) {
|
||||
break; // LCOV_EXCL_LINE
|
||||
} else {
|
||||
writeByte(byte);
|
||||
}
|
||||
}
|
||||
if (remaining > 0 && !ferror(file)) {
|
||||
error(
|
||||
"Premature end of `INCBIN` file \"%s\" (%" PRId32 " bytes left to read)",
|
||||
name.c_str(),
|
||||
remaining
|
||||
);
|
||||
}
|
||||
} else {
|
||||
for (int byte; (byte = fgetc(file)) != EOF;) {
|
||||
writeByte(byte);
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(file)) {
|
||||
@@ -1056,83 +1087,6 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sect_BinaryFileSlice(std::string const &name, uint32_t startPos, uint32_t length) {
|
||||
if (!requireCodeSection()) {
|
||||
return false;
|
||||
}
|
||||
if (length == 0) { // Don't even bother with 0-byte slices
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *file = nullptr;
|
||||
if (std::optional<std::string> fullPath = fstk_FindFile(name); fullPath) {
|
||||
file = fopen(fullPath->c_str(), "rb");
|
||||
}
|
||||
if (!file) {
|
||||
return fstk_FileError(name, "`INCBIN`");
|
||||
}
|
||||
Defer closeFile{[&] { xfclose(file); }};
|
||||
|
||||
if (std::optional<uint64_t> fileSize = seekSize(file); fileSize.has_value()) {
|
||||
if (startPos > *fileSize) {
|
||||
error(
|
||||
"Specified start position (%" PRIu32 ") is greater than length of \"%s\" (%" PRIu64
|
||||
")",
|
||||
startPos,
|
||||
name.c_str(),
|
||||
*fileSize
|
||||
);
|
||||
return false;
|
||||
} else if (length > *fileSize - startPos) {
|
||||
error(
|
||||
"Specified range in `INCBIN` file \"%s\" is out of bounds (%" PRIu32 " + %" PRIu32
|
||||
" > %" PRIu64 ")",
|
||||
name.c_str(),
|
||||
startPos,
|
||||
length,
|
||||
*fileSize
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// The file is seekable; skip to the specified start position
|
||||
fseek(file, startPos, SEEK_SET);
|
||||
} else {
|
||||
// LCOV_EXCL_START
|
||||
if (errno != ESPIPE) {
|
||||
error(
|
||||
"Error determining size of `INCBIN` file \"%s\": %s", name.c_str(), strerror(errno)
|
||||
);
|
||||
}
|
||||
// The file isn't seekable, so we'll just skip bytes one at a time
|
||||
while (startPos--) {
|
||||
if (fgetc(file) == EOF) {
|
||||
error(
|
||||
"Specified start position is greater than length of file \"%s\"", name.c_str()
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
while (length--) {
|
||||
if (int byte = fgetc(file); byte != EOF) {
|
||||
writeByte(byte);
|
||||
// LCOV_EXCL_START
|
||||
} else if (ferror(file)) {
|
||||
error("Error reading `INCBIN` file \"%s\": %s", name.c_str(), strerror(errno));
|
||||
} else {
|
||||
error(
|
||||
"Premature end of `INCBIN` file \"%s\" (%" PRId32 " bytes left to read)",
|
||||
name.c_str(),
|
||||
length + 1
|
||||
);
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void sect_PushSection() {
|
||||
sectionStack.push_front({
|
||||
.section = currentSection,
|
||||
|
||||
+19
-2
@@ -381,6 +381,24 @@ static void
|
||||
if (options.padValue == UNSPECIFIED) {
|
||||
rom0Len = headerSize;
|
||||
}
|
||||
} else if (output != STDOUT_FILENO) {
|
||||
// Truncate a pre-existing output file before writing to it
|
||||
if (ftruncate(output, 0) != 0) {
|
||||
// LCOV_EXCL_START
|
||||
int errnum = errno;
|
||||
if (errnum == EINVAL) {
|
||||
// We do not support FIFOs or symlinks
|
||||
if (struct stat stat; fstat(output, &stat) == 0 && !S_ISREG(stat.st_mode)) {
|
||||
error(
|
||||
"\"%s\" is not a regular file, and thus cannot be modified in-place", name
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
error("Failed to truncate \"%s\": %s", name, strerror(errnum));
|
||||
return;
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
writeLen = writeBytes(output, rom0, rom0Len);
|
||||
|
||||
@@ -498,8 +516,7 @@ bool fix_ProcessFile(char const *name, char const *outputName) {
|
||||
error("Failed to open \"%s\" for reading+writing: %s", name, strerror(errno));
|
||||
} else {
|
||||
Defer closeInput{[&] { xclose(input); }};
|
||||
struct stat stat;
|
||||
if (fstat(input, &stat) == -1) {
|
||||
if (struct stat stat; fstat(input, &stat) == -1) {
|
||||
error("Failed to stat \"%s\": %s", name, strerror(errno)); // LCOV_EXCL_LINE
|
||||
} else if (!S_ISREG(stat.st_mode)) { // We do not support FIFOs or symlinks
|
||||
// LCOV_EXCL_START
|
||||
|
||||
+1
-10
@@ -5,7 +5,6 @@
|
||||
#include "gfx/main.hpp"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <ios>
|
||||
#include <optional>
|
||||
#include <png.h>
|
||||
#include <stdarg.h>
|
||||
@@ -19,7 +18,6 @@
|
||||
|
||||
#include "cli.hpp"
|
||||
#include "diagnostics.hpp"
|
||||
#include "file.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "style.hpp" // style_Parse
|
||||
#include "usage.hpp"
|
||||
@@ -681,14 +679,7 @@ int main(int argc, char *argv[]) {
|
||||
bool useInputImage = !options.input.empty() && !localOptions.reverse;
|
||||
Png png;
|
||||
if (useInputImage) {
|
||||
if (File image;
|
||||
image.open(options.input, std::ios_base::in | std::ios_base::binary) == nullptr) {
|
||||
fatal(
|
||||
"Failed to open PNG image (\"%s\"): %s", image.c_str(options.input), strerror(errno)
|
||||
);
|
||||
} else {
|
||||
png = Png(image.c_str(options.input), *image);
|
||||
}
|
||||
png = Png(options.input);
|
||||
}
|
||||
|
||||
// Execute deferred pal spec parsing, now that all other params are known.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "diagnostics.hpp"
|
||||
#include "file.hpp"
|
||||
#include "helpers.hpp"
|
||||
#include "verbosity.hpp"
|
||||
|
||||
@@ -61,7 +62,19 @@ static void readData(png_structp png, png_bytep data, size_t length) {
|
||||
}
|
||||
}
|
||||
|
||||
Png::Png(std::string const &path) {
|
||||
if (File image; image.open(path, std::ios_base::in | std::ios_base::binary) == nullptr) {
|
||||
fatal("Failed to open PNG image (\"%s\"): %s", image.display_name(path), strerror(errno));
|
||||
} else {
|
||||
initialize(image.display_name(path), *image);
|
||||
}
|
||||
}
|
||||
|
||||
Png::Png(char const *filename, std::streambuf &file) {
|
||||
initialize(filename, file);
|
||||
}
|
||||
|
||||
void Png::initialize(char const *filename, std::streambuf &file) {
|
||||
Input input(filename, file);
|
||||
|
||||
verbosePrint(VERB_NOTICE, "Reading PNG file \"%s\"\n", input.filename);
|
||||
|
||||
+11
-7
@@ -491,7 +491,11 @@ static void outputPalettes(std::vector<Palette> const &palettes) {
|
||||
File output;
|
||||
if (!output.open(options.palettes, std::ios_base::out | std::ios_base::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", output.c_str(options.palettes), strerror(errno));
|
||||
fatal(
|
||||
"Failed to create \"%s\": %s",
|
||||
output.display_name(options.palettes),
|
||||
strerror(errno)
|
||||
);
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
@@ -646,7 +650,7 @@ static void outputUnoptimizedTileData(
|
||||
File output;
|
||||
if (!output.open(options.output, std::ios_base::out | std::ios_base::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", output.c_str(options.output), strerror(errno));
|
||||
fatal("Failed to create \"%s\": %s", output.display_name(options.output), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
@@ -699,7 +703,7 @@ static void outputUnoptimizedMaps(
|
||||
file.emplace();
|
||||
if (!file->open(path, std::ios_base::out | std::ios_base::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", file->c_str(path), strerror(errno));
|
||||
fatal("Failed to create \"%s\": %s", file->display_name(path), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
}
|
||||
@@ -873,7 +877,7 @@ static void outputTileData(UniqueTiles const &tiles) {
|
||||
File output;
|
||||
if (!output.open(options.output, std::ios_base::out | std::ios_base::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", output.c_str(options.output), strerror(errno));
|
||||
fatal("Failed to create \"%s\": %s", output.display_name(options.output), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
@@ -913,7 +917,7 @@ static void outputTilemap(std::vector<AttrmapEntry> const &attrmap) {
|
||||
File output;
|
||||
if (!output.open(options.tilemap, std::ios_base::out | std::ios_base::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", output.c_str(options.tilemap), strerror(errno));
|
||||
fatal("Failed to create \"%s\": %s", output.display_name(options.tilemap), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
@@ -929,7 +933,7 @@ static void
|
||||
File output;
|
||||
if (!output.open(options.attrmap, std::ios_base::out | std::ios_base::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", output.c_str(options.attrmap), strerror(errno));
|
||||
fatal("Failed to create \"%s\": %s", output.display_name(options.attrmap), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
@@ -950,7 +954,7 @@ static void
|
||||
File output;
|
||||
if (!output.open(options.palmap, std::ios_base::out | std::ios_base::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", output.c_str(options.palmap), strerror(errno));
|
||||
fatal("Failed to create \"%s\": %s", output.display_name(options.palmap), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
|
||||
+16
-20
@@ -31,7 +31,7 @@
|
||||
static std::vector<uint8_t> readInto(std::string const &path) {
|
||||
File file;
|
||||
if (!file.open(path, std::ios::in | std::ios::binary)) {
|
||||
fatal("Failed to open \"%s\": %s", file.c_str(path), strerror(errno));
|
||||
fatal("Failed to open \"%s\": %s", file.display_name(path), strerror(errno));
|
||||
}
|
||||
std::vector<uint8_t> data(128 * 16); // Begin with some room pre-allocated
|
||||
|
||||
@@ -87,7 +87,7 @@ static void flushPng(png_structp png) {
|
||||
}
|
||||
|
||||
static void printColor(std::optional<Rgba> const &color) {
|
||||
if (color) {
|
||||
if (color.has_value()) {
|
||||
fprintf(stderr, "#%08x", color->toCSS());
|
||||
} else {
|
||||
fputs("<none> ", stderr);
|
||||
@@ -207,7 +207,9 @@ void reverse() {
|
||||
if (!options.palettes.empty()) {
|
||||
File file;
|
||||
if (!file.open(options.palettes, std::ios::in | std::ios::binary)) {
|
||||
fatal("Failed to open \"%s\": %s", file.c_str(options.palettes), strerror(errno));
|
||||
fatal(
|
||||
"Failed to open \"%s\": %s", file.display_name(options.palettes), strerror(errno)
|
||||
);
|
||||
}
|
||||
|
||||
palettes.clear();
|
||||
@@ -478,12 +480,12 @@ void reverse() {
|
||||
File pngFile;
|
||||
if (!pngFile.open(options.input, std::ios::out | std::ios::binary)) {
|
||||
// LCOV_EXCL_START
|
||||
fatal("Failed to create \"%s\": %s", pngFile.c_str(options.input), strerror(errno));
|
||||
fatal("Failed to create \"%s\": %s", pngFile.display_name(options.input), strerror(errno));
|
||||
// LCOV_EXCL_STOP
|
||||
}
|
||||
png_structp png = png_create_write_struct(
|
||||
PNG_LIBPNG_VER_STRING,
|
||||
const_cast<char *>(pngFile.c_str(options.input)),
|
||||
const_cast<char *>(pngFile.display_name(options.input)),
|
||||
pngError,
|
||||
pngWarning
|
||||
);
|
||||
@@ -533,22 +535,16 @@ void reverse() {
|
||||
png_color pngPalette[4] = {};
|
||||
png_byte pngTrans[4] = {};
|
||||
int nbPngColors = 0, nbPngTrans = 0;
|
||||
for (auto const &color : palettes[0]) {
|
||||
if (color.has_value()) {
|
||||
pngPalette[nbPngColors].red = color->red;
|
||||
pngPalette[nbPngColors].green = color->green;
|
||||
pngPalette[nbPngColors].blue = color->blue;
|
||||
pngTrans[nbPngColors] = color->alpha;
|
||||
if (color->alpha < 255) {
|
||||
nbPngTrans = nbPngColors;
|
||||
}
|
||||
} else {
|
||||
pngPalette[nbPngColors].red = 255;
|
||||
pngPalette[nbPngColors].green = 255;
|
||||
pngPalette[nbPngColors].blue = 255;
|
||||
pngTrans[nbPngColors] = 255;
|
||||
}
|
||||
for (auto const &slot : palettes[0]) {
|
||||
Rgba color = slot.has_value() ? *slot : Rgba(255, 255, 255, 255);
|
||||
pngPalette[nbPngColors].red = color.red;
|
||||
pngPalette[nbPngColors].green = color.green;
|
||||
pngPalette[nbPngColors].blue = color.blue;
|
||||
pngTrans[nbPngColors] = color.alpha;
|
||||
++nbPngColors;
|
||||
if (color.alpha < 255) {
|
||||
nbPngTrans = nbPngColors;
|
||||
}
|
||||
}
|
||||
png_set_PLTE(png, pngInfo, pngPalette, nbPngColors);
|
||||
if (nbPngTrans > 0) {
|
||||
|
||||
Reference in new issue
Block a user