fixup conio.c some more. also includes merge of upstream/master because git is retarded.

This commit is contained in:
mrdudz
2015-12-02 00:13:32 +01:00
7 changed files with 379 additions and 290 deletions

View File

@@ -2,8 +2,9 @@
<article> <article>
<title>ca65 Users Guide <title>ca65 Users Guide
<author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz"> <author><url url="mailto:uz@cc65.org" name="Ullrich von Bassewitz">,<newline>
<date>2015-08-01 <url url="mailto:greg.king5@verizon.net" name="Greg King">
<date>2015-11-17
<abstract> <abstract>
ca65 is a powerful macro assembler for the 6502, 65C02, and 65816 CPUs. It is ca65 is a powerful macro assembler for the 6502, 65C02, and 65816 CPUs. It is
@@ -3935,10 +3936,10 @@ In its simplest form, a macro does not have parameters. Here's an
example: example:
<tscreen><verb> <tscreen><verb>
.macro asr ; Arithmetic shift right .macro asr ; Arithmetic shift right
cmp #$80 ; Put bit 7 into carry cmp #$80 ; Put bit 7 into carry
ror ; Rotate right with carry ror ; Rotate right with carry
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
The macro above consists of two real instructions, that are inserted into The macro above consists of two real instructions, that are inserted into
@@ -3946,9 +3947,9 @@ the code, whenever the macro is expanded. Macro expansion is simply done
by using the name, like this: by using the name, like this:
<tscreen><verb> <tscreen><verb>
lda $2010 lda $2010
asr asr
sta $2010 sta $2010
</verb></tscreen> </verb></tscreen>
@@ -3957,15 +3958,15 @@ by using the name, like this:
When using macro parameters, macros can be even more useful: When using macro parameters, macros can be even more useful:
<tscreen><verb> <tscreen><verb>
.macro inc16 addr .macro inc16 addr
clc clc
lda addr lda addr
adc #$01 adc #<$0001
sta addr sta addr
lda addr+1 lda addr+1
adc #$00 adc #>$0001
sta addr+1 sta addr+1
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
When calling the macro, you may give a parameter, and each occurrence of When calling the macro, you may give a parameter, and each occurrence of
@@ -3973,19 +3974,19 @@ the name "addr" in the macro definition will be replaced by the given
parameter. So parameter. So
<tscreen><verb> <tscreen><verb>
inc16 $1000 inc16 $1000
</verb></tscreen> </verb></tscreen>
will be expanded to will be expanded to
<tscreen><verb> <tscreen><verb>
clc clc
lda $1000 lda $1000
adc #$01 adc #<$0001
sta $1000 sta $1000
lda $1000+1 lda $1000+1
adc #$00 adc #>$0001
sta $1000+1 sta $1000+1
</verb></tscreen> </verb></tscreen>
A macro may have more than one parameter, in this case, the parameters A macro may have more than one parameter, in this case, the parameters
@@ -4006,40 +4007,40 @@ opposite.
Look at this example: Look at this example:
<tscreen><verb> <tscreen><verb>
.macro ldaxy a, x, y .macro ldaxy a, x, y
.ifnblank a .ifnblank a
lda #a lda #a
.endif .endif
.ifnblank x .ifnblank x
ldx #x ldx #x
.endif .endif
.ifnblank y .ifnblank y
ldy #y ldy #y
.endif .endif
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
This macro may be called as follows: That macro may be called as follows:
<tscreen><verb> <tscreen><verb>
ldaxy 1, 2, 3 ; Load all three registers ldaxy 1, 2, 3 ; Load all three registers
ldaxy 1, , 3 ; Load only a and y ldaxy 1, , 3 ; Load only a and y
ldaxy , , 3 ; Load y only ldaxy , , 3 ; Load y only
</verb></tscreen> </verb></tscreen>
There's another helper command for determining, which macro parameters are There's another helper command for determining which macro parameters are
valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt> This command is valid: <tt><ref id=".PARAMCOUNT" name=".PARAMCOUNT"></tt>. That command is
replaced by the parameter count given, <em/including/ intermediate empty macro replaced by the parameter count given, <em/including/ explicitly empty
parameters: parameters:
<tscreen><verb> <tscreen><verb>
ldaxy 1 ; .PARAMCOUNT = 1 ldaxy 1 ; .PARAMCOUNT = 1
ldaxy 1,,3 ; .PARAMCOUNT = 3 ldaxy 1,,3 ; .PARAMCOUNT = 3
ldaxy 1,2 ; .PARAMCOUNT = 2 ldaxy 1,2 ; .PARAMCOUNT = 2
ldaxy 1, ; .PARAMCOUNT = 2 ldaxy 1, ; .PARAMCOUNT = 2
ldaxy 1,2,3 ; .PARAMCOUNT = 3 ldaxy 1,2,3 ; .PARAMCOUNT = 3
</verb></tscreen> </verb></tscreen>
Macro parameters may optionally be enclosed into curly braces. This allows the Macro parameters may optionally be enclosed into curly braces. This allows the
@@ -4047,19 +4048,19 @@ inclusion of tokens that would otherwise terminate the parameter (the comma in
case of a macro parameter). case of a macro parameter).
<tscreen><verb> <tscreen><verb>
.macro foo arg1, arg2 .macro foo arg1, arg2
... ...
.endmacro .endmacro
foo ($00,x) ; Two parameters passed foo ($00,x) ; Two parameters passed
foo {($00,x)} ; One parameter passed foo {($00,x)} ; One parameter passed
</verb></tscreen> </verb></tscreen>
In the first case, the macro is called with two parameters: '<tt/(&dollar;00/' In the first case, the macro is called with two parameters: '<tt/(&dollar;00/'
and 'x)'. The comma is not passed to the macro, since it is part of the and '<tt/x)/'. The comma is not passed to the macro, because it is part of the
calling sequence, not the parameters. calling sequence, not the parameters.
In the second case, '(&dollar;00,x)' is passed to the macro, this time In the second case, '<tt/(&dollar;00,x)/' is passed to the macro; this time,
including the comma. including the comma.
@@ -4072,17 +4073,17 @@ id=".MATCH" name=".MATCH">/ and <tt/<ref id=".XMATCH" name=".XMATCH">/
functions will allow you to do exactly this: functions will allow you to do exactly this:
<tscreen><verb> <tscreen><verb>
.macro ldax arg .macro ldax arg
.if (.match (.left (1, {arg}), #)) .if (.match (.left (1, {arg}), #))
; immediate mode ; immediate mode
lda #<(.right (.tcount ({arg})-1, {arg})) lda #<(.right (.tcount ({arg})-1, {arg}))
ldx #>(.right (.tcount ({arg})-1, {arg})) ldx #>(.right (.tcount ({arg})-1, {arg}))
.else .else
; assume absolute or zero page ; assume absolute or zero page
lda arg lda arg
ldx 1+(arg) ldx 1+(arg)
.endif .endif
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
Using the <tt/<ref id=".MATCH" name=".MATCH">/ function, the macro is able to Using the <tt/<ref id=".MATCH" name=".MATCH">/ function, the macro is able to
@@ -4096,11 +4097,11 @@ as end-of-list.
The macro can be used as The macro can be used as
<tscreen><verb> <tscreen><verb>
foo: .word $5678 foo: .word $5678
... ...
ldax #$1234 ; X=$12, A=$34 ldax #$1234 ; X=$12, A=$34
... ...
ldax foo ; X=$56, A=$78 ldax foo ; X=$56, A=$78
</verb></tscreen> </verb></tscreen>
@@ -4109,38 +4110,38 @@ The macro can be used as
Macros may be used recursively: Macros may be used recursively:
<tscreen><verb> <tscreen><verb>
.macro push r1, r2, r3 .macro push r1, r2, r3
lda r1 lda r1
pha pha
.if .paramcount > 1 .ifnblank r2
push r2, r3 push r2, r3
.endif .endif
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
There's also a special macro to help writing recursive macros: <tt><ref There's also a special macro command to help with writing recursive macros:
id=".EXITMACRO" name=".EXITMACRO"></tt> This command will stop macro expansion <tt><ref id=".EXITMACRO" name=".EXITMACRO"></tt>. That command will stop macro
immediately: expansion immediately:
<tscreen><verb> <tscreen><verb>
.macro push r1, r2, r3, r4, r5, r6, r7 .macro push r1, r2, r3, r4, r5, r6, r7
.ifblank r1 .ifblank r1
; First parameter is empty ; First parameter is empty
.exitmacro .exitmacro
.else .else
lda r1 lda r1
pha pha
.endif .endif
push r2, r3, r4, r5, r6, r7 push r2, r3, r4, r5, r6, r7
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
When expanding this macro, the expansion will push all given parameters When expanding that macro, the expansion will push all given parameters
until an empty one is encountered. The macro may be called like this: until an empty one is encountered. The macro may be called like this:
<tscreen><verb> <tscreen><verb>
push $20, $21, $32 ; Push 3 ZP locations push $20, $21, $32 ; Push 3 ZP locations
push $21 ; Push one ZP location push $21 ; Push one ZP location
</verb></tscreen> </verb></tscreen>
@@ -4151,27 +4152,27 @@ Now, with recursive macros, <tt><ref id=".IFBLANK" name=".IFBLANK"></tt> and
Have a look at the inc16 macro above. Here is it again: Have a look at the inc16 macro above. Here is it again:
<tscreen><verb> <tscreen><verb>
.macro inc16 addr .macro inc16 addr
clc clc
lda addr lda addr
adc #$01 adc #<$0001
sta addr sta addr
lda addr+1 lda addr+1
adc #$00 adc #>$0001
sta addr+1 sta addr+1
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
If you have a closer look at the code, you will notice, that it could be If you have a closer look at the code, you will notice, that it could be
written more efficiently, like this: written more efficiently, like this:
<tscreen><verb> <tscreen><verb>
.macro inc16 addr .macro inc16 addr
inc addr inc addr
bne Skip bne Skip
inc addr+1 inc addr+1
Skip: Skip:
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
But imagine what happens, if you use this macro twice? Since the label "Skip" But imagine what happens, if you use this macro twice? Since the label "Skip"
@@ -4183,27 +4184,27 @@ local variables are replaced by a unique name in each separate macro
expansion. So we can solve the problem above by using <tt/.LOCAL/: expansion. So we can solve the problem above by using <tt/.LOCAL/:
<tscreen><verb> <tscreen><verb>
.macro inc16 addr .macro inc16 addr
.local Skip ; Make Skip a local symbol .local Skip ; Make Skip a local symbol
inc addr inc addr
bne Skip bne Skip
inc addr+1 inc addr+1
Skip: ; Not visible outside Skip: ; Not visible outside
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
Another solution is of course to start a new lexical block inside the macro Another solution is of course to start a new lexical block inside the macro
that hides any labels: that hides any labels:
<tscreen><verb> <tscreen><verb>
.macro inc16 addr .macro inc16 addr
.proc .proc
inc addr inc addr
bne Skip bne Skip
inc addr+1 inc addr+1
Skip: Skip:
.endproc .endproc
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
@@ -4240,7 +4241,7 @@ different:
be omitted. be omitted.
<item> Since <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may not <item> Since <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros may not
contain end-of-line tokens, there are things that cannot be done. They contain end-of-line tokens, there are things that cannot be done. They
may not contain several processor instructions for example. So, while may not contain several processor instructions for example. So, while
some things may be done with both macro types, each type has special some things may be done with both macro types, each type has special
usages. The types complement each other. usages. The types complement each other.
@@ -4254,27 +4255,27 @@ To emulate assemblers that use "<tt/EQU/" instead of "<tt/=/" you may use the
following <tt/.DEFINE/: following <tt/.DEFINE/:
<tscreen><verb> <tscreen><verb>
.define EQU = .define EQU =
foo EQU $1234 ; This is accepted now foo EQU $1234 ; This is accepted now
</verb></tscreen> </verb></tscreen>
You may use the directive to define string constants used elsewhere: You may use the directive to define string constants used elsewhere:
<tscreen><verb> <tscreen><verb>
; Define the version number ; Define the version number
.define VERSION "12.3a" .define VERSION "12.3a"
; ... and use it ; ... and use it
.asciiz VERSION .asciiz VERSION
</verb></tscreen> </verb></tscreen>
Macros with parameters may also be useful: Macros with parameters may also be useful:
<tscreen><verb> <tscreen><verb>
.define DEBUG(message) .out message .define DEBUG(message) .out message
DEBUG "Assembling include file #3" DEBUG "Assembling include file #3"
</verb></tscreen> </verb></tscreen>
Note that, while formal parameters have to be placed in braces, this is Note that, while formal parameters have to be placed in braces, this is
@@ -4283,12 +4284,12 @@ detect the end of one parameter, only the first token is used. If you
don't like that, use classic macros instead: don't like that, use classic macros instead:
<tscreen><verb> <tscreen><verb>
.macro DEBUG message .macro DEBUG message
.out message .out message
.endmacro .endmacro
</verb></tscreen> </verb></tscreen>
(This is an example where a problem can be solved with both macro types). (That is an example where a problem can be solved with both macro types).
<sect1>Characters in macros<p> <sect1>Characters in macros<p>
@@ -4308,12 +4309,12 @@ be sure to take the translation into account.
<sect1>Deleting macros<p> <sect1>Deleting macros<p>
Macros can be deleted. This will not work if the macro that should be deleted Macros can be deleted. This will not work if the macro that should be deleted
is currently expanded as in the following non working example: is currently expanded as in the following non-working example:
<tscreen><verb> <tscreen><verb>
.macro notworking .macro notworking
.delmacro notworking .delmacro notworking
.endmacro .endmacro
notworking ; Will not work notworking ; Will not work
</verb></tscreen> </verb></tscreen>
@@ -4324,19 +4325,19 @@ for <tt><ref id=".DEFINE" name=".DEFINE"></tt> style macros, <tt><ref
id=".UNDEFINE" name=".UNDEFINE"></tt> must be used. Example: id=".UNDEFINE" name=".UNDEFINE"></tt> must be used. Example:
<tscreen><verb> <tscreen><verb>
.define value 1 .define value 1
.macro mac .macro mac
.byte 2 .byte 2
.endmacro .endmacro
.byte value ; Emit one byte with value 1 .byte value ; Emit one byte with value 1
mac ; Emit another byte with value 2 mac ; Emit another byte with value 2
.undefine value .undefine value
.delmacro mac .delmacro mac
.byte value ; Error: Unknown identifier .byte value ; Error: Unknown identifier
mac ; Error: Missing ":" mac ; Error: Missing ":"
</verb></tscreen> </verb></tscreen>
A separate command for <tt>.DEFINE</tt> style macros was necessary, because A separate command for <tt>.DEFINE</tt> style macros was necessary, because
@@ -4348,6 +4349,7 @@ argument to <tt>.UNDEFINE</tt> is not allowed to come from another
different commands increases flexibility. different commands increases flexibility.
<sect>Macro packages<label id="macropackages"><p> <sect>Macro packages<label id="macropackages"><p>
Using the <tt><ref id=".MACPACK" name=".MACPACK"></tt> directive, predefined Using the <tt><ref id=".MACPACK" name=".MACPACK"></tt> directive, predefined
@@ -4862,6 +4864,3 @@ freely, subject to the following restrictions:
</article> </article>

View File

@@ -51,13 +51,9 @@ soft80_init:
jmp soft80_kclrscr jmp soft80_kclrscr
soft80_shutdown: soft80_shutdown:
lda #$1b
sta VIC_CTRL1 jsr $fda3 ; Initialise I/O
lda #$03 jmp $ff5b ; Initialize screen editor
sta CIA2_PRA
lda #$15
sta VIC_VIDEO_ADR
rts
.segment "INIT" .segment "INIT"
firstinit: firstinit:

View File

@@ -262,6 +262,21 @@ void WriteFiles (void)
static void WriteEscaped (FILE* F, const char* Name)
/* Write a file name to a dependency file escaping spaces */
{
while (*Name) {
if (*Name == ' ') {
/* Escape spaces */
fputc ('\\', F);
}
fputc (*Name, F);
++Name;
}
}
static void WriteDep (FILE* F, FileType Types) static void WriteDep (FILE* F, FileType Types)
/* Helper function. Writes all file names that match Types to the output */ /* Helper function. Writes all file names that match Types to the output */
{ {
@@ -285,9 +300,9 @@ static void WriteDep (FILE* F, FileType Types)
fputc (' ', F); fputc (' ', F);
} }
/* Print the dependency */ /* Print the dependency escaping spaces */
Filename = GetStrBuf (E->Name); Filename = GetStrBuf (E->Name);
fprintf (F, "%*s", SB_GetLen (Filename), SB_GetConstBuf (Filename)); WriteEscaped (F, SB_GetConstBuf (Filename));
} }
} }
@@ -305,7 +320,8 @@ static void CreateDepFile (const char* Name, FileType Types)
} }
/* Print the output file followed by a tab char */ /* Print the output file followed by a tab char */
fprintf (F, "%s:\t", OutFile); WriteEscaped (F, OutFile);
fputs (":\t", F);
/* Write out the dependencies for the output file */ /* Write out the dependencies for the output file */
WriteDep (F, Types); WriteDep (F, Types);

