Compare commits

...

32 Commits

Author SHA1 Message Date
Antonio Niño Díaz
fe65e07cb6 Fail when using negative constants if not allowed
Some commands, such as `DS`, `BANK[n]`, etc, don't allow the use of
negative constants, but there wasn't any check to prohibit the code from
trying to do so.

This patch adds the `uconst` type to the parser to use when a constant
is expected, but it mustn't be negative.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-07-01 14:31:58 +01:00
Antonio Niño Díaz
bb12806da1 Fix indentation
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-07-01 14:31:58 +01:00
Antonio Niño Díaz
fa36042131 Add missing documentation of RL command
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-07-01 14:31:39 +01:00
Antonio Niño Díaz
efaad99f25 Update manpage documentation about labels
- Local labels can now be exported.
- Local labels can be declared as Scope.Label in addition of .Label.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-06-13 20:16:42 +01:00
Antonio Niño Díaz
62d820c261 Merge pull request #181 from Ben10do/reference-local-symbols
Allow local labels to be referenced (and exported)

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-06-12 21:46:32 +01:00
Ben10do
a53d795361 Add tests for explicit definitions of local labels
These check that “Parent.child” may be used in place of “.child”, and that “WrongParent.child” may not be used in the scope of “Parent”.
2017-06-12 19:50:02 +01:00
Sanqui
2e60c4dd2e Add tests for remote local symbols 2017-06-12 19:36:52 +01:00
Ben10do
ce8a13a562 Allow local symbols to be referenced
Local symbols can now be referenced outside the scope of their parent, by using the syntax “Parent.Chlid”.

- Local symbol names are now stored internally as “Parent.Child”.
- The symbol’s scope field no longer forms a linked list of the prior local symbols; it will now always contain the parent.
- Add the ability use EXPORT and GLOBAL with local symbols.
- Reduce duplication between findsymbol() and findpsymbol(), as well as between sym_AddLocalReloc() and sym_AddReloc().
2017-06-12 19:36:46 +01:00
Antonio Niño Díaz
ff2321a8ce Make fatalerror and yyerror consistent
There are two ways in which the assembly process can fail:

1. If there is a really big problem that compromises the whole process,
   the assembler has to stop right there and generate an error message.
   This happens with unterminated REPT loops, macros, etc.

2. If the problem isn't that big and the process can still continue,
   even though the final result is invalid, the assembler can try to
   continue and warn the user about all errors it finds in the code.

This patch clarifies the use of each function and replaces the function
used in two places by the correct one.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-29 15:02:57 +01:00
Antonio Niño Díaz
4228e3e890 Document dependency problem for EQUS and MACRO
This is hard to detect in MACROs, as there are legitimate uses for
MACROs that call themselves recursively.

For an EQUS, the problem is that its value may be modified at different
points in the source code, so the only way to detect a possible problem
is by doing an analysis at each usage of the EQUS.

Also, since an EQUS may expand to the name of a MACRO and a MACRO can
use an EQUS, it becomes even harder to check all possible problems that
come out of it. It's better to let this task to the programmer.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-26 22:02:47 +01:00
Antonio Niño Díaz
023b574fc5 New warning for rgbasm and fixes in error messages
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-26 00:57:29 +02:00
Antonio Niño Díaz
a77df57f1c Merge pull request #177 from AntonioND/an/section-checks
Improve section size checks and buffer handling

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-25 13:31:06 +02:00
Antonio Niño Díaz
8f553e89ce Merge pull request #176 from makefile-cleanup
Cleanup Makefile

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-25 13:29:52 +02:00
Antonio Niño Díaz
b7810ffdb3 Check for section overflows in rgbasm
When allocating a section, allocate only the max possible size for that
type (only applies to ROM0 and ROMX).

