Allow negative from-the-end starting indexes in INCBIN (#2181)

This commit is contained in:
Rangi authored and GitHub committed 2026-09-28 20:43:14 -04:00
1 parent ad4e399018
commit c592d665a8
8 files changed
+38 -11

No files matched your search

+1 -1
View File
@@ -103,7 +103,7 @@ void sect_RelBytes(uint32_t n, std::vector<Expression> const &exprs);
void sect_RelWord(Expression const &expr, uint32_t pcShift); void sect_RelWord(Expression const &expr, uint32_t pcShift);
void sect_RelLong(Expression const &expr, uint32_t pcShift); void sect_RelLong(Expression const &expr, uint32_t pcShift);
void sect_PCRelByte(Expression const &expr, uint32_t pcShift); void sect_PCRelByte(Expression const &expr, uint32_t pcShift);
bool sect_BinaryFile(std::string const &name, uint32_t startPos, std::optional<uint32_t> length); bool sect_BinaryFile(std::string const &name, int32_t startPos, std::optional<uint32_t> length);
void sect_EndSection(); void sect_EndSection();
void sect_PushSection(); void sect_PushSection();
+2 -1
View File
@@ -1906,13 +1906,14 @@ INCBIN "sprites/hero.bin"
.Pp .Pp
You can also include only part of a file with You can also include only part of a file with
.Ic INCBIN . .Ic INCBIN .
The example below includes 256 bytes from data.bin, starting from byte 78. The example below includes 256 bytes from data.bin, starting from byte 78 (byte positions start from 0).
.Bd -literal -offset indent .Bd -literal -offset indent
INCBIN "data.bin", 78, 256 INCBIN "data.bin", 78, 256
.Ed .Ed
.Pp .Pp
The length argument is optional. The length argument is optional.
If only the start position is specified, the bytes from the start position until the end of the file will be included. If only the start position is specified, the bytes from the start position until the end of the file will be included.
Negative start positions count from the end of the file, so the last byte is at position -1.
.Ss Statically allocating space in RAM .Ss Statically allocating space in RAM
.Ic DS .Ic DS
statically allocates a number of empty bytes. statically allocates a number of empty bytes.
+2 -2
View File
@@ -1052,12 +1052,12 @@ incbin:
YYACCEPT; YYACCEPT;
} }
} }
| POP_INCBIN string COMMA uconst { | POP_INCBIN string COMMA iconst {
if (sect_BinaryFile($2, $4, std::nullopt)) { if (sect_BinaryFile($2, $4, std::nullopt)) {
YYACCEPT; YYACCEPT;
} }
} }
| POP_INCBIN string COMMA uconst COMMA uconst { | POP_INCBIN string COMMA iconst COMMA uconst {
if (sect_BinaryFile($2, $4, $6)) { if (sect_BinaryFile($2, $4, $6)) {
YYACCEPT; YYACCEPT;
} }
+26 -5
View File
@@ -998,7 +998,7 @@ void sect_PCRelByte(Expression const &expr, uint32_t pcShift) {
} }
} }
bool sect_BinaryFile(std::string const &name, uint32_t startPos, std::optional<uint32_t> length) { bool sect_BinaryFile(std::string const &name, int32_t startPos, std::optional<uint32_t> length) {
if (!requireCodeSection()) { if (!requireCodeSection()) {
return false; return false;
} }
@@ -1016,18 +1016,31 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos, std::optional<u
Defer closeFile{[&] { xfclose(file); }}; Defer closeFile{[&] { xfclose(file); }};
if (std::optional<uint64_t> fileSize = seekSize(file); fileSize.has_value()) { if (std::optional<uint64_t> fileSize = seekSize(file); fileSize.has_value()) {
if (startPos > *fileSize) { // Adjust negative start positions such that -1 is the last byte of a file
if (startPos < 0) {
startPos += *fileSize;
}
if (startPos < 0) {
error( error(
"Specified start position (%" PRIu32 ") is greater than length of \"%s\" (%" PRIu64 "Specified start position (%" PRId32 ") is before the start of \"%s\" (%" PRIu64
")", ")",
startPos, startPos,
name.c_str(), name.c_str(),
*fileSize *fileSize
); );
return false; return false;
} else if (length.has_value() && *length > *fileSize - startPos) { } else if (uint32_t pos = static_cast<uint32_t>(startPos); pos > *fileSize) {
error( error(
"Specified range in `INCBIN` file \"%s\" is out of bounds (%" PRIu32 " + %" PRIu32 "Specified start position (%" PRId32 ") is greater than length of \"%s\" (%" PRIu64
")",
startPos,
name.c_str(),
*fileSize
);
return false;
} else if (length.has_value() && *length > *fileSize - pos) {
error(
"Specified range in `INCBIN` file \"%s\" is out of bounds (%" PRId32 " + %" PRIu32
" > %" PRIu64 ")", " > %" PRIu64 ")",
name.c_str(), name.c_str(),
startPos, startPos,
@@ -1045,6 +1058,14 @@ bool sect_BinaryFile(std::string const &name, uint32_t startPos, std::optional<u
"Error determining size of `INCBIN` file \"%s\": %s", name.c_str(), strerror(errno) "Error determining size of `INCBIN` file \"%s\": %s", name.c_str(), strerror(errno)
); );
} }
if (startPos < 0) {
error(
"Specified start position (%" PRId32 ") is negative and size of \"%s\" is unknown",
startPos,
name.c_str()
);
return false;
}
// The file isn't seekable, so we'll just skip bytes one at a time // The file isn't seekable, so we'll just skip bytes one at a time
while (startPos--) { while (startPos--) {
if (fgetc(file) == EOF) { if (fgetc(file) == EOF) {
+1 -1
View File
@@ -1,3 +1,3 @@
SECTION "Bad", ROM0 SECTION "Bad", ROM0
INCBIN "data.bin", -42 INCBIN "data.bin", -420
+2 -1
View File
@@ -1,2 +1,3 @@
FATAL: Constant must not be negative: -42 error: Specified start position (-297) is before the start of "data.bin" (123)
at incbin-negative-bad.asm(3) at incbin-negative-bad.asm(3)
Assembly aborted with 1 error
+3
View File
@@ -0,0 +1,3 @@
section "test", rom0
incbin "data.bin", -6 ; b0 9b c1 bd 20 db
incbin "data.bin", -123, 10 ; 51 c7 c0 ed 02 f0 2b 29 57 2d
+1
View File
@@ -0,0 +1 @@
°›Á˝ ŰQÇŔíđ+)W-