View File

@@ -147,7 +147,7 @@ static int DoMacAbort = 0;
/* Counter to create local names for symbols */ /* Counter to create local names for symbols */
static unsigned LocalName = 0; static unsigned LocalName = 0;
/* Define style macros disabled if != 0 */ /* Define-style macros disabled if != 0 */
static unsigned DisableDefines = 0; static unsigned DisableDefines = 0;
@@ -422,8 +422,8 @@ void MacDef (unsigned Style)
EnterRawTokenMode (); EnterRawTokenMode ();
NextTok (); NextTok ();
/* If we have a DEFINE style macro, we may have parameters in braces, /* If we have a DEFINE-style macro, we may have parameters in parentheses;
** otherwise we may have parameters without braces. ** otherwise, we may have parameters without parentheses.
*/ */
if (Style == MAC_STYLE_CLASSIC) { if (Style == MAC_STYLE_CLASSIC) {
HaveParams = 1; HaveParams = 1;
@@ -475,7 +475,7 @@ void MacDef (unsigned Style)
} }
} }
/* For class macros, we expect a separator token, for define style macros, /* For classic macros, we expect a separator token, for define-style macros,
** we expect the closing paren. ** we expect the closing paren.
*/ */
if (Style == MAC_STYLE_CLASSIC) { if (Style == MAC_STYLE_CLASSIC) {
@@ -485,9 +485,9 @@ void MacDef (unsigned Style)
} }
/* Preparse the macro body. We will read the tokens until we reach end of /* Preparse the macro body. We will read the tokens until we reach end of
** file, or a .endmacro (or end of line for DEFINE style macros) and store ** file, or a .endmacro (or end of line for DEFINE-style macros) and store
** them into an token list internal to the macro. For classic macros, there ** them into a token list internal to the macro. For classic macros,
** the .LOCAL command is detected and removed at this time. ** the .LOCAL command is detected and removed, at this time.
*/ */
while (1) { while (1) {
@@ -752,11 +752,11 @@ ExpandParam:
FreeTokNode (Mac->Final); FreeTokNode (Mac->Final);
Mac->Final = 0; Mac->Final = 0;
/* Problem: When a .define style macro is expanded within the call /* Problem: When a .define-style macro is expanded within the call
** of a classic one, the latter may be terminated and removed while ** of a classic one, the latter may be terminated and removed while
** the expansion of the .define style macro is still active. Because ** the expansion of the .define-style macro is still active. Because
** line info slots are "stacked", this runs into a CHECK FAILED. For ** line info slots are "stacked", this runs into a CHECK FAILED. For
** now, we will fix that by removing the .define style macro expansion ** now, we will fix that by removing the .define-style macro expansion
** immediately, once the final token is placed. The better solution ** immediately, once the final token is placed. The better solution
** would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot ** would probably be to not require AllocLineInfoSlot/FreeLineInfoSlot
** to be called in FIFO order, but this is a bigger change. ** to be called in FIFO order, but this is a bigger change.
@@ -785,72 +785,74 @@ MacEnd:
static void StartExpClassic (MacExp* E) static void StartExpClassic (MacExp* E)
/* Start expanding a classic macro */ /* Start expanding a classic macro */
{ {
token_t Term; token_t Term;
/* Skip the macro name */ /* Skip the macro name */
NextTok (); NextTok ();
/* Read the actual parameters */ /* Does this invocation have any arguments? */
while (!TokIsSep (CurTok.Tok)) { if (!TokIsSep (CurTok.Tok)) {
TokNode* Last; /* Read the actual parameters */
while (1) {
TokNode* Last;
/* Check for maximum parameter count */ /* Check for maximum parameter count */
if (E->ParamCount >= E->M->ParamCount) { if (E->ParamCount >= E->M->ParamCount) {
ErrorSkip ("Too many macro parameters"); ErrorSkip ("Too many macro parameters");
break;
}
/* The macro may optionally be enclosed in curly braces */
Term = GetTokListTerm (TOK_COMMA);
/* Read tokens for one parameter, accept empty params */
Last = 0;
while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
TokNode* T;
/* Check for end of file */
if (CurTok.Tok == TOK_EOF) {
Error ("Unexpected end of file");
FreeMacExp (E);
return;
}
/* Get the next token in a node */
T = NewTokNode ();
/* Insert it into the list */
if (Last == 0) {
E->Params [E->ParamCount] = T;
} else {
Last->Next = T;
}
Last = T;
/* And skip it... */
NextTok ();
}
/* One parameter more */
++E->ParamCount;
/* If the macro argument was enclosed in curly braces, end-of-line
** is an error. Skip the closing curly brace.
*/
if (Term == TOK_RCURLY) {
if (CurTok.Tok == TOK_SEP) {
Error ("End of line encountered within macro argument");
break; break;
} }
NextTok ();
}
/* Check for a comma */ /* The macro argument optionally may be enclosed in curly braces */
if (CurTok.Tok == TOK_COMMA) { Term = GetTokListTerm (TOK_COMMA);
NextTok ();
} else { /* Read tokens for one parameter, accept empty params */
break; Last = 0;
while (CurTok.Tok != Term && CurTok.Tok != TOK_SEP) {
TokNode* T;
/* Check for end of file */
if (CurTok.Tok == TOK_EOF) {
Error ("Unexpected end of file");
FreeMacExp (E);
return;
}
/* Get the next token in a node */
T = NewTokNode ();
/* Insert it into the list */
if (Last == 0) {
E->Params [E->ParamCount] = T;
} else {
Last->Next = T;
}
Last = T;
/* And skip it... */
NextTok ();
}
/* One parameter more */
++E->ParamCount;
/* If the macro argument was enclosed in curly braces, end-of-line
** is an error. Skip the closing curly brace.
*/
if (Term == TOK_RCURLY) {
if (CurTok.Tok == TOK_SEP) {
Error ("End of line encountered within macro argument");
break;
}
NextTok ();
}
/* Check for a comma */
if (CurTok.Tok == TOK_COMMA) {
NextTok ();
} else {
break;
}
} }
} }
@@ -864,9 +866,9 @@ static void StartExpClassic (MacExp* E)
static void StartExpDefine (MacExp* E) static void StartExpDefine (MacExp* E)
/* Start expanding a DEFINE style macro */ /* Start expanding a DEFINE-style macro */
{ {
/* A define style macro must be called with as many actual parameters /* A define-style macro must be called with as many actual parameters
** as there are formal ones. Get the parameter count. ** as there are formal ones. Get the parameter count.
*/ */
unsigned Count = E->M->ParamCount; unsigned Count = E->M->ParamCount;
@@ -876,10 +878,9 @@ static void StartExpDefine (MacExp* E)
/* Read the actual parameters */ /* Read the actual parameters */
while (Count--) { while (Count--) {
TokNode* Last;
TokNode* Last; /* The macro argument optionally may be enclosed in curly braces */
/* The macro may optionally be enclosed in curly braces */
token_t Term = GetTokListTerm (TOK_COMMA); token_t Term = GetTokListTerm (TOK_COMMA);
/* Check if there is really a parameter */ /* Check if there is really a parameter */
@@ -892,7 +893,6 @@ static void StartExpDefine (MacExp* E)
/* Read tokens for one parameter */ /* Read tokens for one parameter */
Last = 0; Last = 0;
do { do {
TokNode* T; TokNode* T;
/* Get the next token in a node */ /* Get the next token in a node */
@@ -936,7 +936,7 @@ static void StartExpDefine (MacExp* E)
} }
/* Macro expansion will overwrite the current token. This is a problem /* Macro expansion will overwrite the current token. This is a problem
** for define style macros since these are called from the scanner level. ** for define-style macros since these are called from the scanner level.
** To avoid it, remember the current token and re-insert it, once macro ** To avoid it, remember the current token and re-insert it, once macro
** expansion is done. ** expansion is done.
*/ */
@@ -1007,8 +1007,8 @@ Macro* FindMacro (const StrBuf* Name)
Macro* FindDefine (const StrBuf* Name) Macro* FindDefine (const StrBuf* Name)
/* Try to find the define style macro with the given name and return it. If no /* Try to find the define-style macro with the given name; and, return it.
** such macro was found, return NULL. ** If no such macro was found, return NULL.
*/ */
{ {
Macro* M; Macro* M;
@@ -1034,7 +1034,7 @@ int InMacExpansion (void)
void DisableDefineStyleMacros (void) void DisableDefineStyleMacros (void)
/* Disable define style macros until EnableDefineStyleMacros is called */ /* Disable define-style macros until EnableDefineStyleMacros() is called */
{ {
++DisableDefines; ++DisableDefines;
} }
@@ -1042,8 +1042,8 @@ void DisableDefineStyleMacros (void)
void EnableDefineStyleMacros (void) void EnableDefineStyleMacros (void)
/* Re-enable define style macros previously disabled with /* Re-enable define-style macros previously disabled with
** DisableDefineStyleMacros. ** DisableDefineStyleMacros().
*/ */
{ {
PRECONDITION (DisableDefines > 0); PRECONDITION (DisableDefines > 0);

View File

@@ -0,0 +1,20 @@
; Test ca65's handling of the .paramcount read-only variable.
; .paramcount should see all given arguments, even when they are empty.
.macro push r1, r2, r3, r4, r5, r6
.out .sprintf(" .paramcount = %u", .paramcount)
.if .paramcount <> 0
.ifblank r1
.warning "r1 is blank!"
.exitmacro
.endif
lda r1
pha
push r2, r3, r4, r5, r6
.endif
.endmacro
push 1, , {}
push 1, ,
push 1

View File

@@ -13,6 +13,7 @@
#include <conio.h> #include <conio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <joystick.h>
#if defined(__GAMATE__) #if defined(__GAMATE__)
/* there is not enough screen space to show all 256 characters at the bottom */ /* there is not enough screen space to show all 256 characters at the bottom */
@@ -35,13 +36,16 @@ void main(void)
{ {
int i, j, n; int i, j, n;
unsigned char xsize, ysize, tcol, bgcol, bcol, inpos = 0; unsigned char xsize, ysize, tcol, bgcol, bcol, inpos = 0;
#if defined(__NES__) || defined(__PCE__) || defined(__GAMATE__)
unsigned char joy;
joy_install(joy_static_stddrv);
#endif
clrscr(); clrscr();
screensize(&xsize, &ysize); screensize(&xsize, &ysize);
cputs("cc65 conio test\n\r"); cputs("cc65 conio test\n\r");
#if !defined(__NES__) && !defined(__PCE__) && !defined(__GAMATE__) cputs("Input:[ ]");
cputs("Input: [ ]");
#endif
cputsxy(0, 2, "Colors:" ); cputsxy(0, 2, "Colors:" );
tcol = textcolor(0); /* remember original textcolor */ tcol = textcolor(0); /* remember original textcolor */
bgcol = bgcolor(0); /* remember original background color */ bgcol = bgcolor(0); /* remember original background color */
@@ -97,8 +101,10 @@ void main(void)
revers(0); revers(0);
cursor(1); cursor(1);
for(;;) { for (;;) {
/* do the "rvs" blinking */
i = textcolor(COLOR_BLACK);
gotoxy(8, 2); gotoxy(8, 2);
j = n >> 4 & 1; j = n >> 4 & 1;
revers(j); revers(j);
@@ -106,9 +112,18 @@ void main(void)
revers(j ^ 1); revers(j ^ 1);
cputs(" rvs"); cputs(" rvs");
revers(0); revers(0);
textcolor(i);
#if !defined(__NES__) && !defined(__PCE__) && !defined(__GAMATE__) gotoxy(7 + inpos,1);
gotoxy(8 + inpos,1);
#if defined(__NES__) || defined(__PCE__) || defined(__GAMATE__)
/* not all targets have waitvblank */
waitvblank();
/* for targets that do not have a keyboard, read the first
joystick */
joy = joy_read(JOY_1);
cprintf("%02x", joy);
#else
i = cgetc(); i = cgetc();
if ((i >= '0') && (i<='9')) { if ((i >= '0') && (i<='9')) {
textcolor(i - '0'); textcolor(i - '0');
@@ -133,13 +148,6 @@ void main(void)
inpos = (inpos + 1) & 7; inpos = (inpos + 1) & 7;
} }
#endif #endif
/* not all targets have waitvblank() */
#if defined(__NES__) || defined(__PCE__) || defined(__GAMATE__)
waitvblank();
#endif
++n; ++n;
} }
for(;;);
} }

View File

@@ -5,35 +5,9 @@
#include <conio.h> #include <conio.h>
#include <em.h> #include <em.h>
#if defined(__C64__)
#define DRIVERNAME "c64-ram.emd"
#elif defined(__C128__)
#define DRIVERNAME "c128-ram.emd"
#elif defined(__C16__)
#define DRIVERNAME "c16-ram.emd"
#elif defined(__CBM510__)
#define DRIVERNAME "cbm510-ram.emd"
#elif defined(__CBM610__)
#define DRIVERNAME "cbm610-ram.emd"
#elif defined(__APPLE2ENH__)
#define DRIVERNAME "a2e.auxmem.emd"
#elif defined(__APPLE2__)
#define DRIVERNAME "a2.auxmem.emd"
#elif defined(__ATARIXL__)
#define DRIVERNAME "atrx130.emd"
#elif defined(__ATARI__)
#define DRIVERNAME "atr130.emd"
#else
#define DRIVERNAME "unknown"
#error "Unknown target system"
#endif
#define FORCE_ERROR1 0 #define FORCE_ERROR1 0
#define FORCE_ERROR2 0 #define FORCE_ERROR2 0
#define PAGE_SIZE 128 /* Size in words */ #define PAGE_SIZE 128 /* Size in words */
#define BUF_SIZE (PAGE_SIZE + PAGE_SIZE/2) #define BUF_SIZE (PAGE_SIZE + PAGE_SIZE/2)
static unsigned buf[BUF_SIZE]; static unsigned buf[BUF_SIZE];
@@ -75,7 +49,65 @@ static void cmp (unsigned page, register const unsigned* buf,
} }
} }
typedef struct emd_test_s {
char key;
char *displayname;
char *drivername;
} emd_test_t;
static emd_test_t drivers[] = {
#if defined(__APPLE2__)
{ '0', "Apple II auxiliary memory", "a2.auxmem.emd" },
#endif
#if defined(__APPLE2ENH__)
{ '0', "Apple II auxiliary memory", "a2e.auxmem.emd" },
#endif
#if defined(__ATARI__)
{ '0', "Atari 130XE memory", "atr130.emd" },
#endif
#if defined(__ATARIXL__)
{ '0', "Atari 130XE memory", "atrx130.emd" },
#endif
#if defined(__C16__)
{ '0', "C16 RAM above $8000", "c16-ram.emd" },
#endif
#if defined(__C64__)
{ '0', "C64 RAM above $D000", "c64-ram.emd" },
{ '1', "C64 256K", "c64-c256k.emd" },
{ '2', "Double Quick Brown Box", "c64-dqbb.emd" },
{ '3', "GEORAM", "c64-georam.emd" },
{ '4', "Isepic", "c64-isepic.emd" },
{ '5', "RamCart", "c64-ramcart.emd" },
{ '6', "REU", "c64-reu.emd" },
{ '7', "C128 VDC (in C64 mode)", "c64-vdc.emd" },
{ '8', "C64DTV himem", "dtv-himem.emd" },
#endif
#if defined(__C128__)
{ '0', "C128 RAM in bank 1", "c128-ram.emd" },
{ '1', "C128 RAM in banks 1, 2 & 3", "c128-ram2.emd" },
{ '2', "GEORAM", "c128-georam.emd" },
{ '3', "RamCart", "c128-ramcart.emd" },
{ '4', "REU", "c128-reu.emd" },
{ '5', "VDC", "c128-vdc.emd" },
#endif
#if defined(__CBM510__)
{ '0', "CBM5x0 RAM in bank 2", "cbm510-ram.emd" },
#endif
#if defined(__CBM610__)
{ '0', "CBM6x0/7x0 RAM in bank 2", "cbm610-ram.emd" },
#endif
{ 0, NULL, NULL }
};
int main (void) int main (void)
{ {
@@ -85,9 +117,27 @@ int main (void)
unsigned PageCount; unsigned PageCount;
unsigned char X, Y; unsigned char X, Y;
struct em_copy c; struct em_copy c;
unsigned index;
signed char valid_key = -1;
char key;
clrscr (); clrscr ();
Res = em_load_driver (DRIVERNAME); cputs ("Which RAM exp to test?\r\n\r\n");
for (index = 0; drivers[index].key; ++index) {
cprintf("%c: %s\r\n", drivers[index].key, drivers[index].displayname);
}
while (valid_key < 0) {
key = cgetc();
for (index = 0; drivers[index].key && valid_key < 0; ++index) {
if (key == drivers[index].key) {
valid_key = index;
}
}
}
clrscr ();
Res = em_load_driver (drivers[valid_key].drivername);
if (Res != EM_ERR_OK) { if (Res != EM_ERR_OK) {
cprintf ("Error in em_load_driver: %u\r\n", Res); cprintf ("Error in em_load_driver: %u\r\n", Res);
cprintf ("os: %u, %s\r\n", _oserror, _stroserror (_oserror)); cprintf ("os: %u, %s\r\n", _oserror, _stroserror (_oserror));