| |
Slammer
Registered: Feb 2004 Posts: 416 |
Kick Assembler Thread 2
The previous thread took a little long to load, so this is a new fresh one.. |
|
... 592 posts hidden. Click here to view all posts.... |
| |
Angel of Death
Registered: Apr 2008 Posts: 210 |
How much I love using macros and however timesaving it is I am always a bit concerned with not knowing how long my code will turn out. In other words: I'm always worried about ,when finally finished and working, having to take apart the macros to optimize the code to make it shorter...
Probably an OCD symptom on my part but I just happen to like compact code. :)
Anyways. Is there some methode of keeping track of the length besides compiling it and hoping for the best?
|
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
As compiling takes seconds at most, I'll suffer that time.
Work takes 6-10 minutes for build and redeploy. Now that hurts, especially when you leave a space out of a dynamically generated SQL statement.
|
| |
TWW
Registered: Jul 2009 Posts: 543 |
Quote: Look in the manual under pseudo commands. Here is showed how to define 16 bit pseudo commands. There is a move command which is defined like this:
.function _16bit_nextArgument(arg) {
.if (arg.getType()==AT_IMMEDIATE) .return CmdArgument(arg.getType(),>arg.getValue())
.return CmdArgument(arg.getType(),arg.getValue()+1)
}
.pseudocommand mov16 src;tar {
lda src
sta tar
lda _16bit_nextArgument(src)
sta _16bit_nextArgument(tar)
}
With this you can do stuff like:
:mov16 #irq ; $fffe
:mov16 irqTable,x ; $fffe
etc.
You can now define you pseudocommand like this:
pseudocommand irqEnd d12 ; irq {
lda d12
sta $d012
:mov16 irq ; $fffe
}
and use it like this:
:irqEnd #$10 ; #irq1
or
:irqEnd d012Table,y ; irqTable,x
Yeah I saw that section but I thought there might be a more easy approach then define your own special functions to deal with a triviel task such as hi/lo pointers.
I had already used macros for this task but wanted to check out this posibility aswell :)
I guess in the long run pseudo-ops are more convenient even though a little more extensive in the beginning.
*cheers* |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
The _16bit_nextArgument(arg) function is the easy way to deal with 16 bit values. Just write the 4 lines once and newer think about it again. This is good when you have to define many 16bit pseudo commands. If you don't like structural things like the _16bit_nextArgument function and the mov command, simply define the pseudocommand directly as shown below. (I guess I should have given you this example in the first place since it easer to look at).
.pseudocommand irqEnd d12 ; irq {
.var hiArg
.if (irq.getType()==AT_IMMEDIATE) .eval hiArg= CmdArgument(arg.getType(),>arg.getValue())
else .eval hiArg= CmdArgument(arg.getType(),arg.getValue()+1)
lda d12
sta $d012
lda irq
sta $fffe
lda hiArg
sta $ffff
}
|
| |
andym00
Registered: Jun 2009 Posts: 45 |
First up, absolutely love Kick to bits, and now I actually
want to convert over a project to using Kick from ACME
before it goes too far to be practical.. I'm wondering what
the simplest way is to achieve the likes of the references
as in ACME assembler ?
I can't see a sensible way to achieve something like this..
!macro sw_register ~.name, .dst {
.name = *+1
lda #$ff
sta .dst
}
+macro(MySoftwareRegisterName, $d020)
Is there any nice simple way to allow macros to define a
passed in reference ?
I've got an absolute mountain of macros used like this that
I would need to convert and just can't see how you do this
in Kick..
edit: A more real world example of the kind of thing i mean,
since that example above is perhaps to simplistic ;)
!Macro Voice_Level voice_number, ~.level_timer, ~.level_destination, ~.level_lo, ~.level_hi, ~.level_delta_lo, ~.level_delta_hi, ~.waveform, ~.setlevel, ~.process, v0, v1, v2, v3 {
.start:
.l_timer ldx #0
cpx #1
bne .still_active
; Switch off the level flag..
lda voice_flags+voice_number
and #!FLAGS_LEVEL_ACTIVE
sta voice_flags+voice_number
; Snap the level interpolation into place by zeroing the rates..
lda #0
sta .ld_lo+1
sta .ld_hi+1
sta .l_lo+1
; And snap to the final level value to where we should be..
.l_dest lda #0
jmp .l_hi_write
.still_active
dex
stx .l_timer+1
clc
.l_lo lda #0
.ld_lo adc #0
sta .l_lo+1
.l_hi lda #0
.ld_hi adc #0
.l_hi_write sta .l_hi+1
clc
.l_wave adc #0 ; Waveform base.. Should be the base of one of the 16 waveforms..
.l_wave_cmp cmp #0
beq +
sta .l_wave_cmp+1
sta v0
sta v1
sta v2
sta v3
+
rts
.level_timer = .l_timer+1
.level_destination = .l_dest+1
.level_lo = .l_lo+1
.level_hi = .l_hi+1
.level_delta_lo = .ld_lo+1
.level_delta_hi = .ld_hi+1
.waveform = .l_wave+1
.setlevel = .l_hi_write
.process = .start
}
And then created like:
+Voice_Level 0, ~Voice_0_Level_Timer, ~Voice_0_Level_Final, ~Voice_0_Level_lo, ~Voice_0_Level_hi, ~Voice_0_Level_Delta_lo, ~Voice_0_Level_Delta_hi, ~Voice_0_Waveform, ~Voice_0_Set_Level, ~Voice_0_Level_Process, .v0_0+2, .v0_1+2, .v0_2+2, .v0_3+2
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi Andy
First of all, I dont know the acme syntax, but Im guessing that the ~ means by reference, instead of by value.
You are right; Kick Assembler doesn't pass values by reference. You could define a hashtable with the parameter values and use this as parameter, or simply use global variables.
Personally I would prefer to avoid side effects as much as possible. You increase the first five referenced variables by one. This can be achieved in the function call by using the ++ operator like in C++ (It passes the original value to the function, and then increments the variable by one).
:VoiceLevel(0, Voice_0_Level_Timer++, Voice_0_Level_Final++, ect
The setLevel and the process parameters gets information on memorylocations out of the macro. Right now you have to do this by hand like:
.eval setLevel=*+27
.eval process=*
:VoiceLevel(0,
.)
But! In one of the next versions there will be autonamespacing on macros and pseudocommands, which is a really elegant way of solving this. This means that you can access the variables of a macro just by placing a label in front of the macro call. Then you will be able to write code like this:
lda #10
sta v1.l_hi_write+1
vl: :VoiceLevel(
)
(The current version of Kick Assembler supports autonamespacing when a label is put in front of a scope, see the manual for details)
|
| |
andym00
Registered: Jun 2009 Posts: 45 |
Thanks Slammer :)
Yeah, those are pass by reference instead of value, I know
not the nicest way of doing things, but it allows you to
nicely wrap a macro up like that..
Having to do them like in the .eval setLevel=*+27
fashion was what I was afraid of as I know things
are just going to go catastrophically wrong at some point..
A little tweak of the code and forgetting to change the
offsets and hours will go into hunting a stupid bug ;)
I'll have a look into using the hashtables, but I really
don't want to spend forever messing with these ungodly
macros.. It was a mistake to write it like that, but ACME
just made it too easy to do it like it..
The auto namespacing on macros and pseudo-commands sounds
absolutely perfect for the job though..
I guess I'll just leave this with ACME for now.. That one
macro was only one of many many like that, and that's
probably the smallest of the buggers.. I'll finish this up
and then move on to Kick Assembler once and for all as
there's so many nice goodies on offer with it..
(and sorry for bollocksing up the formatting of this thread
with the rather long line!! Any chance a mod can edit that
post of mine and trim the last line ?) |
| |
neilbaldwin Account closed
Registered: Sep 2009 Posts: 48 |
Been trying Kick Assembler today and it's a breath of fresh air. Well done for taking a different approach and dragging things towards more modern programming. :)
One question: is it possible to point the java runtime environment to the path where KickAss.jar exists or do you always have to specify the full path? I'm on OSX (so unix/BSD) and normally put user executables in, say, /usr/local/bin so that I can run them from any shell prompt. However it doesn't seem possible with java though my knowledge is very limited. :)
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
You can always insert the KickAss.jar in the java CLASSPATH environment variable, but then you will have to give the 'package path' to the runtime enviroment at the commandline like this:
java cml.kickass.KickAssembler mysource.asm
If I was in your place i would make some kind of batfile or alias that takes the sourcefile as argument and execute KickAssembler. |
| |
neilbaldwin Account closed
Registered: Sep 2009 Posts: 48 |
Quote: You can always insert the KickAss.jar in the java CLASSPATH environment variable, but then you will have to give the 'package path' to the runtime enviroment at the commandline like this:
java cml.kickass.KickAssembler mysource.asm
If I was in your place i would make some kind of batfile or alias that takes the sourcefile as argument and execute KickAssembler.
I've done just that - works like a charm.
(Slightly embarrassed that I didn't think of it myself LOL)
|
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ... | 61 - Next |