mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Allow ds to take multiple values to repeat for a count (#725)
Fixes #722
This commit is contained in:
@@ -83,4 +83,11 @@ int yylex(void);
|
|||||||
void lexer_CaptureRept(struct CaptureBody *capture);
|
void lexer_CaptureRept(struct CaptureBody *capture);
|
||||||
void lexer_CaptureMacroBody(struct CaptureBody *capture);
|
void lexer_CaptureMacroBody(struct CaptureBody *capture);
|
||||||
|
|
||||||
|
#define INITIAL_DS_ARG_SIZE 2
|
||||||
|
struct DsArgList {
|
||||||
|
size_t nbArgs;
|
||||||
|
size_t capacity;
|
||||||
|
struct Expression *args;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* RGBDS_ASM_LEXER_H */
|
#endif /* RGBDS_ASM_LEXER_H */
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ void out_AbsLongGroup(uint8_t const *s, int32_t length);
|
|||||||
void out_Skip(int32_t skip, bool ds);
|
void out_Skip(int32_t skip, bool ds);
|
||||||
void out_String(char const *s);
|
void out_String(char const *s);
|
||||||
void out_RelByte(struct Expression *expr, uint32_t pcShift);
|
void out_RelByte(struct Expression *expr, uint32_t pcShift);
|
||||||
void out_RelBytes(struct Expression *expr, uint32_t n);
|
void out_RelBytes(uint32_t n, struct Expression *exprs, size_t size);
|
||||||
void out_RelWord(struct Expression *expr, uint32_t pcShift);
|
void out_RelWord(struct Expression *expr, uint32_t pcShift);
|
||||||
void out_RelLong(struct Expression *expr, uint32_t pcShift);
|
void out_RelLong(struct Expression *expr, uint32_t pcShift);
|
||||||
void out_PCRelByte(struct Expression *expr, uint32_t pcShift);
|
void out_PCRelByte(struct Expression *expr, uint32_t pcShift);
|
||||||
|
|||||||
@@ -310,6 +310,33 @@ static void strfmt(char *dest, size_t destLen, char const *fmt, size_t nbArgs, s
|
|||||||
dest[i] = '\0';
|
dest[i] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void initDsArgList(struct DsArgList *args)
|
||||||
|
{
|
||||||
|
args->nbArgs = 0;
|
||||||
|
args->capacity = INITIAL_DS_ARG_SIZE;
|
||||||
|
args->args = malloc(args->capacity * sizeof(*args->args));
|
||||||
|
if (!args->args)
|
||||||
|
fatalerror("Failed to allocate memory for ds arg list: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t nextDsArgListIndex(struct DsArgList *args)
|
||||||
|
{
|
||||||
|
if (args->nbArgs == args->capacity) {
|
||||||
|
args->capacity = (args->capacity + 1) * 2;
|
||||||
|
args->args = realloc(args->args, args->capacity * sizeof(*args->args));
|
||||||
|
if (!args->args)
|
||||||
|
fatalerror("realloc error while resizing ds arg list: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
|
return args->nbArgs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void freeDsArgList(struct DsArgList *args)
|
||||||
|
{
|
||||||
|
free(args->args);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void failAssert(enum AssertionType type)
|
static inline void failAssert(enum AssertionType type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@@ -397,6 +424,7 @@ enum {
|
|||||||
struct SectionSpec sectSpec;
|
struct SectionSpec sectSpec;
|
||||||
struct MacroArgs *macroArg;
|
struct MacroArgs *macroArg;
|
||||||
enum AssertionType assertType;
|
enum AssertionType assertType;
|
||||||
|
struct DsArgList dsArgs;
|
||||||
struct {
|
struct {
|
||||||
int32_t start;
|
int32_t start;
|
||||||
int32_t stop;
|
int32_t stop;
|
||||||
@@ -537,6 +565,8 @@ enum {
|
|||||||
%type <sectMod> sectmod
|
%type <sectMod> sectmod
|
||||||
%type <macroArg> macroargs
|
%type <macroArg> macroargs
|
||||||
|
|
||||||
|
%type <dsArgs> ds_args
|
||||||
|
|
||||||
%type <forArgs> for_args
|
%type <forArgs> for_args
|
||||||
|
|
||||||
%token T_Z80_ADC "adc" T_Z80_ADD "add" T_Z80_AND "and"
|
%token T_Z80_ADC "adc" T_Z80_ADD "add" T_Z80_AND "and"
|
||||||
@@ -946,8 +976,23 @@ endu : T_POP_ENDU { sect_EndUnion(); }
|
|||||||
;
|
;
|
||||||
|
|
||||||
ds : T_POP_DS uconst { out_Skip($2, true); }
|
ds : T_POP_DS uconst { out_Skip($2, true); }
|
||||||
| T_POP_DS uconst T_COMMA reloc_8bit {
|
| T_POP_DS uconst T_COMMA ds_args {
|
||||||
out_RelBytes(&$4, $2);
|
out_RelBytes($2, $4.args, $4.nbArgs);
|
||||||
|
freeDsArgList(&$4);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
ds_args : reloc_8bit {
|
||||||
|
initDsArgList(&$$);
|
||||||
|
size_t i = nextDsArgListIndex(&$$);
|
||||||
|
|
||||||
|
$$.args[i] = $1;
|
||||||
|
}
|
||||||
|
| ds_args T_COMMA reloc_8bit {
|
||||||
|
size_t i = nextDsArgListIndex(&$1);
|
||||||
|
|
||||||
|
$1.args[i] = $3;
|
||||||
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@@ -1265,7 +1310,7 @@ relocexpr_no_str : scoped_anon_id { rpn_Symbol(&$$, $1); }
|
|||||||
| relocexpr T_OP_XOR relocexpr {
|
| relocexpr T_OP_XOR relocexpr {
|
||||||
rpn_BinaryOp(RPN_XOR, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_XOR, &$$, &$1, &$3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_OR relocexpr {
|
| relocexpr T_OP_OR relocexpr {
|
||||||
rpn_BinaryOp(RPN_OR, &$$, &$1, &$3);
|
rpn_BinaryOp(RPN_OR, &$$, &$1, &$3);
|
||||||
}
|
}
|
||||||
| relocexpr T_OP_AND relocexpr {
|
| relocexpr T_OP_AND relocexpr {
|
||||||
|
|||||||
@@ -1239,10 +1239,13 @@ DW "H", "e", "l", "l", "o", "!"
|
|||||||
If you do not want this special handling, enclose the string in parentheses.
|
If you do not want this special handling, enclose the string in parentheses.
|
||||||
.Pp
|
.Pp
|
||||||
.Ic DS
|
.Ic DS
|
||||||
can also be used to fill a region of memory with some value.
|
can also be used to fill a region of memory with some repeated values.
|
||||||
The following produces 42 times the byte $FF:
|
For example:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
DS 42, $FF
|
; outputs 3 bytes: $AA, $AA, $AA
|
||||||
|
DS 3, $AA
|
||||||
|
; outputs 7 bytes: $BB, $CC, $BB, $CC, $BB, $CC, $BB
|
||||||
|
DS 7, $BB, $CC
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
You can also use
|
You can also use
|
||||||
|
|||||||
@@ -637,12 +637,14 @@ void out_RelByte(struct Expression *expr, uint32_t pcShift)
|
|||||||
* Output several copies of a relocatable byte. Checking will be done to see if
|
* Output several copies of a relocatable byte. Checking will be done to see if
|
||||||
* it is an absolute value in disguise.
|
* it is an absolute value in disguise.
|
||||||
*/
|
*/
|
||||||
void out_RelBytes(struct Expression *expr, uint32_t n)
|
void out_RelBytes(uint32_t n, struct Expression *exprs, size_t size)
|
||||||
{
|
{
|
||||||
checkcodesection();
|
checkcodesection();
|
||||||
reserveSpace(n);
|
reserveSpace(n);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < n; i++) {
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
|
struct Expression *expr = &exprs[i % size];
|
||||||
|
|
||||||
if (!rpn_isKnown(expr)) {
|
if (!rpn_isKnown(expr)) {
|
||||||
createPatch(PATCHTYPE_BYTE, expr, i);
|
createPatch(PATCHTYPE_BYTE, expr, i);
|
||||||
writebyte(0);
|
writebyte(0);
|
||||||
@@ -650,7 +652,9 @@ void out_RelBytes(struct Expression *expr, uint32_t n)
|
|||||||
writebyte(expr->nVal);
|
writebyte(expr->nVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rpn_Free(expr);
|
|
||||||
|
for (size_t i = 0; i < size; i++)
|
||||||
|
rpn_Free(&exprs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
SECTION "test fixed", ROM0[0]
|
SECTION "test fixed", ROM0[0]
|
||||||
|
|
||||||
FixedStart:
|
FixedStart:
|
||||||
ds 8, (@ - FixedStart) * 2 + zero
|
ds 6, (@ - FixedStart) * 2 + zero
|
||||||
ds 8, (@ - FixedStart) * 2 + zero
|
ds 10, (@ - FixedStart) + zero, (@ - FixedStart) * 3 + zero, (@ - FixedStart) * 4 + zero
|
||||||
|
|
||||||
SECTION "test floating", ROM0
|
SECTION "test floating", ROM0
|
||||||
|
|
||||||
FloatingStart:
|
FloatingStart:
|
||||||
ds 8, (@ - FloatingStart) * 2 + zero
|
ds 6, (@ - FloatingStart) * 2 + zero
|
||||||
ds 8, (@ - FloatingStart) * 2 + zero
|
ds 10, (@ - FloatingStart) + zero, (@ - FloatingStart) * 3 + zero, (@ - FloatingStart) * 4 + zero
|
||||||
|
|
||||||
SECTION "zero", ROM0[0]
|
SECTION "zero", ROM0[0]
|
||||||
zero:
|
zero:
|
||||||
|
|||||||
Binary file not shown.
@@ -6,3 +6,4 @@ Label:
|
|||||||
ds 5, .other - Label - 5 ; Expressions should work...
|
ds 5, .other - Label - 5 ; Expressions should work...
|
||||||
ds 60, .last - Label ; ...even if not constant
|
ds 60, .last - Label ; ...even if not constant
|
||||||
.last
|
.last
|
||||||
|
ds 11, $67, $89
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
****<2A><><EFBFBD><EFBFBD><EFBFBD>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
|
****<2A><><EFBFBD><EFBFBD><EFBFBD>EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEg<EFBFBD>g<EFBFBD>g<EFBFBD>g<EFBFBD>g<EFBFBD>g
|
||||||
Reference in New Issue
Block a user