diff --git a/docs/gbz80.7.html b/docs/gbz80.7.html
index 15af5770..f1ed7bf5 100644
--- a/docs/gbz80.7.html
+++ b/docs/gbz80.7.html
@@ -34,8 +34,12 @@ Note: All arithmetic/logic operations that use register
is assumed it's register A. The following two
lines have the same effect:
@@ -1689,7 +1693,7 @@ Flags: See XOR A,r8
https://github.com/rednex/rgbds.
diff --git a/docs/rgbasm.5.html b/docs/rgbasm.5.html
index f805d97b..c8ee1a1d 100644
--- a/docs/rgbasm.5.html
+++ b/docs/rgbasm.5.html
@@ -38,7 +38,11 @@ The syntax is line‐based, just as in any other assembler, meaning that
Example:
-John: ld a,87 ;Weee
+
+
+John: ld a,87 ;Weee
+
+
All pseudo‐ops, mnemonics and registers (reserved keywords) are
case‐insensitive and all labels are case‐sensitive.
@@ -47,13 +51,40 @@ There are two syntaxes for comments. In both cases, a comment ends at the end of
the line. The most common one is: anything that follows a semicolon
";" (that isn't inside a string) is a comment. There is another
format: anything that follows a "*" that is placed right at the
- start of a line is a comment.
+ start of a line is a comment. The assembler removes all comments from the code
+ before doing anything else.
+
+Sometimes lines can be too long and it may be necessary to split them. The
+ syntax to do so is the following one:
+
+
+
+ DB 1, 2, 3, 4 \
+ 5, 6, 7, 8
+
+
+
+This works anywhere in the code except inside of strings. To split strings it is
+ needed to use
+
+like this:
+
+
+
+ DB STRCAT("Hello ", \
+ "world!")
+
+
Before you can start writing code, you must define a section. This tells the
assembler what kind of information follows and, if it is code, where to put
it.
-SECTION "CoolStuff",ROMX
+
+
+ SECTION "CoolStuff",ROMX
+
+
This switches to the section called "CoolStuff" (or creates it if it
doesn't already exist) and it defines it as a code section. All sections
@@ -139,25 +170,38 @@ If a section is defined with no indications, it is a floating section. The
obligation to follow any specific rules. The following example defines a
section that can be placed anywhere in any ROMX bank:
-SECTION "CoolStuff",ROMX
+
+
+ SECTION "CoolStuff",ROMX
+
+
If it is needed, the following syntax can be used to fix the base address of the
section:
-SECTION
- "CoolStuff",ROMX[$4567]
+
+
+ SECTION "CoolStuff",ROMX[$4567]
+
+
It won't, however, fix the bank number, which is left to the linker. If you also
want to specify the bank you can do:
-SECTION
- "CoolStuff",ROMX[$4567],BANK[3]
+
+
+ SECTION "CoolStuff",ROMX[$4567],BANK[3]
+
+
And if you only want to force the section into a certain bank, and not it's
position within the bank, that's also possible:
-SECTION
- "CoolStuff",ROMX,BANK[7]
+
+
+ SECTION "CoolStuff",ROMX,BANK[7]
+
+
In addition, you can specify byte alignment for a section. This ensures that the
section starts at a memory address where the given number of least-significant
@@ -167,11 +211,13 @@ In addition, you can specify byte alignment for a section. This ensures that the
needed to align the start of an array to 256 bytes to optimize the code that
accesses it.
-SECTION "OAM Data",WRAM0,ALIGN[8];
- align to 256 bytes
-
-SECTION "VRAM
- Data",ROMX,BANK[2],ALIGN[4]; align to 16 bytes
+
+
+ SECTION "OAM Data",WRAM0,ALIGN[8] ; align to 256 bytes
+
+ SECTION "VRAM Data",ROMX,BANK[2],ALIGN[4] ; align to 16 bytes
+
+
HINT: If you think this is a lot of typing for doing a simple
ORG type thing you can quite easily write an
@@ -260,8 +306,12 @@ ThisWillBeExported.too::
EQUates are constant symbols. They can, for example, be used for things such
as bit-definitions of hardware registers.
- EXIT_OK EQU $00
- EXIT_FAILURE EQU $01
+
+
+EXIT_OK EQU $00
+EXIT_FAILURE EQU $01
+
+
Note that a colon (:) following the label-name is not allowed. EQUates
cannot be exported and imported. They don't change their value during the
@@ -285,7 +335,11 @@ COUNT SET ARRAY_SIZE+COUNT
be exported and imported. Alternatively you can use = as a synonym for
SET.
- COUNT = 2
+
- RSSET,
RSRESET, RB,
@@ -378,10 +432,10 @@ str_SIZEOF = 259
COUNTREG EQUS "[hl+]"
-ld a,COUNTREG
+ ld a,COUNTREG
PLAYER_NAME EQUS "\"John\""
-db PLAYER_NAME
+ db PLAYER_NAME
@@ -390,13 +444,20 @@ db PLAYER_NAME
This will be interpreted as:
- ld a,[hl+]
- db "John"
+
+
+ ld a,[hl+]
+ db "John"
+
+
String-symbols can also be used to define small one-line macros:
- PUSHA EQUS "push af\npush bc\npush
- de\npush hl\n"
+
+
+PUSHA EQUS "push af\npush bc\npush de\npush hl\n"
+
+
Note that a colon (:) following the label-name is not allowed. String
equates can't be exported or imported.
@@ -510,7 +571,11 @@ LoopyMacro: MACRO
address and the second being a bytecount. The macro will then reset all
bytes in this range.
- LoopyMacro MyVars,54
+
+
+LoopyMacro MyVars,54
+
+
Arguments are passed as string equates. There's no need to enclose them in
quotes. An expression will not be evaluated first but passed directly.
@@ -525,6 +590,21 @@ LoopyMacro: MACRO
use the first 9 like this. If you want to use the rest, you need to use
the keyword SHIFT.
+ Line continuations work as usual inside macros or lists of arguments of
+ macros. Strings, however, are a bit trickier. The following example shows
+ how to use strings as arguments for a macro:
+
+
+
+PrintMacro : MACRO
+ PRINTT \1
+ENDM
+
+ PrintMacro STRCAT(\"Hello\"\, \
+ \" world\\n\")
+
+
+
SHIFT is a special command only available in
macros. Very useful in REPT-blocks. It will "shift" the
arguments by one "to the left". \1
@@ -710,8 +790,11 @@ The following symbols are defined by the assembler:
DB defines a list of bytes that will be stored in
the final image. Ideal for tables and text (which is not zero-terminated).
-DB 1,2,3,4,"This is a
- string"
+
+
+DB 1,2,3,4,"This is a string"
+
+
Alternatively, you can use DW to store a list of
words (16-bits) or DL to store a list of
@@ -738,8 +821,11 @@ You can also use DB,
DW and DL without
any arguments instead.
-DS str_SIZEOF ;allocate str_SIZEOF
- bytes
+
+
+DS str_SIZEOF ;allocate str_SIZEOF bytes
+
+
You probably have some graphics you'd like to include. Use
@@ -747,17 +833,23 @@ You probably have some graphics you'd like to include. Use
the file isn't found in the current directory, the include-path list passed to
the linker on the command line will be searched.
-INCBIN "titlepic.bin"
-INCBIN "sprites/hero.bin" ;
- UNIX
-INCBIN "sprites\\hero.bin" ;
- Windows
+
+
+INCBIN "titlepic.bin"
+INCBIN "sprites/hero.bin" ; UNIX
+INCBIN "sprites\\hero.bin" ; Windows
+
+
You can also include only part of a file with
INCBIN. The example below includes 256 bytes from
data.bin starting from byte 78.
-INCBIN "data.bin",78,256
+
+
+INCBIN "data.bin",78,256
+
+
Unions allow multiple memory allocations to share the same space in memory, like
unions in C. This allows you to easily reuse memory for different purposes,
@@ -872,7 +964,11 @@ Use INCLUDE to process another assembler-file and
INCLUDE calls infinitely (or until you run out of
memory, whichever comes first).
-INCLUDE "irq.inc"
+
+
+ INCLUDE "irq.inc"
+
+
The four commands IF,
@@ -929,7 +1025,11 @@ The last one, Gameboy graphics, is quite interesting and useful. The values are
actually pixel values and it converts the “chunky” data to
“planar” data as used in the Gameboy.
-DW `01012323
+
Admittedly, an expression with just a single number is quite boring. To spice
things up a bit there are a few operators you can use to perform calculations
@@ -1465,7 +1565,7 @@ The options that OPT can modify are currently: b,
https://github.com/rednex/rgbds.
diff --git a/src/asm/lexer.c b/src/asm/lexer.c
index 0c728784..8696b140 100644
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -638,6 +638,44 @@ scanagain:
}
}
+ /* Check for line continuation character */
+ if (*pLexBuffer == '\\') {
+
+ /*
+ * Look for line continuation character after a series of
+ * spaces. This is also useful for files that use Windows line
+ * endings: "\r\n" is replaced by " \n" before the lexer has the
+ * opportunity to see it.
+ */
+ if (pLexBuffer[1] == ' ') {
+ pLexBuffer += 2;
+ while (1) {
+ if (*pLexBuffer == ' ') {
+ pLexBuffer++;
+ } else if (*pLexBuffer == '\n') {
+ pLexBuffer++;
+ nLineNo += 1;
+ goto scanagain;
+ } else {
+ errx(1, "Expected a new line after the continuation character.");
+ }
+ }
+ }
+
+ /* Line continuation character */
+ if (pLexBuffer[1] == '\n') {
+ pLexBuffer += 2;
+ nLineNo += 1;
+ goto scanagain;
+ }
+
+ /*
+ * If there isn't a newline character or a space, ignore the
+ * character '\'. It will eventually be handled by other
+ * functions like PutMacroArg().
+ */
+ }
+
/*
* Try to match an identifier, macro argument (e.g. \1),
* or numeric literal.
@@ -725,6 +763,9 @@ static uint32_t yylex_MACROARGS(void)
case '\\':
ch = '\\';
break;
+ case '"':
+ ch = '\"';
+ break;
case ',':
ch = ',';
break;
@@ -734,6 +775,32 @@ static uint32_t yylex_MACROARGS(void)
case '}':
ch = '}';
break;
+ case ' ':
+ /*
+ * Look for line continuation character after a
+ * series of spaces. This is also useful for
+ * files that use Windows line endings: "\r\n"
+ * is replaced by " \n" before the lexer has the
+ * opportunity to see it.
+ */
+ while (1) {
+ if (*pLexBuffer == ' ') {
+ pLexBuffer++;
+ } else if (*pLexBuffer == '\n') {
+ pLexBuffer++;
+ nLineNo += 1;
+ ch = 0;
+ break;
+ } else {
+ errx(1, "Expected a new line after the continuation character.");
+ }
+ }
+ break;
+ case '\n':
+ /* Line continuation character */
+ nLineNo += 1;
+ ch = 0;
+ break;
default:
maxLength = MAXSTRLEN - index;
length = CopyMacroArg(&yylval.tzString[index],
diff --git a/src/asm/rgbasm.5 b/src/asm/rgbasm.5
index 8d7baeb2..d8be1701 100644
--- a/src/asm/rgbasm.5
+++ b/src/asm/rgbasm.5
@@ -5,7 +5,7 @@
.\"
.\" SPDX-License-Identifier: MIT
.\"
-.Dd February 24, 2018
+.Dd February 26, 2018
.Dt RGBASM 5
.Os RGBDS Manual
.Sh NAME
@@ -26,7 +26,9 @@ one instruction or pseudo‐op per line:
.Pp
Example:
.Pp
-.Dl John: ld a,87 ;Weee
+.Bd -literal -offset indent
+John: ld a,87 ;Weee
+.Ed
.Pp
All pseudo‐ops, mnemonics and registers (reserved keywords) are case‐insensitive
and all labels are case‐sensitive.
@@ -35,13 +37,35 @@ There are two syntaxes for comments. In both cases, a comment ends at the end of
the line. The most common one is: anything that follows a semicolon
\[dq]\&;\[dq] (that isn't inside a string) is a comment. There is another
format: anything that follows a \[dq]*\[dq] that is placed right at the start of
-a line is a comment.
+a line is a comment. The assembler removes all comments from the code before
+doing anything else.
+.Pp
+Sometimes lines can be too long and it may be necessary to split them. The
+syntax to do so is the following one:
+.Pp
+.Bd -literal -offset indent
+ DB 1, 2, 3, 4 \[rs]
+ 5, 6, 7, 8
+.Ed
+.Pp
+This works anywhere in the code except inside of strings. To split strings it is
+needed to use
+.It STRCAT
+like this:
+.Pp
+.Bd -literal -offset indent
+ DB STRCAT("Hello ", \[rs]
+ "world!")
+.Ed
+.Pp
.Ss Sections
Before you can start writing code, you must define a section.
This tells the assembler what kind of information follows and, if it is code,
where to put it.
.Pp
-.Dl SECTION \[dq]CoolStuff\[dq],ROMX
+.Bd -literal -offset indent
+ SECTION \[dq]CoolStuff\[dq],ROMX
+.Ed
.Pp
This switches to the section called "CoolStuff" (or creates it if it doesn't
already exist) and it defines it as a code section.
@@ -128,22 +152,30 @@ obligation to follow any specific rules.
The following example defines a section that can be placed anywhere in any ROMX
bank:
.Pp
-.Dl SECTION \[dq]CoolStuff\[dq],ROMX
+.Bd -literal -offset indent
+ SECTION \[dq]CoolStuff\[dq],ROMX
+.Ed
.Pp
If it is needed, the following syntax can be used to fix the base address of the
section:
.Pp
-.Dl SECTION \[dq]CoolStuff\[dq],ROMX[$4567]
+.Bd -literal -offset indent
+ SECTION \[dq]CoolStuff\[dq],ROMX[$4567]
+.Ed
.Pp
It won't, however, fix the bank number, which is left to the linker.
If you also want to specify the bank you can do:
.Pp
-.Dl SECTION \[dq]CoolStuff\[dq],ROMX[$4567],BANK[3]
+.Bd -literal -offset indent
+ SECTION \[dq]CoolStuff\[dq],ROMX[$4567],BANK[3]
+.Ed
.Pp
And if you only want to force the section into a certain bank, and not it's
position within the bank, that's also possible:
.Pp
-.Dl SECTION \[dq]CoolStuff\[dq],ROMX,BANK[7]
+.Bd -literal -offset indent
+ SECTION \[dq]CoolStuff\[dq],ROMX,BANK[7]
+.Ed
.Pp
In addition, you can specify byte alignment for a section.
This ensures that the section starts at a memory address where the given number
@@ -155,9 +187,11 @@ However, if an alignment is specified, the base address must be left unassigned.
This can be useful when using DMA to copy data or when it is needed to align the
start of an array to 256 bytes to optimize the code that accesses it.
.Pp
-.Dl SECTION \[dq]OAM Data\[dq],WRAM0,ALIGN[8] ; align to 256 bytes
-.Pp
-.Dl SECTION \[dq]VRAM Data\[dq],ROMX,BANK[2],ALIGN[4] ; align to 16 bytes
+.Bd -literal -offset indent
+ SECTION \[dq]OAM Data\[dq],WRAM0,ALIGN[8] ; align to 256 bytes
+
+ SECTION \[dq]VRAM Data\[dq],ROMX,BANK[2],ALIGN[4] ; align to 16 bytes
+.Ed
.Pp
HINT: If you think this is a lot of typing for doing a simple
.Ic ORG
@@ -255,8 +289,10 @@ EQUates are constant symbols.
They can, for example, be used for things such as bit-definitions of hardware
registers.
.Pp
-.Dl EXIT_OK EQU $00
-.Dl EXIT_FAILURE EQU $01
+.Bd -literal -offset indent
+EXIT_OK EQU $00
+EXIT_FAILURE EQU $01
+.Ed
.Pp
Note that a colon (:) following the label-name is not allowed.
EQUates cannot be exported and imported.
@@ -278,7 +314,9 @@ Note that a colon (:) following the label-name is not allowed.
SETs cannot be exported and imported.
Alternatively you can use = as a synonym for SET.
.Pp
-.Dl COUNT = 2
+.Bd -literal -offset indent
+COUNT = 2
+.Ed
.Pp
.It Sy RSSET , RSRESET , RB , RW
.Pp
@@ -330,10 +368,10 @@ If you are familiar with C you can think of it as the same as #define.
.Pp
.Bd -literal -offset indent
COUNTREG EQUS "[hl+]"
-ld a,COUNTREG
+ ld a,COUNTREG
PLAYER_NAME EQUS \[dq]\[rs]\[dq]John\[rs]\[dq]\[dq]
-db PLAYER_NAME
+ db PLAYER_NAME
.Ed
.Pp
Note that : following the label-name is not allowed, and that strings must be
@@ -341,12 +379,16 @@ quoted to be useful.
.Pp
This will be interpreted as:
.Pp
-.Dl ld a,[hl+]
-.Dl db \[dq]John\[dq]
+.Bd -literal -offset indent
+ ld a,[hl+]
+ db \[dq]John\[dq]
+.Ed
.Pp
String-symbols can also be used to define small one-line macros:
.Pp
-.Dl PUSHA EQUS \[dq]push af\[rs]npush bc\[rs]npush de\[rs]npush hl\[rs]n\[dq]
+.Bd -literal -offset indent
+PUSHA EQUS \[dq]push af\[rs]npush bc\[rs]npush de\[rs]npush hl\[rs]n\[dq]
+.Ed
.Pp
Note that a colon (:) following the label-name is not allowed.
String equates can't be exported or imported.
@@ -459,7 +501,9 @@ Now I can call the macro specifying two arguments.
The first being the address and the second being a bytecount.
The macro will then reset all bytes in this range.
.Pp
-.Dl LoopyMacro MyVars,54
+.Bd -literal -offset indent
+LoopyMacro MyVars,54
+.Ed
.Pp
Arguments are passed as string equates.
There's no need to enclose them in quotes.
@@ -479,6 +523,19 @@ In reality, up to 256 arguments can be passed to a macro, but you can only use
the first 9 like this. If you want to use the rest, you need to use the keyword
.Ic SHIFT .
.Pp
+Line continuations work as usual inside macros or lists of arguments of macros.
+Strings, however, are a bit trickier. The following example shows how to use
+strings as arguments for a macro:
+.Pp
+.Bd -literal -offset indent
+PrintMacro : MACRO
+ PRINTT \[rs]1
+ENDM
+
+ PrintMacro STRCAT(\[rs]\[dq]Hello\[rs]\[dq]\[rs], \[rs]
+ \[rs]\[dq] world\[rs]\[rs]n\[rs]\[dq])
+.Ed
+.Pp
.Ic SHIFT
is a special command only available in macros.
Very useful in REPT-blocks.
@@ -565,7 +622,9 @@ The following symbols are defined by the assembler:
defines a list of bytes that will be stored in the final image.
Ideal for tables and text (which is not zero-terminated).
.Pp
-.Dl DB 1,2,3,4,\[dq]This is a string\[dq]
+.Bd -literal -offset indent
+DB 1,2,3,4,\[dq]This is a string\[dq]
+.Ed
.Pp
Alternatively, you can use
.Ic DW
@@ -609,7 +668,9 @@ and
.Ic DL
without any arguments instead.
.Pp
-.Dl DS str_SIZEOF ;allocate str_SIZEOF bytes
+.Bd -literal -offset indent
+DS str_SIZEOF ;allocate str_SIZEOF bytes
+.Ed
.Pp
.Ss Including binary files
You probably have some graphics you'd like to include.
@@ -619,15 +680,19 @@ to include a raw binary file as it is.
If the file isn't found in the current directory, the include-path list passed
to the linker on the command line will be searched.
.Pp
-.Dl INCBIN \[dq]titlepic.bin\[dq]
-.Dl INCBIN \[dq]sprites/hero.bin\[dq]\ ; UNIX
-.Dl INCBIN \[dq]sprites\[rs]\[rs]hero.bin\[dq]\ ; Windows
+.Bd -literal -offset indent
+INCBIN \[dq]titlepic.bin\[dq]
+INCBIN \[dq]sprites/hero.bin\[dq]\ ; UNIX
+INCBIN \[dq]sprites\[rs]\[rs]hero.bin\[dq]\ ; Windows
+.Ed
.Pp
You can also include only part of a file with
.Ic INCBIN .
The example below includes 256 bytes from data.bin starting from byte 78.
.Pp
-.Dl INCBIN \[dq]data.bin\[dq],78,256
+.Bd -literal -offset indent
+INCBIN \[dq]data.bin\[dq],78,256
+.Ed
.Ss Unions
Unions allow multiple memory allocations to share the same space in memory,
like unions in C.
@@ -755,7 +820,9 @@ You may nest
.Ic INCLUDE
calls infinitely (or until you run out of memory, whichever comes first).
.Pp
-.Dl INCLUDE \[dq]irq.inc\[dq]
+.Bd -literal -offset indent
+ INCLUDE \[dq]irq.inc\[dq]
+.Ed
.Pp
.Ss Conditional assembling
The four commands
@@ -831,7 +898,9 @@ The last one, Gameboy graphics, is quite interesting and useful.
The values are actually pixel values and it converts the
.Do chunky Dc data to Do planar Dc data as used in the Gameboy.
.Pp
-.Dl DW \`01012323
+.Bd -literal -offset indent
+ DW \`01012323
+.Ed
.Pp
Admittedly, an expression with just a single number is quite boring.
To spice things up a bit there are a few operators you can use to perform
diff --git a/src/gbz80.7 b/src/gbz80.7
index 0e186e5a..7de1a94e 100644
--- a/src/gbz80.7
+++ b/src/gbz80.7
@@ -5,7 +5,7 @@
.\"
.\" SPDX-License-Identifier: MIT
.\"
-.Dd January 26, 2018
+.Dd February 23, 2018
.Dt GBZ80 7
.Os RGBDS Manual
.Sh NAME
@@ -24,8 +24,10 @@ as destination can omit the destination as it is assumed it's register
.Sy A .
The following two lines have the same effect:
.Pp
-.Dl OR A,B
-.Dl OR B
+.Bd -literal -offset indent
+OR A,B
+OR B
+.Ed
.Pp
.Sh LEGEND
List of abbreviations used in this document.