When finding an overflow, in any kind of section, output an error with
the location of the line of code that caused the overflow.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-24 14:29:27 +02:00
Antonio Niño Díaz
0d3401058d Check max section sizes in rgblink
The max size of some section types depends on the flags passed to
rgblink. Instead of doing in rgbasm some checks (for the sections with
fixed size) and others in rgblink, all checks are now done in rgblink.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-24 02:05:30 +02:00
Antonio Niño Díaz
6e123ccc36 Optimize allocation of buffers for sections
Instead of allocating 0x4000 bytes for all sections and resize them as
needed, allocate 0x8000 bytes and don't let them to be resized. This is
the max possible size (ROM0 when ROMX sections aren't present).

Buffers are not needed for RAM sections, this patch changes the code so
that it only allocates buffers for ROM sections.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-24 02:05:30 +02:00
Antonio Niño Díaz
f2724df566 Fix rgblink error messages about prohibited sections
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-23 20:45:39 +02:00
Antonio Niño Díaz
646d71d927 Remove unused code
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-23 20:25:19 +02:00
Antonio Niño Díaz
9b9b41e605 Fix install instructions
It isn't needed to create the folders manually, the Makefile does it
automatically.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-23 14:34:33 +02:00
Antonio Niño Díaz
907ccfb280 Cleanup Makefile 2017-04-23 13:32:32 +02:00
Antonio Niño Díaz
fcd7c117e7 Fix man page documentation for dependcy files
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-22 11:43:28 +02:00
Antonio Niño Díaz
323922d854 Merge pull request #174 from makedepend
Generate make-style dependency files

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-22 11:40:16 +02:00
Antonio Niño Díaz
f97e3bad33 Merge pull request #171 from NieDzejkob/master
Implement separate time constants

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-22 11:36:59 +02:00
Antonio Niño Díaz
64415555f1 Merge pull request #175 from NieDzejkob/man
Fix some man installation locations

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-19 19:46:58 +01:00
NieDzejkob
ab2aef3f2b Fix some man installation locations 2017-04-19 13:18:18 +02:00
NieDzejkob
947db1e21b Implement numeric time and date constants 2017-04-19 13:12:08 +02:00
Antonio Niño Díaz
cde607c09c Deps file can only be created if object file specified
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 22:02:18 +01:00
Antonio Niño Díaz
739b113f57 Print dependencies of all included files
Files that weren't found with the absolute path weren't added as
dependencies even if they were found after considering the list of
include directories.

This patch makes rgbasm print the complete path (including the include
directory path) in these cases.

Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 20:27:58 +01:00
Antonio Niño Díaz
64585eebf6 Merge branch 'makedepend'
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 19:29:25 +01:00
Antonio Niño Díaz
1050acc290 Remove useless link in documentation
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 18:21:08 +01:00
Antonio Niño Díaz
466bb9ed0b Fix links in man pages
Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
2017-04-17 18:14:49 +01:00
Anthony J. Bentley
581133ecce Output make-style dependencies with -M. 2015-12-11 01:06:19 -07:00
32 changed files with 505 additions and 255 deletions

View File

@@ -1,6 +0,0 @@
# GNU Make 3.x doesn't support the "!=" shell syntax, so here's an alternative
PKG_CONFIG = pkg-config
PNGFLAGS = $(shell ${PKG_CONFIG} --cflags libpng)
include Makefile

165
Makefile
View File

@@ -1,25 +1,35 @@
PKG_CONFIG = pkg-config
WARNFLAGS = -Wall -Werror
PNGFLAGS != ${PKG_CONFIG} --cflags libpng
REALCFLAGS = ${CFLAGS} ${WARNFLAGS} ${PNGFLAGS} -Iinclude -g \
-std=c99 -D_POSIX_C_SOURCE=200809L
# User-defined variables
Q := @
PREFIX := /usr/local
bindir := ${PREFIX}/bin
mandir := ${PREFIX}/man
STRIP := -s
BINMODE := 555
MANMODE := 444
# Other variables
PKG_CONFIG := pkg-config
PNGCFLAGS := `${PKG_CONFIG} --static --cflags libpng`
PNGLDFLAGS := `${PKG_CONFIG} --static --libs-only-L libpng`
PNGLDLIBS := `${PKG_CONFIG} --static --libs-only-l libpng`
WARNFLAGS := -Wall -Werror
CFLAGS := ${WARNFLAGS} -g -std=c99 -D_POSIX_C_SOURCE=200809L -Iinclude
YFLAGS :=
LFLAGS := --nounistd
YACC := yacc
FLEX := flex
LEX := flex
RM := rm -rf
# User-defined variables
PREFIX = /usr/local
bindir = ${PREFIX}/bin
mandir = ${PREFIX}/man
Q = @
STRIP = -s
BINMODE = 555
MANMODE = 444
# Rules to build the RGBDS binaries
rgbasm_obj = \
all: rgbasm rgblink rgbfix rgbgfx
rgbasm_obj := \
src/asm/asmy.o \
src/asm/charmap.o \
src/asm/fstack.o \
@@ -36,7 +46,10 @@ rgbasm_obj = \
src/extern/strlcpy.o \
src/extern/strlcat.o
rgblink_obj = \
src/asm/asmy.h: src/asm/asmy.c
src/asm/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h
rgblink_obj := \
src/link/assign.o \
src/link/lexer.o \
src/link/library.o \
@@ -50,17 +63,46 @@ rgblink_obj = \
src/link/symbol.o \
src/extern/err.o
rgbfix_obj = \
src/link/parser.h: src/link/parser.c
src/link/lexer.o: src/link/parser.h
rgbfix_obj := \
src/fix/main.o \
src/extern/err.o
rgbgfx_obj = \
rgbgfx_obj := \
src/gfx/gb.o \
src/gfx/main.o \
src/gfx/makepng.o \
src/extern/err.o
all: rgbasm rgblink rgbfix rgbgfx
rgbasm: ${rgbasm_obj}
$Q${CC} ${CFLAGS} -o $@ ${rgbasm_obj} -lm
rgblink: ${rgblink_obj}
$Q${CC} ${CFLAGS} -o $@ ${rgblink_obj}
rgbfix: ${rgbfix_obj}
$Q${CC} ${CFLAGS} -o $@ ${rgbfix_obj}
rgbgfx: ${rgbgfx_obj}
$Q${CC} ${CFLAGS} ${PNGLDFLAGS} -o $@ ${rgbgfx_obj} ${PNGLDLIBS}
# Rules to process files
.y.c:
$Q${YACC} -d ${YFLAGS} -o $@ $<
.l.o:
$Q${RM} $*.c
$Q${LEX} ${LFLAGS} -o $*.c $<
$Q${CC} ${CFLAGS} -c -o $@ $*.c
$Q${RM} $*.c
.c.o:
$Q${CC} ${CFLAGS} ${PNGCFLAGS} -c -o $@ $<
# Target used to remove all files generated by other Makefile targets.
clean:
$Q${RM} rgbds.7.html gbz80.7.html rgbds.5.html
@@ -71,6 +113,8 @@ clean:
$Q${RM} src/asm/asmy.c src/asm/asmy.h
$Q${RM} src/link/lexer.c src/link/parser.c src/link/parser.h
# Target used to install the binaries and man pages.
install: all
$Qmkdir -p ${DESTDIR}${bindir}
$Qinstall ${STRIP} -m ${BINMODE} rgbasm ${DESTDIR}${bindir}/rgbasm
@@ -80,70 +124,18 @@ install: all
$Qmkdir -p ${DESTDIR}${mandir}/man1 ${DESTDIR}${mandir}/man5 ${DESTDIR}${mandir}/man7
$Qinstall -m ${MANMODE} src/rgbds.7 ${DESTDIR}${mandir}/man7/rgbds.7
$Qinstall -m ${MANMODE} src/gbz80.7 ${DESTDIR}${mandir}/man7/gbz80.7
$Qinstall -m ${MANMODE} src/rgbds.5 ${DESTDIR}${mandir}/man7/rgbds.5
$Qinstall -m ${MANMODE} src/rgbds.5 ${DESTDIR}${mandir}/man5/rgbds.5
$Qinstall -m ${MANMODE} src/asm/rgbasm.1 ${DESTDIR}${mandir}/man1/rgbasm.1
$Qinstall -m ${MANMODE} src/asm/rgbasm.5 ${DESTDIR}${mandir}/man1/rgbasm.5
$Qinstall -m ${MANMODE} src/asm/rgbasm.5 ${DESTDIR}${mandir}/man5/rgbasm.5
$Qinstall -m ${MANMODE} src/fix/rgbfix.1 ${DESTDIR}${mandir}/man1/rgbfix.1
$Qinstall -m ${MANMODE} src/link/rgblink.1 ${DESTDIR}${mandir}/man1/rgblink.1
$Qinstall -m ${MANMODE} src/link/rgblink.5 ${DESTDIR}${mandir}/man5/rgblink.5
$Qinstall -m ${MANMODE} src/gfx/rgbgfx.1 ${DESTDIR}${mandir}/man1/rgbgfx.1
rgbasm: ${rgbasm_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgbasm_obj} -lm
rgblink: ${rgblink_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgblink_obj}
rgbfix: ${rgbfix_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgbfix_obj}
rgbgfx: ${rgbgfx_obj}
$Q${CC} ${REALCFLAGS} -o $@ ${rgbgfx_obj} `${PKG_CONFIG} --libs libpng`
.y.c:
$Q${YACC} -d ${YFLAGS} -o $@ $<
.l.o:
$Q${RM} $*.c
$Q${FLEX} ${LFLAGS} -o $*.c $<
$Q${CC} ${REALCFLAGS} -c -o $@ $*.c
$Q${RM} $*.c
.c.o:
$Q${CC} ${REALCFLAGS} -c -o $@ $<
src/asm/locallex.o src/asm/globlex.o src/asm/lexer.o: src/asm/asmy.h
src/asm/asmy.h: src/asm/asmy.c
src/link/lexer.o : src/link/parser.h
src/link/parser.h : src/link/parser.c
# Below is a target for the project maintainer to easily create win32 exes.
# This is not for Windows users!
# If you're building on Windows with Cygwin or Mingw, just follow the Unix
# install instructions instead.
mingw:
$Q${RM} win32 win64
$Qmkdir win32 win64
$Qenv make clean
$Qenv PKG_CONFIG_PATH=/usr/i686-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=i686-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm win32/rgbasm.exe
$Qmv rgblink win32/rgblink.exe
$Qmv rgbfix win32/rgbfix.exe
$Qmv rgbgfx win32/rgbgfx.exe
$Qenv make clean
$Qenv PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=x86_64-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm win64/rgbasm.exe
$Qmv rgblink win64/rgblink.exe
$Qmv rgbfix win64/rgbfix.exe
$Qmv rgbgfx win64/rgbgfx.exe
$Qenv make clean
# Below is a target for the project maintainer to easily create web manuals.
# Target for the project maintainer to easily create web manuals.
# It relies on mandoc: http://mdocml.bsd.lv
MANDOC = -Thtml -Ios=General -Oman=%N.%S.html -Ostyle=manual.css
MANDOC := -Thtml -Ios=General -Oman=%N.%S.html -Ostyle=manual.css
wwwman:
$Qmandoc ${MANDOC} src/rgbds.7 > rgbds.7.html
@@ -155,3 +147,24 @@ wwwman:
$Qmandoc ${MANDOC} src/link/rgblink.1 > rgblink.1.html
$Qmandoc ${MANDOC} src/link/rgblink.5 > rgblink.5.html
$Qmandoc ${MANDOC} src/gfx/rgbgfx.1 > rgbgfx.1.html
# Targets for the project maintainer to easily create Windows exes.
# This is not for Windows users!
# If you're building on Windows with Cygwin or Mingw, just follow the Unix
# install instructions instead.
mingw32:
$Qenv PKG_CONFIG_PATH=/usr/i686-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=i686-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm rgbasm.exe
$Qmv rgblink rgblink.exe
$Qmv rgbfix rgbfix.exe
$Qmv rgbgfx rgbgfx.exe
mingw64:
$Qenv PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/sys-root/mingw/lib/pkgconfig/ \
make CC=x86_64-w64-mingw32-gcc YACC=bison WARNFLAGS= -j
$Qmv rgbasm rgbasm.exe
$Qmv rgblink rgblink.exe
$Qmv rgbfix rgbfix.exe
$Qmv rgbgfx rgbgfx.exe

View File

@@ -110,7 +110,6 @@ make command line. For example, to install RGBDS in your home directory instead
of systemwide, run the following:
```sh
mkdir -p $HOME/{bin,man/man1,man/man7}
make install PREFIX=$HOME
```

View File

@@ -80,8 +80,6 @@
*/
#define MAXSECTIONSIZE 0x4000
#define NAME_DB "db"
#define NAME_DW "dw"
#define NAME_RB "rb"

View File

@@ -26,8 +26,25 @@ extern void opt_Push(void);
extern void opt_Pop(void);
extern void opt_Parse(char *s);
/*
* Used for errors that compromise the whole assembly process by affecting the
* folliwing code, potencially making the assembler generate errors caused by
* the first one and unrelated to the code that the assembler complains about.
* It is also used when the assembler goes into an invalid state (for example,
* when it fails to allocate memory).
*/
noreturn void fatalerror(const char *fmt, ...);
/*
* Used for errors that make it impossible to assemble correctly, but don't
* affect the following code. The code will fail to assemble but the user will
* get a list of all errors at the end, making it easier to fix all of them at
* once.
*/
void yyerror(const char *fmt, ...);
/*
* Used to warn the user about problems that don't prevent the generation of
* valid code.
*/
void warning(const char *fmt, ...);
#define YY_FATAL_ERROR fatalerror

View File

@@ -439,6 +439,7 @@ void if_skip_to_endc( void )
%type <sVal> relocconst
%type <nConstValue> const
%type <nConstValue> uconst
%type <nConstValue> const_3bit
%type <sVal> const_8bit
%type <sVal> const_16bit
@@ -587,7 +588,11 @@ label : /* empty */
else
sym_AddReloc($1);
} | T_LABEL ':' ':' {
sym_AddReloc($1);
if ($1[0] == '.') {
sym_AddLocalReloc($1);
} else {
sym_AddReloc($1);
}
sym_Export($1);
};
@@ -688,7 +693,7 @@ shift : T_POP_SHIFT
{ sym_ShiftCurrentMacroArgs(); }
;
rept : T_POP_REPT const
rept : T_POP_REPT uconst
{
copyrept();
fstk_RunRept( $2 );
@@ -706,7 +711,7 @@ equs : T_LABEL T_POP_EQUS string
{ sym_AddString( $1, $3 ); }
;
rsset : T_POP_RSSET const
rsset : T_POP_RSSET uconst
{ sym_AddSet( "_RS", $2 ); }
;
@@ -714,28 +719,28 @@ rsreset : T_POP_RSRESET
{ sym_AddSet( "_RS", 0 ); }
;
rl : T_LABEL T_POP_RL const
rl : T_LABEL T_POP_RL uconst
{
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+4*$3 );
}
;
rw : T_LABEL T_POP_RW const
rw : T_LABEL T_POP_RW uconst
{
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+2*$3 );
}
;
rb : T_LABEL T_POP_RB const
rb : T_LABEL T_POP_RB uconst
{
sym_AddEqu( $1, sym_GetConstantValue("_RS") );
sym_AddSet( "_RS", sym_GetConstantValue("_RS")+$3 );
}
;
ds : T_POP_DS const
ds : T_POP_DS uconst
{ out_Skip( $2 ); }
;
@@ -817,7 +822,7 @@ include : T_POP_INCLUDE string
incbin : T_POP_INCBIN string
{ out_BinaryFile( $2 ); }
| T_POP_INCBIN string ',' const ',' const
| T_POP_INCBIN string ',' uconst ',' uconst
{
out_BinaryFileSlice( $2, $4, $6 );
}
@@ -1038,6 +1043,14 @@ relocconst : T_ID
{ $$ = $2; }
;
uconst : const
{
if($1 < 0)
fatalerror("Constant mustn't be negative: %d", $1);
$$=$1;
}
;
const : T_ID { $$ = sym_GetConstantValue($1); }
| T_NUMBER { $$ = $1; }
| string { $$ = str2int($1); }
@@ -1064,16 +1077,18 @@ const : T_ID { $$ = sym_GetConstantValue($1); }
| const T_OP_SHL const { $$ = $1 << $3; }
| const T_OP_SHR const { $$ = $1 >> $3; }
| const T_OP_MUL const { $$ = $1 * $3; }
| const T_OP_DIV const {
if ($3 == 0)
fatalerror("division by zero");
$$ = $1 / $3;
}
| const T_OP_MOD const {
if ($3 == 0)
fatalerror("division by zero");
$$ = $1 % $3;
}
| const T_OP_DIV const
{
if ($3 == 0)
fatalerror("division by zero");
$$ = $1 / $3;
}
| const T_OP_MOD const
{
if ($3 == 0)
fatalerror("division by zero");
$$ = $1 % $3;
}
| T_OP_ADD const %prec NEG { $$ = +$2; }
| T_OP_SUB const %prec NEG { $$ = -$2; }
| T_OP_NOT const %prec NEG { $$ = 0xFFFFFFFF^$2; }
@@ -1109,7 +1124,7 @@ const : T_ID { $$ = sym_GetConstantValue($1); }
string : T_STRING
{ strcpy($$,$1); }
| T_OP_STRSUB '(' string ',' const ',' const ')'
| T_OP_STRSUB '(' string ',' uconst ',' uconst ')'
{ strncpy($$,$3+$5-1,$7); $$[$7]=0; }
| T_OP_STRCAT '(' string ',' string ')'
{ strcpy($$,$3); strcat($$,$5); }
@@ -1123,33 +1138,33 @@ section:
{
out_NewSection($2,$4);
}
| T_POP_SECTION string ',' sectiontype '[' const ']'
| T_POP_SECTION string ',' sectiontype '[' uconst ']'
{
if( $6>=0 && $6<0x10000 )
out_NewAbsSection($2,$4,$6,-1);
else
yyerror("Address $%x not 16-bit", $6);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']'
| T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' uconst ']'
{
out_NewAlignedSection($2, $4, $8, -1);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']'
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' uconst ']'
{
bankrangecheck($2, $4, -1, $8);
}
| T_POP_SECTION string ',' sectiontype '[' const ']' ',' T_OP_BANK '[' const ']'
| T_POP_SECTION string ',' sectiontype '[' uconst ']' ',' T_OP_BANK '[' uconst ']'
{
if ($6 < 0 || $6 > 0x10000) {
yyerror("Address $%x not 16-bit", $6);
}
bankrangecheck($2, $4, $6, $11);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']' ',' T_OP_BANK '[' const ']'
| T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' uconst ']' ',' T_OP_BANK '[' uconst ']'
{
out_NewAlignedSection($2, $4, $8, $13);
}
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']' ',' T_OP_ALIGN '[' const ']'
| T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' uconst ']' ',' T_OP_ALIGN '[' uconst ']'
{
out_NewAlignedSection($2, $4, $13, $8);
}
@@ -1351,7 +1366,7 @@ z80_ldio : T_Z80_LDIO T_MODE_A comma op_mem_ind
if( (!rpn_isReloc(&$4))
&& ($4.nVal<0 || ($4.nVal>0xFF && $4.nVal<0xFF00) || $4.nVal>0xFFFF) )
{
yyerror("Source address $%x not in HRAM ($FF00 to $FFFE)", $4.nVal);
yyerror("Source address $%x not in $FF00 to $FFFF", $4.nVal);
}
out_AbsByte(0xF0);
@@ -1365,7 +1380,7 @@ z80_ldio : T_Z80_LDIO T_MODE_A comma op_mem_ind
if( (!rpn_isReloc(&$2))
&& ($2.nVal<0 || ($2.nVal>0xFF && $2.nVal<0xFF00) || $2.nVal>0xFFFF) )
{
yyerror("Destination address $%x not in HRAM ($FF00 to $FFFE)", $2.nVal);
yyerror("Destination address $%x not in $FF00 to $FFFF", $2.nVal);
}
out_AbsByte(0xE0);
@@ -1385,7 +1400,10 @@ z80_ld : z80_ld_mem
;
z80_ld_hl : T_Z80_LD T_MODE_HL comma '[' T_MODE_SP const_8bit ']'
{ out_AbsByte(0xF8); out_RelByte(&$6); }
{
out_AbsByte(0xF8); out_RelByte(&$6);
warning("'LD HL,[SP+e8]' is obsolete, use 'LD HL,SP+e8' instead.");
}
| T_Z80_LD T_MODE_HL comma T_MODE_SP const_8bit
{ out_AbsByte(0xF8); out_RelByte(&$5); }
| T_Z80_LD T_MODE_HL comma const_16bit

