So I expanded on this idea quite a bit, I'll link code soonish. It's pretty useful imo at this point and I think most bugs are fixed.
I decided to name the macro 'mb' so it's easy to type primarily. It stands for Move Byte, since that is mostly what is does.
I guess you could also define an underscore to do the same thing perhaps for readability to make it look like more natural code in the source.
So what it does is figure out what is on the right side of an assignment and assign it to whatever is on the left. It's pretty flexible at figuring out what to do, and should work as expected:
mb foo := bar
So, foo and bar can both be either a 6502 register or memory address (variable). If for example you did:
mb x := a
It will output a tax instruction. The left side is limited to a memory address or register, but the right side can also be a simple expression:
mb x := CurrentWorld + #1 & #%00000111
It will figure out the right side is going to have to use the accumulator, output the correct code, then do a tax. If the assignment was the accumulator, there would be no output for the assignment (since the accumulator is already holding the result).
If you have two variable names and no indication of the register to use, the default is to use the accumulator. This can be overridden as:
mb x, var1 := var2
This will output: ldx var2 \ stx var1
This only forces the register on the right side - if the left side is a different register assignment still happens with the register indicated.
Forcing is only useful where it is not obvious what must be used, though you could force it all the time if you wanted to be explicit - you will get an error if you try to force an index register with functionality that requires the accumulator. Code that specifies a register 1st after the := will behave the same as a forced register. ( y := x + 3 will force using reg x on the right side... see below)
Support for the following:
Code:
& bit and
| bit or
^ bit eor
+ add, clear carry 1st
++ add with carry
- sub, set carry 1st
-- sbc with carry
<< shift reg a left
>> shift reg a right
* multiply
/ divide
Shifting requires a plain constant value after the operator and will output that many asl or lsr commands. Multiply or divide also require a constant value of power of 2 (same as shifting of course.)
You can also use a single - or + with x and y followed by a plain constant value - that is how many decrement or increment commands will be output.
This is intended for simple, very close to assembly type code, so there is no support for brackets in the expressions or trying to use more than one register at a time in a single expression, though brackets will be skipped if you want to use the operators to write a constant expression.
I have also integrated this into the logical block code, as in this part of the timer code from smb:
Code:
; if game timer not yet at digits at 000
if GameTimerDisplay | GameTimerDisplay[1] | GameTimerDisplay[2] == not zero
; if timer = 100
if ( y := GameTimerDisplay - 1 == zero ) && ( GameTimerDisplay[1] | GameTimerDisplay[2] == zero )
mb EventMusicQueue := #TimeRunningOutMusic
endif
mb GameTimerCtrlTimer := #$18 ; reset game timer control
mb y := #$23 ; set offset for last digit
mb DigitModifier[ 5 ] := #$ff ; set value to decrement game timer digit
jsr DigitsMathRoutine ; do sub to decrement game timer slowly
mb a := #$a4 ; set status nybbles to update game timer display
jmp PrintStatusBarNumbers ; do sub to update the display
endif
The expression in the if condition share the same code as 'mb'.
As well, the
[ constant ] syntax can be used rather that
+ constant. You can also include x or y:
mb VRAM_Buffer1[ x - 1 ] := WSelectBufferTemplate[ x ]
For indexed (I find it more readable.)
Any questions, feedback or criticisms welcome.
BTW I agree that would be nice to have .param as rainwarrior described. You can mostly get that functionality with .mid and recursive calls, but not as nicely.
EDIT: This macro is included as a part of ca65hl.