mirror of
https://github.com/antoinevignau/source.git
synced 2025-01-01 15:30:02 +00:00
1 line
10 KiB
Plaintext
Executable File
1 line
10 KiB
Plaintext
Executable File
;..............................................................................;
|
||
;
|
||
; If - expression, test, value, goto
|
||
;
|
||
; This macro implements an if construct. The expression will be evaluated,
|
||
; its value compared to the given value, and if the test succeeds execution
|
||
; continues at 'goto'. Otherwise execution will continue until an EndWhile
|
||
; macro is encountered.
|
||
;
|
||
; The expression may be a register, simple variable, or complex expression.
|
||
; If the 'goto' label is preceeded by a '!' then it is assumed that a long
|
||
; branch is necessary.
|
||
;
|
||
; Sample calls:
|
||
;
|
||
; If X,'<>',#50,DoneIf - if x<>50 then goto DoneIf
|
||
; If Var1,'=',Var2,!DoneIf - if var1=var2 then branch long to DoneIf
|
||
; If '(Var1.+Var2)','>',Var3,Quit - if var1+var2>var3 then goto Quit
|
||
;
|
||
; The following test conditions are supported and must be quoted:
|
||
;
|
||
; '=', '>', '>=', '<', '<=', '<>'
|
||
;
|
||
; A complex expression must be quoted and placed in paranthesis to work
|
||
; correctly.
|
||
;
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab IF_ &exp,&test,&value,&goto
|
||
&lab ;
|
||
lclc &cc
|
||
lclc &first
|
||
lclc &newexp
|
||
lclc &WorkAroundApplesBuggyAssembler
|
||
|
||
|
||
&newexp setc &exp
|
||
|
||
&first setc &substr(&newexp,1,1)
|
||
IF (&newexp = 'x') or (&newexp = 'y') or (&newexp = 'a') GOTO .register
|
||
IF (&newexp = 'X') or (&newexp = 'Y') or (&newexp = 'A') GOTO .register
|
||
IF (&first = '(') GOTO .expression
|
||
.simplevar
|
||
lda &newexp
|
||
cmp &value
|
||
GOTO .dotest
|
||
|
||
mexit
|
||
.expression
|
||
&newexp setc &substr(&newexp,2,&len(&newexp)-2)
|
||
eval &newexp
|
||
cmp &value
|
||
GOTO .dotest
|
||
|
||
.register
|
||
&WorkAroundApplesBuggyAssembler setc &concat('cp',&newexp)
|
||
.; cp&newexp &value **SIGH!!!!!!**
|
||
&WorkAroundApplesBuggyAssembler &value
|
||
GOTO .dotest
|
||
|
||
.dotest
|
||
IF (&test = '=') GOTO .doeq
|
||
IF (&test = '<') GOTO .dolt
|
||
IF (&test = '>=') GOTO .doge
|
||
IF (&test = '<>') GOTO .done
|
||
IF (&test = '<=') GOTO .dole
|
||
IF (&test = '>') GOTO .dogt
|
||
IF (&test = '<27>') GOTO .dole
|
||
IF (&test = '<27>') GOTO .doge
|
||
IF (&test = '<27>') GOTO .done
|
||
macerr 'IF_: unrecognized comparison <20>',&test,'<27> (make sure it's not in quotes).'
|
||
mexit
|
||
.doeq
|
||
&cc setc 'eq'
|
||
GOTO .goto
|
||
|
||
.dolt
|
||
&cc setc 'lt'
|
||
GOTO .goto
|
||
|
||
.doge
|
||
&cc setc 'ge'
|
||
GOTO .goto
|
||
|
||
.done
|
||
&cc setc 'ne'
|
||
GOTO .goto
|
||
|
||
.dole
|
||
&cc setc 'le'
|
||
GOTO .goto
|
||
|
||
.dogt
|
||
&cc setc 'gt'
|
||
GOTO .goto
|
||
|
||
mexit
|
||
.goto
|
||
jump &cc,&goto
|
||
mexit
|
||
MEND
|
||
;..............................................................................;
|
||
;
|
||
; jump - Branch on condition code to short/long label
|
||
;
|
||
; Generic jump macro. If label starts with ! will do long jump else short.
|
||
;
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab jump &cc,&label
|
||
&lab ;
|
||
lclc &a
|
||
|
||
&a setc &substr(&label,1,1)
|
||
IF (&a = '!') GOTO .long
|
||
b&cc &label
|
||
mexit
|
||
.long
|
||
&a setc &substr(&label,2,&len(&label)-1)
|
||
j&cc &a
|
||
mexit
|
||
MEND
|
||
|
||
;..............................................................................;
|
||
;
|
||
; While - expression, test, value, resume
|
||
;
|
||
; This macro implements a while construct. The expression will be evaluated,
|
||
; its value compared to the given value, and if the test fails execution will
|
||
; continue at 'resume'. Otherwise execution will continue until an EndWhile
|
||
; macro is encountered.
|
||
;
|
||
; The expression may be a register, simple variable, or complex expression.
|
||
; If the 'resume' label is preceeded by a '!' then it is assumed that a long
|
||
; branch is necessary.
|
||
;
|
||
; Sample calls:
|
||
;
|
||
; While X,'<>',#50 - loop until x register = 50
|
||
; While Var1,'=',Var2 - loop until var1<>var2, then jump long
|
||
; While '(Var1.+Var2)','>',Var3 - loop until var1+var2<=var3
|
||
;
|
||
; The following test conditions are supported and must be quoted:
|
||
;
|
||
; '=', '>', '>=', '<', '<=', '<>'
|
||
;
|
||
; A complex expression must be quoted and placed in paranthesis to work
|
||
; correctly.
|
||
;
|
||
; Note: Up to 10 levels of local while nesting are supported.
|
||
;
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab while_ &exp,&test,&value
|
||
&lab ;
|
||
|
||
lclc &long
|
||
.; IF (&nbr(&wcnt) > 0) GOTO .past
|
||
gbla &wcnt
|
||
gblc &while[10]
|
||
gbla &wnum[10]
|
||
|
||
IF (&wcnt = 10) THEN
|
||
macerr 'Too many levels of nested While_'s (max. 10).'
|
||
mexit
|
||
ENDIF
|
||
.past
|
||
&wcnt seta &wcnt+1
|
||
&while[&wcnt] setc &concat('~A',&i2s(&sysindex))
|
||
&wnum[&wcnt] seta &wnum[&wcnt]+1
|
||
~A&i2s(&sysindex) ;
|
||
if_ &exp,&test,&value,&concat('~B',&i2s(&sysindex))
|
||
brl &concat('~W',&concat(&i2s(&wcnt),&i2s(&wnum[&wcnt])))
|
||
~B&i2s(&sysindex) ;
|
||
mexit
|
||
MEND
|
||
;..............................................................................;
|
||
;
|
||
; EndWhile
|
||
;
|
||
; This macro will return control back to the latest while loop encountered.
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab endwhile_
|
||
&lab ;
|
||
|
||
gbla &wcnt
|
||
gblc &while[10]
|
||
gbla &wnum[10]
|
||
|
||
IF (&wcnt = 0) THEN
|
||
macerr 'Unexpected EndWhile_.'
|
||
mexit
|
||
ENDIF
|
||
|
||
brl &while[&wcnt]
|
||
~W&i2s(&wcnt)&i2s(&wnum[&wcnt]) ;
|
||
&wcnt seta &wcnt-1
|
||
mexit
|
||
MEND
|
||
;..............................................................................;
|
||
;
|
||
; Repeat
|
||
;
|
||
; This macro will set a label to the start of a repeat/until loop for the
|
||
; current lexical level.
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab repeat_
|
||
&lab ;
|
||
.; IF (&nbr(&rcnt) > 0) GOTO .past
|
||
gbla &rcnt
|
||
gblc &repeat[10]
|
||
.past
|
||
&rcnt seta &rcnt+1
|
||
&repeat[&rcnt] setc &concat('~A',&i2s(&sysindex))
|
||
~A&i2s(&sysindex) ;
|
||
mexit
|
||
MEND
|
||
|
||
;..............................................................................;
|
||
;
|
||
; Until &exp,&test,&value
|
||
;
|
||
; If the expression evaluates to true then exit else return to the
|
||
; last seen repeat.
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab until_ &exp,&test,&value
|
||
&lab ;
|
||
gbla &rcnt
|
||
gblc &repeat[10]
|
||
if_ &exp,&test,&value,&concat('~B',&i2s(&sysindex))
|
||
brl &repeat[&rcnt]
|
||
~B&i2s(&sysindex) ;
|
||
&rcnt seta &rcnt-1
|
||
mexit
|
||
MEND
|
||
|
||
;..............................................................................;
|
||
;
|
||
; FOR variable, initial value, final value, step size
|
||
;
|
||
; This macros implements a primitive FOR type construct. The specified
|
||
; variable may be either a register ('X','Y','A') or a memory location. The
|
||
; variable is currently assumed to be of word size. It will get loaded with
|
||
; the initial value specified. Execution will loop between the FOR and NEXT
|
||
; macros until the variable exceeds the final value, each pass through the
|
||
; loop the variable or register as the case may be is offset by the given
|
||
; step size. Step size may be positive or negative but must be word size.
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab for_ &var,&init,&final,&step
|
||
&lab ;
|
||
.; IF (&nbr(&fcnt) > 0) GOTO .past
|
||
gbla &fcnt
|
||
gblc &for[10]
|
||
gblc &forstep[10]
|
||
gblc &forfinal[10]
|
||
gblc &forvar[10]
|
||
.past
|
||
&fcnt seta &fcnt+1
|
||
&for[&fcnt] setc &concat('~A',&i2s(&sysindex))
|
||
&forstep[&fcnt] setc &step
|
||
&forfinal[&fcnt] setc &final
|
||
IF (&var = 'x') or (&var = 'X') GOTO .initx
|
||
IF (&var = 'y') or (&var = 'Y') GOTO .inity
|
||
lda &init
|
||
&forvar[&fcnt] setc 'A'
|
||
IF (&var = 'a') or (&var = 'A') GOTO .quit
|
||
sta &var
|
||
&forvar[&fcnt] setc &var
|
||
GOTO .quit
|
||
|
||
.initx
|
||
ldx &init
|
||
&forvar[&fcnt] setc 'X'
|
||
GOTO .quit
|
||
|
||
.inity
|
||
ldy &init
|
||
&forvar[&fcnt] setc 'Y'
|
||
.quit
|
||
~A&i2s(&sysindex) ;
|
||
mexit
|
||
MEND
|
||
;..............................................................................;
|
||
;
|
||
; NEXT
|
||
;
|
||
; See description under FOR.
|
||
;
|
||
;..............................................................................;
|
||
MACRO
|
||
&lab next_
|
||
&lab ;
|
||
gbla &fcnt
|
||
gblc &for[10]
|
||
gblc &forstep[10]
|
||
gblc &forfinal[10]
|
||
gblc &forvar[10]
|
||
IF (&forvar[&fcnt] = 'A') GOTO .nextA
|
||
IF (&forvar[&fcnt] = 'X') GOTO .nextX
|
||
IF (&forvar[&fcnt] = 'Y') GOTO .nextY
|
||
lda &forvar[&fcnt]
|
||
GOTO .nextA
|
||
|
||
.nextX
|
||
txa
|
||
GOTO .nextA
|
||
|
||
.nextY
|
||
tya
|
||
.nextA
|
||
IF (&forstep[&fcnt] = '#1') GOTO .incA
|
||
IF (&forstep[&fcnt] = '#-1') GOTO .decA
|
||
clc
|
||
adc &forstep[&fcnt]
|
||
GOTO .donextA
|
||
|
||
.decA
|
||
dec a
|
||
GOTO .donextA
|
||
|
||
.incA
|
||
inc a
|
||
.donextA
|
||
IF (&forvar[&fcnt] = 'X') GOTO .setx
|
||
IF (&forvar[&fcnt] = 'Y') GOTO .sety
|
||
IF (&forvar[&fcnt] = 'A') GOTO .checkit
|
||
sta &forvar[&fcnt]
|
||
GOTO .checkit
|
||
|
||
.setx
|
||
tax
|
||
GOTO .checkit
|
||
|
||
.sety
|
||
tay
|
||
GOTO .checkit
|
||
|
||
.checkit
|
||
cmp &forfinal[&fcnt]
|
||
bgt ~F&i2s(&sysindex)
|
||
brl &for[&fcnt]
|
||
.quit
|
||
~F&i2s(&sysindex) ;
|
||
&fcnt seta &fcnt-1
|
||
mexit
|
||
MEND
|