View File

@@ -36,6 +36,9 @@ ULONG nCurrentREPTBlockCount;
ULONG ulMacroReturnValue;
extern char *tzObjectname;
extern FILE *dependfile;
/*
* defines for nCurrentStatus
*/
@@ -198,6 +201,9 @@ fstk_FindFile(char *fname)
FILE *f;
if ((f = fopen(fname, "rb")) != NULL || errno != ENOENT) {
if (dependfile) {
fprintf(dependfile, "%s: %s\n", tzObjectname, fname);
}
return f;
}
@@ -211,6 +217,9 @@ fstk_FindFile(char *fname)
}
if ((f = fopen(path, "rb")) != NULL || errno != ENOENT) {
if (dependfile) {
fprintf(dependfile, "%s: %s\n", tzObjectname, path);
}
return f;
}
}

View File

@@ -475,6 +475,7 @@ setuplex(void)
lex_FloatAddSecondRange(id, '\\', '\\');
lex_FloatAddSecondRange(id, '@', '@');
lex_FloatAddSecondRange(id, '#', '#');
lex_FloatAddRange(id, '.', '.');
lex_FloatAddRange(id, 'a', 'z');
lex_FloatAddRange(id, 'A', 'Z');
lex_FloatAddRange(id, '0', '9');

View File

@@ -535,7 +535,7 @@ yylex_ReadBracketedSymbol(char *dest, size_t index)
if (*pLexBuffer == '}')
pLexBuffer++;
else
yyerror("Missing }");
fatalerror("Missing }");
return length;
}
@@ -601,7 +601,7 @@ yylex_ReadQuotedString()
if (*pLexBuffer == '"')
pLexBuffer++;
else
yyerror("Unterminated string");
fatalerror("Unterminated string");
}
ULONG

View File

@@ -26,6 +26,9 @@ ULONG nTotalLines, nPass, nPC, nIFDepth, nErrors;
extern int yydebug;
FILE *dependfile;
extern char *tzObjectname;
/*
* Option stack
*/
@@ -274,7 +277,7 @@ usage(void)
{
printf(
"Usage: rgbasm [-hvE] [-b chars] [-Dname[=value]] [-g chars] [-i path]\n"
" [-o outfile] [-p pad_value] file.asm\n");
" [-M dependfile] [-o outfile] [-p pad_value] file.asm\n");
exit(1);
}
@@ -288,6 +291,8 @@ main(int argc, char *argv[])
char *tzMainfile;
dependfile = NULL;
cldefines_size = 32;
cldefines = reallocarray(cldefines, cldefines_size,
2 * sizeof(void *));
@@ -317,7 +322,7 @@ main(int argc, char *argv[])
newopt = CurrentOptions;
while ((ch = getopt(argc, argv, "b:D:g:hi:o:p:vEw")) != -1) {
while ((ch = getopt(argc, argv, "b:D:g:hi:M:o:p:vEw")) != -1) {
switch (ch) {
case 'b':
if (strlen(optarg) == 2) {
@@ -348,6 +353,11 @@ main(int argc, char *argv[])
case 'i':
fstk_AddIncludePath(optarg);
break;
case 'M':
if ((dependfile = fopen(optarg, "w")) == NULL) {
err(1, "Could not open dependfile %s", optarg);
}
break;
case 'o':
out_SetFileName(optarg);
break;
@@ -392,6 +402,13 @@ main(int argc, char *argv[])
printf("Assembling %s\n", tzMainfile);
}
if (dependfile) {
if (!tzObjectname)
errx(1, "Dependency files can only be created if an output object file is specified.\n");
fprintf(dependfile, "%s: %s\n", tzObjectname, tzMainfile);
}
nStartClock = clock();
nLineNo = 1;

View File

@@ -17,8 +17,6 @@
#include "asm/fstack.h"
#include "extern/err.h"
#define SECTIONCHUNK 0x4000
void out_SetCurrentSection(struct Section * pSect);
struct Patch {
@@ -80,6 +78,24 @@ out_PopSection(void)
fatalerror("No entries in the section stack");
}
ULONG
getmaxsectionsize(ULONG secttype, char * sectname)
{
switch (secttype)
{
case SECT_ROM0: return 0x8000; /* If ROMX sections not used. */
case SECT_ROMX: return 0x4000;
case SECT_VRAM: return 0x2000;
case SECT_SRAM: return 0x2000;
case SECT_WRAM0: return 0x2000; /* If WRAMX sections not used. */
case SECT_WRAMX: return 0x1000;
case SECT_OAM: return 0xA0;
case SECT_HRAM: return 0x7F;
default: break;
}
errx(1, "Section \"%s\" has an invalid section type.", sectname);
}
/*
* Count the number of symbols used in this object
*/
@@ -244,11 +260,7 @@ writesymbol(struct sSymbol * pSym, FILE * f)
sectid = -1;
type = SYM_IMPORT;
} else {
if (pSym->nType & SYMF_LOCAL) {
strcpy(symname, pSym->pScope->tzName);
strcat(symname, pSym->tzName);
} else
strcpy(symname, pSym->tzName);
strcpy(symname, pSym->tzName);
if (pSym->nType & SYMF_EXPORT) {
/* Symbol should be exported */
@@ -441,38 +453,36 @@ checksection(void)
* this much initialized data
*/
void
checkcodesection(SLONG size)
checkcodesection(void)
{
checksection();
if (pCurrentSection->nType != SECT_ROM0 &&
pCurrentSection->nType != SECT_ROMX) {
errx(1, "Section '%s' cannot contain code or data (not a "
"ROM0 or ROMX)", pCurrentSection->pzName);
fatalerror("Section '%s' cannot contain code or data (not ROM0 or ROMX)",
pCurrentSection->pzName);
}
if (pCurrentSection->nPC + size > MAXSECTIONSIZE) {
/*
* N.B.: This check is not sufficient to ensure the section
* will fit, because there can be multiple sections of this
* type. The definitive check must be done at the linking
* stage.
*/
errx(1, "Section '%s' is too big (old size %d + %d > %d)",
pCurrentSection->pzName, pCurrentSection->nPC, size,
MAXSECTIONSIZE);
}
if (((pCurrentSection->nPC % SECTIONCHUNK) >
((pCurrentSection->nPC + size) % SECTIONCHUNK)) &&
(pCurrentSection->nType == SECT_ROM0 ||
pCurrentSection->nType == SECT_ROMX)) {
pCurrentSection->tData = realloc(pCurrentSection->tData,
((pCurrentSection->nPC + size) / SECTIONCHUNK + 1) *
SECTIONCHUNK);
}
if (pCurrentSection->tData == NULL) {
err(1, "Could not expand section");
}
/*
* Check if the section has grown too much.
*/
void
checksectionoverflow(ULONG delta_size)
{
ULONG maxsize = getmaxsectionsize(pCurrentSection->nType,
pCurrentSection->pzName);
if (pCurrentSection->nPC + delta_size > maxsize) {
/*
* This check is here to trap broken code that generates
* sections that are too big and to prevent the assembler from
* generating huge object files or trying to allocate too much
* memory.
* The real check must be done at the linking stage.
*/
fatalerror("Section '%s' is too big (max size = 0x%X bytes).",
pCurrentSection->pzName, maxsize);
}
return;
}
/*
@@ -580,10 +590,15 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG align
pSect->charmap = NULL;
pPatchSymbols = NULL;
if ((pSect->tData = malloc(SECTIONCHUNK)) != NULL) {
return (pSect);
} else
fatalerror("Not enough memory for section");
pSect->tData = NULL;
if (secttype == SECT_ROM0 || secttype == SECT_ROMX) {
/* It is only needed to allocate memory for ROM
* sections. */
ULONG sectsize = getmaxsectionsize(secttype, pzName);
if ((pSect->tData = malloc(sectsize)) == NULL)
fatalerror("Not enough memory for section");
}
return (pSect);
} else
fatalerror("Not enough memory for sectionname");
} else
@@ -641,7 +656,8 @@ out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank)
void
out_AbsByte(int b)
{
checkcodesection(1);
checkcodesection();
checksectionoverflow(1);
b &= 0xFF;
if (nPass == 2)
pCurrentSection->tData[nPC] = b;
@@ -654,7 +670,8 @@ out_AbsByte(int b)
void
out_AbsByteGroup(char *s, int length)
{
checkcodesection(length);
checkcodesection();
checksectionoverflow(length);
while (length--)
out_AbsByte(*s++);
}
@@ -666,13 +683,14 @@ void
out_Skip(int skip)
{
checksection();
checksectionoverflow(skip);
if (!((pCurrentSection->nType == SECT_ROM0)
|| (pCurrentSection->nType == SECT_ROMX))) {
pCurrentSection->nPC += skip;
nPC += skip;
pPCSymbol->nValue += skip;
} else {
checkcodesection(skip);
checkcodesection();
while (skip--)
out_AbsByte(CurrentOptions.fillchar);
}
@@ -684,7 +702,8 @@ out_Skip(int skip)
void
out_String(char *s)
{
checkcodesection(strlen(s));
checkcodesection();
checksectionoverflow(strlen(s));
while (*s)
out_AbsByte(*s++);
}
@@ -697,7 +716,8 @@ out_String(char *s)
void
out_RelByte(struct Expression * expr)
{
checkcodesection(1);
checkcodesection();
checksectionoverflow(1);
if (rpn_isReloc(expr)) {
if (nPass == 2) {
pCurrentSection->tData[nPC] = 0;
@@ -718,7 +738,8 @@ out_RelByte(struct Expression * expr)
void
out_AbsWord(int b)
{
checkcodesection(2);
checkcodesection();
checksectionoverflow(2);
b &= 0xFFFF;
if (nPass == 2) {
pCurrentSection->tData[nPC] = b & 0xFF;
@@ -738,7 +759,8 @@ out_RelWord(struct Expression * expr)
{
ULONG b;
checkcodesection(2);
checkcodesection();
checksectionoverflow(2);
b = expr->nVal & 0xFFFF;
if (rpn_isReloc(expr)) {
if (nPass == 2) {
@@ -760,7 +782,8 @@ out_RelWord(struct Expression * expr)
void
out_AbsLong(SLONG b)
{
checkcodesection(sizeof(SLONG));
checkcodesection();
checksectionoverflow(sizeof(SLONG));
if (nPass == 2) {
pCurrentSection->tData[nPC] = b & 0xFF;
pCurrentSection->tData[nPC + 1] = b >> 8;
@@ -781,7 +804,8 @@ out_RelLong(struct Expression * expr)
{
SLONG b;
checkcodesection(4);
checkcodesection();
checksectionoverflow(4);
b = expr->nVal;
if (rpn_isReloc(expr)) {
if (nPass == 2) {
@@ -807,7 +831,8 @@ out_PCRelByte(struct Expression * expr)
{
SLONG b = expr->nVal;
checkcodesection(1);
checkcodesection();
checksectionoverflow(1);
b = (b & 0xFFFF) - (nPC + 1);
if (nPass == 2 && (b < -128 || b > 127))
yyerror("PC-relative value must be 8-bit");
@@ -835,7 +860,8 @@ out_BinaryFile(char *s)
fsize = ftell(f);
fseek(f, 0, SEEK_SET);
checkcodesection(fsize);
checkcodesection();
checksectionoverflow(fsize);
if (nPass == 2) {
SLONG dest = nPC;
@@ -879,7 +905,8 @@ out_BinaryFileSlice(char *s, SLONG start_pos, SLONG length)
fseek(f, start_pos, SEEK_SET);
checkcodesection(length);
checkcodesection();
checksectionoverflow(length);
if (nPass == 2) {
SLONG dest = nPC;

View File

@@ -25,6 +25,7 @@
.Op Fl D Ar name Ns Op = Ns Ar value
.Op Fl g Ar chars
.Op Fl i Ar path
.Op Fl M Ar dependfile
.Op Fl o Ar outfile
.Op Fl p Ar pad_value
.Ar file
@@ -61,6 +62,11 @@ The
option disables this behavior.
.It Fl i Ar path
Add an include path.
.It Fl M Ar dependfile
Print
.Xr make 1
dependencies to
.Ar dependfile .
.It Fl o Ar outfile
Write an object file to the given filename.
.It Fl p Ar pad_value
@@ -88,10 +94,9 @@ and
.Xr rgbds 5 ,
.Xr rgbds 7 ,
.Xr gbz80 7
.Pp
.Lk https://rednex.github.io/rgbds/asm.htm rgbasm assembly commands
.Sh HISTORY
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
number of contributors at https://github.com/rednex/rgbds.
number of contributors at
.Lk https://github.com/rednex/rgbds .

View File

@@ -223,13 +223,17 @@ GlobalLabel
AnotherGlobal:
\&.locallabel
\&.yet_a_local:
AnotherGlobal.with_another_local:
ThisWillBeExported:: ;note the two colons
ThisWillBeExported.too::
.Ed
.Pp
In the line where a label is defined there musn't be any whitespace before it.
Local labels are only accessible within the scope they are defined.
A scope starts after a global label and ends at the next global label.
Declaring a normal label with :: does an EXPORT at the same time.
Declaring a label (global or local) with :: does an EXPORT at the same time.
Local labels can be declared as scope.local or simply as as .local.
If the former notation is used, the scope must be the actual current scope.
.Pp
Labels will normally change their value during the link process and are thus not
constant.
@@ -303,6 +307,8 @@ There are four commands in the RS group of commands:
.Ic _RS No and adds Ar constexpr No to Ic _RS .
.It Ic RW Ar constexpr Ta Sets the preceding symbol to
.Ic _RS No and adds Ar constexpr No * 2 to Ic _RS.
.It Ic RL Ar constexpr Ta Sets the preceding symbol to
.Ic _RS No and adds Ar constexpr No * 4 to Ic _RS.
.El
.Pp
Note that a colon (:) following the symbol-name is not allowed.
@@ -340,6 +346,14 @@ String-symbols can also be used to define small one-line macros:
Note that a colon (:) following the label-name is not allowed.
String equates can't be exported or imported.
.Pp
.Sy Important note :
An EQUS can be expanded to a string that contains another EQUS
and it will be expanded as well.
This means that, if you aren't careful, you may trap the assembler into an
infinite loop if there's a circular dependency in the expansions.
Also, a MACRO can have inside an EQUS which references the same MACRO, which has
the same problem.
.Pp
.It Sy MACRO
.Pp
One of the best features of an assembler is the ability to write macros for it.
@@ -401,6 +415,14 @@ LoopyMacro: MACRO
ENDM
.Ed
.Pp
.Sy Important note :
Since a MACRO can call itself (or a different MACRO that calls the first one)
there can be problems of circular dependency.
They trap the assembler in an infinite loop, so you have to be careful when
using recursion with MACROs.
Also, a MACRO can have inside an EQUS which references the same MACRO, which has
the same problem.
.Pp
.Sy Macro Arguments
.Pp
I'd like LoopyMacro a lot better if I didn't have to pre-load the registers
@@ -521,6 +543,12 @@ The following symbols are defined by the assembler:
.It Ic EQUS Ta Ic __TIME__ Ta Ta The current time
.It Ic EQUS Ta Ic __ISO_8601_LOCAL__ Ta ISO 8601 timestamp (local)
.It Ic EQUS Ta Ic __ISO_8601_UTC__ Ta ISO 8601 timestamp (UTC)
.It Ic EQU Ta Ic __UTC_YEAR__ Ta Ta Today's year
.It Ic EQU Ta Ic __UTC_MONTH__ Ta Ta Today's month number, 1-12
.It Ic EQU Ta Ic __UTC_DAY__ Ta Ta Today's day of the month, 1-31
.It Ic EQU Ta Ic __UTC_HOUR__ Ta Ta Current hour, 0-23
.It Ic EQU Ta Ic __UTC_MINUTE__ Ta Ta Current minute, 0-59
.It Ic EQU Ta Ic __UTC_SECOND__ Ta Ta Current second, 0-59
.El
.Pp
.Sh DEFINING DATA
@@ -970,6 +998,7 @@ machine.
.It Sx PUSHS
.It Sx REPT
.It Sx RB
.It Sx RL
.It Sx ROM0
.It Sx ROMX
.It Sx RSRESET
@@ -1005,4 +1034,4 @@ machine.
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd.
It is now maintained by a number of contributors at
https://github.com/rednex/rgbds.
.Lk https://github.com/rednex/rgbds .

View File

@@ -24,8 +24,29 @@ char SavedTIME[256];
char SavedDATE[256];
char SavedTIMESTAMP_ISO8601_LOCAL[256];
char SavedTIMESTAMP_ISO8601_UTC[256];
char SavedDAY[3];
char SavedMONTH[3];
char SavedYEAR[5];
char SavedHOUR[3];
char SavedMINUTE[3];
char SavedSECOND[3];
bool exportall;
void helper_RemoveLeadingZeros(char * string){
char * new_beginning = string;
while(*new_beginning == '0')
new_beginning++;
if(new_beginning == string)
return;
if(*new_beginning == '\0')
new_beginning--;
memmove(string, new_beginning, strlen(new_beginning) + 1);
}
SLONG
Callback_NARG(struct sSymbol * sym)
{
@@ -93,26 +114,16 @@ createsymbol(char *s)
return (NULL);
}
}
/*
* Find a symbol by name and scope
* Creates the full name of a local symbol in a given scope, by prepending
* the name with the parent symbol's name.
*/
struct sSymbol *
findsymbol(char *s, struct sSymbol * scope)
size_t
fullSymbolName(char *output, size_t outputSize, char *localName, struct sSymbol *scope)
{
struct sSymbol **ppsym;
SLONG hash;
hash = calchash(s);
ppsym = &(tHashedSymbols[hash]);
while ((*ppsym) != NULL) {
if ((strcmp(s, (*ppsym)->tzName) == 0)
&& ((*ppsym)->pScope == scope)) {
return (*ppsym);
} else
ppsym = &((*ppsym)->pNext);
}
return (NULL);
struct sSymbol *parent = scope->pScope ? scope->pScope : scope;
return snprintf(output, outputSize, "%s%s", parent->tzName, localName);
}
/*
@@ -123,13 +134,25 @@ findpsymbol(char *s, struct sSymbol * scope)
{
struct sSymbol **ppsym;
SLONG hash;
char fullname[MAXSYMLEN + 1];
if (s[0] == '.' && scope) {
fullSymbolName(fullname, sizeof(fullname), s, scope);
s = fullname;
}
char *seperator;
if ((seperator = strchr(s, '.'))) {
if (strchr(seperator + 1, '.')) {
fatalerror("'%s' is a nonsensical reference to a nested local symbol", s);
}
}
hash = calchash(s);
ppsym = &(tHashedSymbols[hash]);
while ((*ppsym) != NULL) {
if ((strcmp(s, (*ppsym)->tzName) == 0)
&& ((*ppsym)->pScope == scope)) {
if ((strcmp(s, (*ppsym)->tzName) == 0)) {
return (ppsym);
} else
ppsym = &((*ppsym)->pNext);
@@ -137,6 +160,16 @@ findpsymbol(char *s, struct sSymbol * scope)
return (NULL);
}
/*
* Find a symbol by name and scope
*/
struct sSymbol *
findsymbol(char *s, struct sSymbol * scope)
{
struct sSymbol **ppsym = findpsymbol(s, scope);
return ppsym ? *ppsym : NULL;
}
/*
* Find a symbol by name and scope
*/
@@ -572,31 +605,17 @@ sym_AddSet(char *tzSym, SLONG value)
void
sym_AddLocalReloc(char *tzSym)
{
if ((nPass == 1)
|| ((nPass == 2) && (sym_isDefined(tzSym) == 0))) {
/* only add local reloc symbols in pass 1 */
struct sSymbol *nsym;
if (pScope) {
if (strlen(tzSym) + strlen(pScope->tzName) > MAXSYMLEN) {
fatalerror("Symbol too long");
}
if (pScope) {
if ((nsym = findsymbol(tzSym, pScope)) != NULL) {
if (nsym->nType & SYMF_DEFINED) {
yyerror("'%s' already defined", tzSym);
}
} else
nsym = createsymbol(tzSym);
char fullname[MAXSYMLEN + 1];
fullSymbolName(fullname, sizeof(fullname), tzSym, pScope);
sym_AddReloc(fullname);
if (nsym) {
nsym->nValue = nPC;
nsym->nType |=
SYMF_RELOC | SYMF_LOCAL | SYMF_DEFINED;
if (exportall) {
nsym->nType |= SYMF_EXPORT;
}
nsym->pScope = pScope;
nsym->pSection = pCurrentSection;
}
} else
fatalerror("Local label in main scope");
} else {
fatalerror("Local label in main scope");
}
}
@@ -606,12 +625,32 @@ sym_AddLocalReloc(char *tzSym)
void
sym_AddReloc(char *tzSym)
{
struct sSymbol* scope = NULL;
if ((nPass == 1)
|| ((nPass == 2) && (sym_isDefined(tzSym) == 0))) {
/* only add reloc symbols in pass 1 */
struct sSymbol *nsym;
char *localPtr = NULL;
if ((nsym = findsymbol(tzSym, NULL)) != NULL) {
if ((localPtr = strchr(tzSym, '.')) != NULL) {
if (!pScope) {
fatalerror("Local label in main scope");
}
struct sSymbol *parent = pScope->pScope ? pScope->pScope : pScope;
int parentLen = localPtr - tzSym;
if (strchr(localPtr + 1, '.') != NULL) {
fatalerror("'%s' is a nonsensical reference to a nested local symbol", tzSym);
} else if (strlen(parent->tzName) != parentLen || strncmp(tzSym, parent->tzName, parentLen) != 0) {
yyerror("Not currently in the scope of '%.*s'", parentLen, tzSym);
}
scope = parent;
}
if ((nsym = findsymbol(tzSym, scope)) != NULL) {
if (nsym->nType & SYMF_DEFINED) {
yyerror("'%s' already defined", tzSym);
}
@@ -621,14 +660,17 @@ sym_AddReloc(char *tzSym)
if (nsym) {
nsym->nValue = nPC;
nsym->nType |= SYMF_RELOC | SYMF_DEFINED;
if (localPtr) {
nsym->nType |= SYMF_LOCAL;
}
if (exportall) {
nsym->nType |= SYMF_EXPORT;
}
nsym->pScope = NULL;
nsym->pScope = scope;
nsym->pSection = pCurrentSection;
}
}
pScope = findsymbol(tzSym, NULL);
pScope = findsymbol(tzSym, scope);
}
/*
@@ -684,7 +726,7 @@ sym_Export(char *tzSym)
/* only export symbols in pass 1 */
struct sSymbol *nsym;
if ((nsym = findsymbol(tzSym, 0)) == NULL)
if ((nsym = sym_FindSymbol(tzSym)) == NULL)
nsym = createsymbol(tzSym);
if (nsym)
@@ -692,7 +734,7 @@ sym_Export(char *tzSym)
} else {
struct sSymbol *nsym;
if ((nsym = findsymbol(tzSym, 0)) != NULL) {
if ((nsym = sym_FindSymbol(tzSym)) != NULL) {
if (nsym->nType & SYMF_DEFINED)
return;
}
@@ -711,7 +753,7 @@ sym_Global(char *tzSym)
/* only globalize symbols in pass 2 */
struct sSymbol *nsym;
nsym = findsymbol(tzSym, 0);
nsym = sym_FindSymbol(tzSym);
if ((nsym == NULL) || ((nsym->nType & SYMF_DEFINED) == 0)) {
if (nsym == NULL)
@@ -800,6 +842,12 @@ sym_PrepPass2(void)
sym_AddString("__DATE__", SavedDATE);
sym_AddString("__ISO_8601_LOCAL__", SavedTIMESTAMP_ISO8601_LOCAL);
sym_AddString("__ISO_8601_UTC__", SavedTIMESTAMP_ISO8601_UTC);
sym_AddString("__UTC_DAY__", SavedDAY);
sym_AddString("__UTC_MONTH__", SavedMONTH);
sym_AddString("__UTC_YEAR__", SavedYEAR);
sym_AddString("__UTC_HOUR__", SavedHOUR);
sym_AddString("__UTC_MINUTE__", SavedMINUTE);
sym_AddString("__UTC_SECOND__", SavedSECOND);
sym_AddSet("_RS", 0);
sym_AddEqu("_NARG", 0);
@@ -845,6 +893,19 @@ sym_Init(void)
struct tm *time_utc = gmtime(&now);
strftime(SavedTIMESTAMP_ISO8601_UTC,
sizeof(SavedTIMESTAMP_ISO8601_UTC), "\"%FT%TZ\"", time_utc);
strftime(SavedDAY, sizeof(SavedDAY), "%d", time_utc);
strftime(SavedMONTH, sizeof(SavedMONTH), "%m", time_utc);
strftime(SavedYEAR, sizeof(SavedYEAR), "%Y", time_utc);
strftime(SavedHOUR, sizeof(SavedHOUR), "%H", time_utc);
strftime(SavedMINUTE, sizeof(SavedMINUTE), "%M", time_utc);
strftime(SavedSECOND, sizeof(SavedSECOND), "%S", time_utc);
helper_RemoveLeadingZeros(SavedDAY);
helper_RemoveLeadingZeros(SavedMONTH);
helper_RemoveLeadingZeros(SavedHOUR);
helper_RemoveLeadingZeros(SavedMINUTE);
helper_RemoveLeadingZeros(SavedSECOND);
} else {
warnx("Couldn't determine current time.");
/* The '?' have to be escaped or they will be treated as
@@ -853,12 +914,24 @@ sym_Init(void)
strcpy(SavedDATE, "\"\?\? \?\?\? \?\?\?\?\"");
strcpy(SavedTIMESTAMP_ISO8601_LOCAL, "\"\?\?\?\?-\?\?-\?\?T\?\?:\?\?:\?\?+\?\?\?\?\"");
strcpy(SavedTIMESTAMP_ISO8601_UTC, "\"\?\?\?\?-\?\?-\?\?T\?\?:\?\?:\?\?Z\"");
strcpy(SavedDAY, "1");
strcpy(SavedMONTH, "1");
strcpy(SavedYEAR, "1900");
strcpy(SavedHOUR, "0");
strcpy(SavedMINUTE, "0");
strcpy(SavedSECOND, "0");
}
sym_AddString("__TIME__", SavedTIME);
sym_AddString("__DATE__", SavedDATE);
sym_AddString("__ISO_8601_LOCAL__", SavedTIMESTAMP_ISO8601_LOCAL);
sym_AddString("__ISO_8601_UTC__", SavedTIMESTAMP_ISO8601_UTC);
sym_AddString("__UTC_DAY__", SavedDAY);
sym_AddString("__UTC_MONTH__", SavedMONTH);
sym_AddString("__UTC_YEAR__", SavedYEAR);
sym_AddString("__UTC_HOUR__", SavedHOUR);
sym_AddString("__UTC_MINUTE__", SavedMINUTE);
sym_AddString("__UTC_SECOND__", SavedSECOND);
pScope = NULL;

View File

@@ -12,7 +12,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 16, 2017
.Dd April 17, 2017
.Dt RGBFIX 1
.Os RGBDS Manual
.Sh NAME
@@ -153,4 +153,5 @@ SurvivalKids.gbc
.Nm
was originally released by Carsten S\(/orensen as a standalone program called
gbfix, and was later packaged in RGBDS by Justin Lloyd. It is now maintained by
a number of contributors at https://github.com/rednex/rgbds.
a number of contributors at
.Lk https://github.com/rednex/rgbds .

View File

@@ -12,7 +12,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 16, 2017
.Dd April 17, 2017
.Dt GBZ80 7
.Os RGBDS Manual
.Sh NAME
@@ -1821,4 +1821,4 @@ Flags: See
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd.
It is now maintained by a number of contributors at
https://github.com/rednex/rgbds.
.Lk https://github.com/rednex/rgbds .

View File

@@ -12,7 +12,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd April 8, 2017
.Dd April 17, 2017
.Dt RGBGFX 1
.Os RGBDS Manual
.Sh NAME
@@ -103,4 +103,4 @@ was created by
.An stag019
to be included in RGBDS.
It is now maintained by a number of contributors at
https://github.com/rednex/rgbds.
.Lk https://github.com/rednex/rgbds .

View File

@@ -160,15 +160,51 @@ obj_ReadRGBSection(FILE * f)
errx(1, "ROMX sections can't be used with option -t.");
}
if ((options & OPT_CONTWRAM) && (pSection->Type == SECT_WRAMX)) {
errx(1, "WRAMX sections can't be used with option -w.");
errx(1, "WRAMX sections can't be used with options -w or -d.");
}
if (options & OPT_DMG_MODE) {
/* WRAMX sections are checked for OPT_CONTWRAM */
if (pSection->Type == SECT_VRAM && pSection->nBank == 1) {
errx(1, "VRAM bank 1 can't be used with option -w.");
errx(1, "VRAM bank 1 can't be used with option -d.");
}
}
unsigned int maxsize = 0;
/* Verify that the section isn't too big */
switch (pSection->Type)
{
case SECT_ROM0:
maxsize = (options & OPT_TINY) ? 0x8000 : 0x4000;
break;
case SECT_ROMX:
maxsize = 0x4000;
break;
case SECT_VRAM:
case SECT_SRAM:
maxsize = 0x2000;
break;
case SECT_WRAM0:
maxsize = (options & OPT_CONTWRAM) ? 0x2000 : 0x1000;
break;
case SECT_WRAMX:
maxsize = 0x1000;
break;
case SECT_OAM:
maxsize = 0xA0;
break;
case SECT_HRAM:
maxsize = 0x7F;
break;
default:
errx(1, "Section \"%s\" has an invalid section type.", pzName);
break;
}
if (pSection->nByteSize > maxsize) {
errx(1, "Section \"%s\" is bigger than the max size for that type: 0x%X > 0x%X",
pzName, pSection->nByteSize, maxsize);
}
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
/*
* These sectiontypes contain data...
@@ -339,24 +375,3 @@ file_Length(FILE * f)
return (r);
}
void
lib_ReadXLB0(FILE * f)
{
SLONG size;
size = file_Length(f) - 4;
while (size) {
char *name;
size -= readasciiz(&name, f);
readword(f);
size -= 2;
readword(f);
size -= 2;
size -= readlong(f);
size -= 4;
obj_ReadOpenFile(f, name);
free(name);
}
}

View File

@@ -119,4 +119,5 @@ to fix these so that the program will actually run in a Game Boy:
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
number of contributors at https://github.com/rednex/rgbds.
number of contributors at
.Lk https://github.com/rednex/rgbds .

View File

@@ -98,4 +98,5 @@ linkerscript. The address and alignment musn't be set.
.Nm
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd. It is now maintained by a
number of contributors at https://github.com/rednex/rgbds.
number of contributors at
.Lk https://github.com/rednex/rgbds .

View File

@@ -187,4 +187,4 @@ Symbol ID follows.
was originally written by Carsten S\(/orensen as part of the ASMotor package,
and was later packaged in RGBDS by Justin Lloyd.
It is now maintained by a number of contributors at
https://github.com/rednex/rgbds.
.Lk https://github.com/rednex/rgbds .

View File

@@ -47,5 +47,5 @@ implementation of rgbds.
.It
2017, Bentley's repository is moved to a neutral name.
It is now maintained by a number of contributors at
https://github.com/rednex/rgbds
.Lk https://github.com/rednex/rgbds .
.El

View File

@@ -0,0 +1,6 @@
SECTION "sec", ROM0
Parent:
db 0
WrongParent.child
db 0

View File

@@ -0,0 +1,3 @@
ERROR: local-wrong-parent.asm(5):
Not currently in the scope of 'WrongParent'
error: Assembly aborted in pass 1 (1 errors)!

View File

@@ -0,0 +1,7 @@
SECTION "sec", ROM0
Parent:
Parent.child::
db 0
NotParent:
dw Parent.child

View File

View File

@@ -0,0 +1,7 @@
SECTION "sec", ROM0
Parent:
.child:
db 0
NotParent:
dw Parent.child.fail

View File

@@ -0,0 +1,2 @@
ERROR: remote-local-noexist.asm(7):
'Parent.child.fail' is a nonsensical reference to a nested local symbol

View File

@@ -0,0 +1,7 @@
SECTION "sec", ROM0
Parent:
.child:
db 0
NotParent:
dw Parent.child

View File

View File

@@ -1 +1 @@
error: VRAM bank 1 can't be used with option -w.
error: VRAM bank 1 can't be used with option -d.

View File

@@ -1 +1 @@
error: WRAMX sections can't be used with option -w.
error: WRAMX sections can't be used with options -w or -d.