| |
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.. |
|
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
maybe you should just change your forum settings. you can set how many of the latest posts you want to see. i guess you set it to show all posts. for me the thread loads fast enough. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I dont know what happend but suddenly I found it taking ages each time i pressed preview or submitted a post :-) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I just been looking around to see if I can find some wrong settings. Clicking on 'My Settings' gives me 'Post shown pr page = 10. However I still get all the posts shown in the Kick Ass thread.. I need a hint how i edit the settings of an individual thread? |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
sounds like a cookie/browser issue. that setting applies to all threads afaik. |
| |
Mix256 Account closed
Registered: Dec 2008 Posts: 26 |
I'm taking this here, since the thread got the attention.
Bug-description: The "-o" option don't seemt to work.
[java] Warning. Allready have an inputfile. Won't use 'src/game/kng2.asm'
[java] Error: Inputfile '-o game.prg' doesn't exist.
|
| |
yago
Registered: May 2002 Posts: 332 |
Slammer: It was probably the LCP aftermath, whole CSDb was sloppy.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Mix256: You will have to give me the whole commandline so I can test it. The following works fine for me:
test1.asm -showmem -debug -execute "c:/c64/winvice-1.22/x64.exe -confirmexit +sound +truedrive -VICIIdsize" -vicesymbols -o myfile.prg
|
| |
Mix256 Account closed
Registered: Dec 2008 Posts: 26 |
Sorry, just switched IDE and this one gave me some strange troubles. Works fine in cmd for me as well. Truly sorry!
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Nice assembler. The cmd-line works fine but I am having trouble Assembling the source from Relaunch64 (V2.1 B3).
I have set up KickAss as compiler #1 and when I try to assemble the folowing:
.pc = $0810
lda #$00
sta $d020
rts
(file: test.asm)
it produces just a quick cmd prompt window flash and does not produce any test.prg.
I removed the default parameters in the compiler set up and the Parameter field is empty.
I have not specified any output directory for compiled source but tried that aswell.
sugestions? |
| |
LOGAN Account closed
Registered: Aug 2003 Posts: 71 |
Does the source have any basic start to run?
a file test.asm should produce a test.prg somewhere. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
basic sys-trick is not implemented no. I will use that later when I get the file generated. One thing at a time :)
The .prg isn't generated since iv'e searched the entire c-drive for it.
something goes wrong when compiling and I don't know if it is a argument or something which has to be passed for this to work.......
BUT it works in cmd-line and not in the IDE. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I just tried it and it seems to work fine. Here is what to do:
1. Go into options->compiler settings->setup compiler 1
2. Enter the path to the KickAss.jar file
3. Select KickAssembler as your assembler.
4. compile your source
When you select KickAssembler in step 3, the following parameters are generated :
-log c64error.txt INPUT -o OUTPUT
The -log switch tells KickAssembler to dump all output to a logfile, since Relaunch doesn't catch the output to the console. My guess is that you have modified the -log switch parameter so no log file is generated. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
I followed yuor receipy to the letter (Which is the same as I initially did). When I selected KackAss as a compiler the parameters are generated automatically (here is a ctrl+c+v of my parameters):
-log c64error.txt INPUT -o OUTPUT
and yes KickAss is selected in the drop down thingy aswell.
The Relaunch64 I use is a Beta version can this matter?
Can the location of the different files matter (Here is my setup):
C:\Commodore 64\KickAssembler\KickAss.jar
C:\Commodore 64\Relaunch64\Relaunc64.exe
C:\Documents and Settings\tomw\My Documents\Code\test\test.asm
since it compiles from CMD I recon it should not be any problems with java stuff (Wich is latest and greatest anyways).
However when i compiled from command i copied the test.asm file to the kickass folder due to lazyness in pathtyping :-)
so still stuck I'm afraid :( |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
the first thing i'd try would be ... use path names without spaces :) many programs fail on those, for some reason. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I see that you have spaces in the filepath and that might be a problem. Unless Relaunch uses quotes around its arguments windows interpret the filepath as two arguments instead of one:
So this is bad:
java -jar C:\Commodore 64\KickAssembler\KickAss.jar
and this is ok:
java -jar "C:\Commodore 64\KickAssembler\KickAss.jar"
So try removing the space in Commodore 64 and place your sourcefile in a place like C:\source.
Edit: Seems Groepaz came first with the same reply :-) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Eureka.
I did the folowing after reading your posts:
instead of:
C:\Commodore 64\KickAssembler\KickAss.jar
i do a:
C:\Commod~1\KickAs~1\KickAss.jar
and now the code is compiled. However the file test.prg got stored in the kickass directory instead of the directory from wich it came from... maybee i need to use a c:\source as you said :)
thanx
|
| |
LOGAN Account closed
Registered: Aug 2003 Posts: 71 |
I think I used something like quotes around the input output to accomidate spaces in pathnames plus relaunch64
maybe something like this:
-log c64error.txt "INPUT" -o "OUTPUT"
On a side note I think there was an option to choose where an prg file would be stored... |
| |
TWW
Registered: Jul 2009 Posts: 541 |
I saw that option too but this would mean it will always produce the .prg in that location and i have 'several' projects going and I want them to be generated in their respective folder. So i'll try the quotes trick. thanx for the advice!
Edit: I tried the qutes and quotes around input produced an error and around output made no difference.
Edit 2: I tried to launc the source file from C:\source\test.txt and the test.prg and the errorlog.txt file ends up in kickass directory. This ain't my day (yeah I have a fricking bad hang over too)... |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
KickAssembler saves the prg file to the current directory unless a specific destination is given.
I find that naturally, but I'll change it if this is not the standard for Compilers / Assemblers around?
Btw. If I change it, I guess you will get in trouble with the autorun facility of relaunc, which can't find the prg file, so we will have to involve Daniel aswell. However, I guess having the prg-files in the KickAss dir is messy, but not a major problem.
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
i would find it very strange if a compiler/assembler wouldnt save the output to current directory - or whatever destination is explictly given to the -o option .... and i dont think i have ever seen a compiler/assembler that behaves different in that respect :) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Right.
I guess it depends what you have been used to doing. B4 i used a ms-dos shortcut in the folder of my project which in turn generated the .prg in the same project folder.
But as you said Slammer, It probably isn't suck a big problem to have the .prg file(s) in the kickass directory. I just have to get used to it :) Thanx for a great tool btw.
ps. Headache is gone btw thanx to an execcive order of grease/salt from the local McDonalds ^^ |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Question:
I am setting up 16 irq's with 5 splitts each and naturally I want to use macros to do this.
Here is what i have:
.var raster1 = 90
.var raster2 = 130
.var raster3 = 170
.var raster4 = 210
.var raster5 = 50
*setup irg here*
irq: :interupt(raster1,$1b,$78,$18,$02)
..code..
:endirq
!irq :interupt(raster2,$1b,$78,$18,$02)
..code..
:endirq
!irq :interupt(raster3,$1b,$78,$18,$02)
..code..
:endirq
!irq :interupt(raster4,$1b,$78,$18,$02)
..code..
:endirq
!irq :interupt(raster5,$1b,$08,$15,$03)
..code..
lda #<irq
sta $0314
lda #>irq
sta $0315
:endirq
and the macros look like this:
.macro interupt(d12,d11,d16,d18,dd0) {
dec $d019
lda #d12
sta $d012
lda #d11
sta $d011
lda #d16
sta $d016
lda #d18
sta $d018
lda #dd0
sta $dd00
lda #>!irq+
sta $0315
lda #<!irq+
sta $0314
}
.macro endirq() {
pla
tay
pla
tax
pla
rti
}
The "lda #>!irq+" inside the macro is reported as an error and it won't compile. Is there a way I can use the same macro including 0314/0315 "preconfigured" or do I have to set up 0314/0315 as passed parameters aswell? And if I need to pass the variables can I do a:
:interupt(raster4,$1b,$78,$18,$02,#<irqx,#>irqx)?
Or maybee there is even an easier method to the whole thing? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
In each interrupt you refer to the next irq, but the last one can't find the next irq symbol because there are no more irq symbols.
Btw. the idea with irq macros works fine. I do it with pseudocommands (takes mnemonic arguments instead of just values). It looks like this:
:irqStart
.. code ..
:irqEnd #$00 ; #irq2 // D012 value ; next irq
or:
:irqStart_stableRaster
.. code ..
:irqEnd #$00 ; #irq2 // D012 value ; next irq
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Interesting capabilities with this.... I will need to check this out but off on a couple of days travel. I'll check in later if I encounter problems with this :) thanx btw! |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Alright. After testing and playing around this will be the preffered assembler for Creators. You will be credited for this very good assembler.
However a small request:
http://qbnz.com/highlighter/
Would be great to have KickAss syntax included here :-)
-TWW |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
That would be great, but I must say its not on the top of the todo list. Feel free to do one if you like. There are already a KickAssembler highlighting for Ultra Edit on the web. |
| |
LOGAN Account closed
Registered: Aug 2003 Posts: 71 |
I currently use Notepad++ and it doesnt even have generic 6510 assembly support :(
BTW I noticed that kickass has some support for C64DTV but I seen a highlight file somewhere that had a couple more opcodes defined.... hmm cant remember where or what anymore, but was some downloadable highlight file |
| |
pmc Account closed
Registered: Sep 2009 Posts: 5 |
Quote: That would be great, but I must say its not on the top of the todo list. Feel free to do one if you like. There are already a KickAssembler highlighting for Ultra Edit on the web.
Yes there is, available here:
http://eab.abime.net/showthread.php?t=44124&highlight=ultraedit
Made by me in fact ;-) |
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
Just as a side-note, I created a section on Codebase for syntax highlighting files. There is only one file uploaded at the moment (the one just mentioned here), but please add more files, for other editors/assemblers/platforms.
http://codebase64.org/doku.php?id=base:emulation
In order to upload files on codebase, press "edit page", click on the icon that looks like a framed painting, select "sourcecode" in the popup window that appears, select your file (by clicking browse), click on the "upload" button, and when the file is uploaded, click on its name in the list to insert a link to the file on the wiki page. Note that the ".txt" extension is not allowed by the wiki system, so you have to make a ".zip" of it or so. Huh..
//FTC |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
I use Eclipse for all my development including c64 stuff.
I use this plugin: de.fh_zwickau.asmplugin_1.0.1. for asm highlighting. Its not perfect buy its easy to modify the config file. Comments need the semi-colon to make them highlight.
The page for this plugin is down and has been for a while for some reason. If anyone wants it let me know.
Steve
|
| |
pmc Account closed
Registered: Sep 2009 Posts: 5 |
@ Frantic - cool, until I read this I didn't realise my little UltraEdit wordfile for KickAssembler was already famous enough to be on Codebase64 ;-D
Nice one :-) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Conjuror: Im interested. Why don't you upload it to codebase? |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Done http://codebase64.org/doku.php?id=base:emulation
I added some 6502 instructions that I noticed were missing as I was working with it. Probably a lot more missing. See asm_instruction_set.xml
Enjoy!
|
| |
MagerValp
Registered: Dec 2001 Posts: 1055 |
TextMate bundle added to codebase.
|
| |
LOGAN Account closed
Registered: Aug 2003 Posts: 71 |
I hope The assembler list will include more than just the modded Acme. And hopefully more symtax highlighting for other editors (preferably free and open source editors like, erm, notepad++ :D |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Small question regarding syntax;
I do this:
:irqEnd #$32 ; #<irq1 ; #>irq1
.pseudocommand irqEnd d12 ; irqlo ; irqhi {
lda d12
sta $d012
lda irqlo
sta $fffe
lda irqhi
sta $ffff
}
This works fine.
Question is, how would i do a:
:irqEnd #$32 ; irq1
.pseudocommand irqEnd d12 ; irq {
lda d12
sta $d012
lda #<irq
sta $fffe
lda #>irq
sta $ffff
}
So I don't need to pass both the lo- & the hi-byte to the Pseudo?
In other words, How can I splitt up the 'irq' parameter (16 bits adress pointer) into hi & lo-byte pointers wich I can pass to $ffff:$fffe inside a Pseudo? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
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
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Btw. forgot to tell that if you don't like to code that much then use a normal macro:
.macro endIrq(d012Value, irq) {
lda #d012Value
sta $d012
lda #<irq
sta $fffe
lda #>irq
sta $ffff
}
Pseudo commands gives more flexibility (you can use different addressing modes on the same pseudo command), while macros might be easier. However, once you get the idea, pseudocommands are really effective. |
| |
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: 541 |
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: 44 |
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: 44 |
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)
|
| |
neilbaldwin Account closed
Registered: Sep 2009 Posts: 48 |
I think I found a bug but it may be misunderstanding.
If I include a table of values at the end of my (small bit of) code;
.import source "table_of_values.asm"
the origin of the table gets forced to $2000 despite the fact that the .pc hasn't reached anywhere near that in the preceding code.
If I then edit the "table_of_values.asm" file and put;
.pc = *
at the start, it compiles at the right address.
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
i've bugged that bug last day and it was fixed a few hours later. there is a new distribution on the site. version 3.9. |
| |
LOGAN Account closed
Registered: Aug 2003 Posts: 71 |
Thanks Slammer for your continues development of KickAssembler.
I hope people work together to create a macro/function library for KickAss that will be useful for many people.
|
| |
Iapetus/Algarbi/Wood
Registered: Dec 2004 Posts: 71 |
How do I access a label which is inside a pseudopc block from outside?
I am getting: Error: Unknown symbol
Thanx |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Algarbi: Minor error. It is fixed in the new version 3.11 which is now on the website. |
| |
Iapetus/Algarbi/Wood
Registered: Dec 2004 Posts: 71 |
Thanx |
| |
Garvin
Registered: Sep 2009 Posts: 5 |
I've just stared trying out kickass and took some old tasm code converting it and trying to make it follow the kickass syntax for labels and such. Haven't touched any asm in years.
First program was no problems, but the second proved a challenge, since the error wasn't what I'd expect.
Anyways, it seems like line comment screwed me up good.
Ex.
fadeRow: lda fader
-- snip --
beq tasm
rts
tasm: jmp wrap //change to $9000 to get back to tasm
-- snip --
more code
-- snip --
fader: ldx $53
lda $1ac0,x
sta a3+1
Now, I got "Error: Unknown symbol 'fader'".
Removing the comment and the error was gone =)
Btw, commenting out the line fadeRow: compiles to the row before the comment and throws no error. Block comment works fine tho.
This is using version 3.11 |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Edit: deleted..
Could you pm me some code. The actual code would be nice, since I guess you use a label which is nested in another directive or something. |
| |
Garvin
Registered: Sep 2009 Posts: 5 |
Unfortunately I can't reach it, it's on my windoze desktop and not my linux. But I'll see if I'm allowed on the comp when I get back from work^^
The program compiles fine with the line comment removed tho. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
The code in the post assemblers ok (if you insert the missing variables). Eg:
fadeRow: lda fader
beq tasm
rts
tasm: jmp wrap //change to $9000 to get back to tasm
wrap:
fader: ldx $53
lda $1ac0,x
sta a3+1
a3:
I'm planning a new release tonight. If you send me a failing example I'll se if I can include a bugfix. |
| |
Garvin
Registered: Sep 2009 Posts: 5 |
Yeah, something in the full source is probably causing the parser to freak out (it's quite messy, I think I started coding it in a monitor and later reassembled it, judging for certain label names).
I'll try an get you a pm as soon as I get home =) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
From the start of the KickAssembler project people have asked for executable files so you don't have to install Java. Well now we have it, atleast for Windows, with possibility for Linux support, if there is a demand for it. The executable version is up to 3 times faster than the java version. There will ofcause still be distributed a jar-file so all java platforms are supported.
Check out version 3.12 at http://www.theweb.dk/KickAssembler/Main.php |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
It was a while since I tried it, but now I see that you have incorporated mostly everything I missed before, great work!
Linux support would be nice. I suggest you split the binary versions to separate downloads though.
The size of the archive grew from 1 Mbyte to 25 Mbyte, and I think you wouldn't want another 24 Mbytes extra download for each supported platform for all users.
Question:
Is there a way to differentiate between the memory address and the pseudo address for a given label?
(compare to LMA vs. VMA in ELF binaries)
This can of course be done with a fairly simple calculation function but it would be a neat feature.
example:
.pc = $1000
lda #5
sta somewhere.mem+1
:CopyPseudoCodeToTarget()
jsr somewhere // pseudo/VMA which is how it works already.
// Acc = 5
rts
.pseudopc $2000 {
somewhere:
lda #0
rts
}
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
tlr: Right now you can't, but i'll put it on the todo list. |
| |
LOGAN Account closed
Registered: Aug 2003 Posts: 71 |
The only thing I still would like to see is a way to feed it ACME or another assembler based source codes that could be converted on the fly to KickAssembler as a kind of pre-processor pass. This way people could use their old sources without the need to rewrite it.
For example someone using Acme supplies a short routine that's used by someone using KickAss. The source still can be updated by the acme coder and be used seamless in kickassembler.
Anyway would be cool as some translation table as ini files.
(Or able to be implemented as pseudo ops, though remarks using ; would through kickass off. Can't kickass not check somehow if its used as comment or seperator?
off topic:
I almost feel the different assemblers could use their own file extension. For example .tas for turbo assembler, kas for kick assembler, .acm for acme, etc. Is there some standard?
Anyway, keep up the good work, this is my fav assembler. (Hope you have added additional image formats support) |
| |
Mace
Registered: May 2002 Posts: 1799 |
The other day I made some 64TASS code to create sprites for a certain routine I'm working on.
The result was 52 lines of code.
I reworked it in Kick Assembler and it became 5 lines!
It could have been even shorter if there was some possibility to do a pattern fill:
.fill [no. of repeats],[comma separated byte pattern]
(There's a feature request hidden inside this post ;-) ) |
| |
Nitro Account closed
Registered: Aug 2008 Posts: 13 |
I've just tried the executable version hoping to get the speedup, but it worked the other way: it works very slow when there are many files included. Also file handling is different, it looks for files to include in the kickass directory, not the source directory. |
| |
Mace
Registered: May 2002 Posts: 1799 |
I just tried:
.pc = $2000
.for(var x=0; x<64; x++) {
.print x
}
Result:
Made no progress and cant solve the program.. You should have gotten an error. Contact the author!
However, the parsing went okay when I tried:
.pc = $2000
lda #$01
sta $d020
rts
What's wrong?
[edit]
I tried V2.25 and that one worked okay.
So the problem is in V3.12 (both Java and executable). |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Mace:
If you want to fill patterns you can do it like this:
.fill $100, List().add($fe,$82,$82,$82,$82,$82,$fe,$00).get(mod(i,8))
There was a minor error in the progress detection in the for loop, if you have a program that assembles in one pass with a forloop the error will occur. I have fixed the problem and there will be a v3.13 out later this weekend.
Nitro:
I haven't noticed that about the speed (but I tend to use the java version). I will check out file problem - the java-compiler has some differences in this area. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Quote:.fill $100, List().add($fe,$82,$82,$82,$82,$82,$fe,$00).get(mod(i,8)) This is so cool :-)
I will see how to modify this into what I need.
Thanks! |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
The site can't be updated right now, so I uploaded the new release to CSDB.
** It also seems that my email is dead, so pm me here on CSDB instead (The feedback on the site, and the kickass@theweb.dk address won't work) **
Nitro: I fixed the dir bug, however because of the filesize of the executable I can't upload it to csdb. About execution times, I noticed that it takes some time to load the first time you run KickAss.exe, but then it gets faster (probably some libraries have to be loaded or something). Have you tried to time it with the -time option? If the performance seems much worse let me know. |
| |
Nitro Account closed
Registered: Aug 2008 Posts: 13 |
I wasn't talking about the executable load time but assemble time, the differences are huge :)
EXE: Assemble time = 9168 ms
JAR: Assemble time = 2010 ms
I'm including about 33 files, 4,85kb each. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Haha, and then ppl say JAVA is slow! |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Ok, I wasn't aware of this. I can only recomend using the java version then. I might tweak the compiler to produce faster code, but my hopes are not high (Perhaps they forgot to buffer the input in the load library) |
| |
Mace
Registered: May 2002 Posts: 1799 |
Copied from "What assembler/compiler are you using?"
Quoting SlammerWhats your favorite feature of the assembler you are using? What feature really helps you? (...)
The main reason why I switched from 64TASS to KickAss is because of the List() directive, math functions like sin() so I don't need a sinus generator anymore.
Namespacing and scoping look useful too, but have had no need for them yet.
What I like less about KickAss compared to 64TASS is the import of binaries. In 64TASS it's a matter of .binary "file",offset,length and it's in the memory.
No need to do .fill stuff and such. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Mace: Have you tried
.import binary Music.bin or
.import c64 "prog.c64"
I'll se if I can add an optional offset and length parameter in a later version. (until then you can always write a macro (.macro importFile(filename,offset, length) {..})
Btw. The favorite feature question is intended for all assemblers. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Of course I tried .import, but it's not the same since it fetches the entire file and not just a part of it.
What I use the offset and length for is for importing parts of externally created data, like graphics. |
| |
Digger
Registered: Mar 2005 Posts: 421 |
Slammer, I am getting a weird error after first pass:
Memory Map
----------
WARNING! No data in memory!
What's that about? I've searched the manual but no info there.
Thanks!
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
You have assembled a program that contains no bytes. Eg. if you assemble
.for(var i=0; i<10; i++)
.print "i="+i
you will get the 'WARNING! No data in memory!'. The first two lines is the memory map which is empty. |
| |
Iapetus/Algarbi/Wood
Registered: Dec 2004 Posts: 71 |
I am getting a problem when I use //, the compiler can't find lables after the use of //
For instance:
lda #$00
sta pintaTileX+1
pintaTileY: lda #$00 // y coord
.
.
.
pintaTileX: lda #$00
Error: Unknown symbol 'pintaTileX'
If I change the first line containing // to:
pintaTileY: lda #$00 /* y coord */
it works
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
If you use an editor that uses nonstandard codes for lineshift the linecomment won't be terminated.
Try using a different editor and examine the file with an hexeditor. |
| |
Iapetus/Algarbi/Wood
Registered: Dec 2004 Posts: 71 |
I have been using scite for ages and never had problems. I clicked on "convert line end characters" under Options and it worked.
Thank you |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi, My internet provider has been really unstable. This means that if you have given feedback in the form on the Kick Assembler website or written to mailaddress given in the manual the past one and and a half month I haven't recieved your mail.
It should be working now, so if you havn't recieved an answer -> write again. Sorry for the inconvenience. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
i just tried to post a few bugs again and the same error.
here are 2 bugs i've found tho,
1. Script
when using a Hashtable like this, .var pixelTable = Hashtable() and then using it in a loop generates this:
parsing
flex pass 1
.if (pixelTable.get(key) != null)
^
Error: Unknown function : !=
2. Reading bytes from binary files
when loading binary files like this, .var dataFile = LoadBinary("data\hiresvector\lightwave.obj")
and then reading it byte by byte using vectorFile.get(i) gives back random signs of the byte. it can be solved by doing vectorFile.get(i) & 255 so it seems kickasm is reading 32 bits and gives back 8 without clearing the other 24 bits or something.
-Pantaloon
|
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: i just tried to post a few bugs again and the same error.
here are 2 bugs i've found tho,
1. Script
when using a Hashtable like this, .var pixelTable = Hashtable() and then using it in a loop generates this:
parsing
flex pass 1
.if (pixelTable.get(key) != null)
^
Error: Unknown function : !=
2. Reading bytes from binary files
when loading binary files like this, .var dataFile = LoadBinary("data\hiresvector\lightwave.obj")
and then reading it byte by byte using vectorFile.get(i) gives back random signs of the byte. it can be solved by doing vectorFile.get(i) & 255 so it seems kickasm is reading 32 bits and gives back 8 without clearing the other 24 bits or something.
-Pantaloon
Due to Java's lack of unsigned data types a byte read from a file is always signed. When converted to an int, it's properly sign extended, and as you say, to read unsigned in Java one has to convert the byte into a larger data type, say short or int, then mask the lower 8 bits via the "and 0xff".
Would ofcourse be nice if KickAss did that for you, or assume unsigned always and add some .getSigned(i) or even .get<DataType>(i). |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Jackasser is right. Javas byte primitive is signed and ranges from -128 to 127. I will se if I can make you an unsigned getter.
The != function should be defined for the most common object types. What objects have you stored in the table?
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
the hashtable entries contains a List that contains structs that are defined like this: .struct Pixel {addr,mask} |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Ok, Here is a workaround. List hasn't got the != function right now. So use null!=pixelTable.get(key) which will call the != function on the null object instead. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
thx :) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Observe the folowing:
//------------------------------------------------------------------------ -------------------------------------------
//-Routine for pulling $d800 Collors.
//------------------------------------------------------------------------------ -------------------------------------
.pc = * "Collor Puller Routine"
.label coll1 = CollPull
.label coll2 = CollPull+235
.label coll3 = CollPull+235*2
.label coll4 = CollPull+235*3
.label coll5 = CollPull+235*4
.label coll6 = CollPull+235*5
.label coll7 = CollPull+235*6
.label coll8 = CollPull+235*7
.label coll9 = CollPull+235*8
.label coll10 = CollPull+235*9
.label coll11 = CollPull+235*10
.label coll12 = CollPull+235*11
.label coll13 = CollPull+235*12
.label coll14 = CollPull+235*13
.label coll15 = CollPull+235*14
.label coll16 = CollPull+235*15
.label coll17 = CollPull+235*16
.label coll18 = CollPull+235*17
.label coll19 = CollPull+235*18
.label coll20 = CollPull+235*19
.label coll21 = CollPull+235*20
.label coll22 = CollPull+235*21
.label coll23 = CollPull+235*22
.label coll24 = CollPull+235*23
.label coll25 = CollPull+235*24
CollPull:
.for (y=0;y<25;y++) {
.for (x=0;x<39;x++) {
lda $d801+x+[y*40]
sta $d800+x+[y*40]
}
rts
}
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
This allowes me to jsr collN for any of the 25 lines i need. My question is; Is there some more fancysmancy way of handling the labels in this case (Include it in the loop f.ex) something like this:
.for (y=0;y<25;y++) {
.label "coll"+toIntString(y+1)
.for (x=0;x<39;x++) {
lda $d801+x+[y*40]
sta $d800+x+[y*40]
}
rts
}
and then be able to jsr coll5 f.ex. outside the scope?
If not can I use the .label in conjunction with list() to generate the label list? |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
fancymansy way in graham ass (took 5 minutes):
*= $1000
x = $f0
y = $f1
speedcode = $4000
labelslo = $c000
labelshi = $c028
sei
jsr makespeed
ldx column
lda labelslo,x
sta self+1
lda labelshi,x
sta self+2
self jsr speedcode
jmp *
makespeed
lda #0
sta x
sta y
lda #<speedcode
sta $fc
lda #>speedcode
sta $fd
loop2
ldx x
lda $fc
sta labelslo,x
lda $fd
sta labelshi,x
loop1
lda y
asl
tay
lda mul40,y
clc
adc x
sta $fa
lda mul40+1,y
adc #>$d800
sta $fb
ldy #$00 ;lda $d801
lda c0
sta ($fc),y
iny
lda $fa
clc
adc #$01
sta ($fc),y
iny
lda $fb
adc #$00
sta ($fc),y
iny
lda c1 ;sta $d800
sta ($fc),y
iny
lda $fa
sta ($fc),y
iny
lda $fb
sta ($fc),y
iny
tya
clc
adc $fc
sta $fc
bcc *+4
inc $fd
inc y
lda y
cmp #25
bne loop1
ldy #$00
lda #$60
sta ($fc),y ; rts
inc $fc
bne *+4
inc $fd
lda #0
sta y
inc x
lda x
cmp #40
bne loop2
rts
c0 lda $d800
c1 sta $d800
mul40 .word 0,40,80,120,160,200,240,280,320,360,400,440,480,520,560,600,640,680,720,760,800, 840,880,920,960 |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
.pc = * "Collor Puller Routine" CollPull:
.var l = List()
.for (y=0;y<25;y++)
{
.eval l = l.add(*)
.for (x=0;x<39;x++)
{
lda $d801+x+[y*40]
sta $d800+x+[y*40]
}
rts
}
lotable:
.fill l.size(), <l.get(i)
hitable:
.fill l.size(), >l.get(i)
and use like this
// y contains the row
ldy #$00
lda lotable,y
sta jsra+1
lda hitable,y
sta jsra+2
jsra: jsr $0000
or from script
jsr l.get(0)
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
Slammer:
Would it be possible to add a new script command in kickasm, something like this:
.var data = .system "myprog.exe " + cmdlineString
so it's possible to call an external program while kickasm is doing the scriptjob ? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Yep, absolutely. One of the long term goals of creating v3 was making an architecture that made things like this possible. However, im a bit busy at the moment so don't expect it soon.
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Oswald/Pantalon:
I was thinking more in the lines of modifications of labels inside scopes / loops. Not Self Modifying speedcode or lookup-tables.
So to rephrase;
can I do something like:
.for (y=0;y<5;y++) {
.label mylabel+toIntString(y)
//Do something
}
and get the assembler to generate 5 labels (mylabel1 to mylabel 5) for my 5 Do something routines? |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
well, thats now how kickassembler works, just store the programCounter in a list and use it that way, its the same as working with labels just a different syntax really. instead of doing something mylabel you do something mylabels(labelindex). |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Alright I see now.
Thanx.
-TWW |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
Slammer:
can you add something like .ifdefined(myvar) , it would be very useful to check if a variable has been declared when using alot of small source files.
and i found a bug, if you use the .import directive inside an if statement it doesnt compile.
ie.
.if (LINK == true)
{
.import source "MySourceFile.s"
}
-P |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Some kind of ifdefined is already on the todo-list - I'll prioritize it a bit higher.
Right now the development is on a hold i'm afraid. I have to replace my old development computer.
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
nice!, hope you get a new computer soon :) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
I know even before posting that this question will sound weird but here goes;
Can I create a macro/pseudocommand which will compile differently depending on arguments passed?
f.ex.
ex #1:
A routine changes the code it produces based on arguments passed. Like a multiply routine which choosed 8 bit or 16 bit multiply depending on which arguments the macro/pseudo is called with.
ex #2:
A joystick routine called with port as a parameter simply returns the joystick status in A or something BUT if an aditional parameter like acceleration is passed the routine "changes" into different produced code which handles acceleration this aswell (somehow^^)...
TWW/Creators |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Yes you can. Use the if command or modify arguments to change the behavior. Here are a couple of examples from my own library (increasing complexity).
Example 1. I got two versions of a move macro, one that is fast and a general one for moving a lot of data. Dependent of the number of bytes to be moved i select one of the two:
.macro Move(source, target, size) {
.if (size <= $1000) :FastMove(source,target,size)
else :GeneralMove(source,target,size)
}
.macro FastMove(source, target, size) {
..
}
.macro GeneralMove(source, target, size) {
...
}
Example 2. I got a 8/16 bit library that gives me amiga/pc like pseudo commands. Below is an example of an 8 bit adc command. You con give it 3 arguments it adds the first two and place the result in the third argument (eg: :add #3 ; table1,x ; result). But you can also leave out the third argument and then the result is placed in the second (eg: :add #3 ; score)
.pseudocommand adc arg1;arg2;tar {
.if (tar.getType()==AT_NONE) .eval tar=arg2
lda arg2
adc arg1
sta tar
}
Example 3. Now lets take the 16bit version of the adc command which is a bit harder since the highbyte of each argument should be treated different dependent on the mode of the arguments (absolute, immediate, zeropage, etc). Eg if you have an immediate argument like #$1234 the the lowbyte is 34 and the highbyte is 12, but if you have an absolute like $1000 then the lowbyte is in $1000 and the highbyte is in $1001. To take care of this we define a nextArguent function and use it as show below.
.pseudocommand adc16 arg1 ; arg2 ; tar {
.if (tar.getType()==AT_NONE) .eval tar=arg2
lda arg2
adc arg1
sta tar
lda _16bit_nextArgument(arg2)
adc _16bit_nextArgument(arg1)
sta _16bit_nextArgument(tar)
}
.function _16bit_nextArgument(arg) {
.if (arg.getType()==AT_IMMEDIATE) .return CmdArgument(arg.getType(),>arg.getValue())
.return CmdArgument(arg.getType(),arg.getValue()+1)
}
// the above macro is use like this:
:add16 #$2800 ; $1000
:add16 screen ; offset ; zpPointer
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Awesome.
Seriously, Thanx for such a cool tool!
TWW/Creators |
| |
Mace
Registered: May 2002 Posts: 1799 |
Hmm, 'nested' macros... interesting and simple, yet I never thought of it :-) |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
i found a bug:
.const LINK = false
begin:
.if (LINK == false)
{
.import c64 "\datapata\myfile.prg"
}
end:
.print end - begin
the print won't work, it will output the address at begin:
if i remove .if () it works.
-P |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I will have a look at it.. Right now im on vacation in Austria - will be home on monday. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
Feature request:
a method to generate a random unique list, ie:
.var randomNumbers = randomUniqueList(numberOfElements)
the randomUniqueList would give you back a list of values
between 0 and numberOfElements, no number should me mapped twice in the list.
Generating this kind of list using the built in Hashtable takes forever today.
Edit:
i found out doing this,
.var random_table = Hashtable()
.for (var i = 0; i < 12*40; i++ )
{
.eval random_table.put(i,i)
}
would generate a somewhat unique list because of the nature of the hashtable, but still its not random.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Why dont you use the random function? Quick Pseudocode:
for (;hashtable.getKeys().getsize()< noOfDesiredElements;) {
.var randomNo = random()
.eval hashtable.put(randomNo, randomNo)
}
Nb. Since we dont have a while statement (yet) I use the for statement as a while |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
i found a better way,
shuffle() that can be done on lists :)
|
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: i found a better way,
shuffle() that can be done on lists :)
@Slammer: Collections.shuffle(List<?> list); *hint* *hint* and while you're at it, Collections.sort(List<?> list); :D Heck, .reverse is useful too!
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
JackAsser: Shuffle is already implemented. Sort and Reverse are, as you said, pretty easy to implement so they will be in the next release.. (reverse is implemented by just one extra line of code *S*) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I posted some examples of pseudo commands on codebase64.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
There is a new release on the site.
This is a one time notice, normally you will have to check the website yourself, however the site have been kind of unstable lately. It's now moved to a new host - hopefully this will help. |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
Hi! Is there any way to tell kickassembler to repeat a instruction x times?
for example, turning this:
nop
nop
nop
nop
into something like:
:nop (4)
That'll be great to follow better the .asm listings.
I think I have read that somewhere but I am unable to find that again.
Thanks!
|
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
RTFM |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I think you are refering to the repetition commands in the pseudocommand tutorial on codebase64.
You can find it here
(Oswald: No, it's actually not in the manual) |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
so it is a macro that must be defined. Ok, that's good, I thought that was a fact of the assembler, and I've read the manual lots of times lol
Now I can remember reading that exact tip from you, in the codebase :D thanks Slammer.
|
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
then "read 2 posts above your own one" :P :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
With functions, macros and pseudo-commands you can get KickAssembler to do a lot of fancy stuff. I suggest that everytime you find something you like you copy-paste it into your own library.
Here is a little trick. If you wan't the repetition commands to be an integrated part of KickAssembler you can copy-paste them into the resources/autoinclude.asm file that is placed inside the jar file. (To view the content of a jar just rename it to a zip-file)
Oswald: Yep |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
yeah I did that with the .import source "macrolib.asm" directive
It's nice to know the "trick" you said to include it as standard.
very handy :)
haha :D @oswald
:nop #2
jmp *-2
|
| |
Mace
Registered: May 2002 Posts: 1799 |
Quoting SlammerThere is a new release on the site.
Seems that toIntString() is borked now.
Or is it .text toIntString()?
Because that returns odd results!
So :BasicUpstart() doesn't work either: de number after SYS is all nonsense. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
OK, I will look into it tonight
When did you download? |
| |
Mace
Registered: May 2002 Posts: 1799 |
I downloaded today, just minutes before that post.
[edit]
While you're at it, I've got another question.
I have declared to pseudocommands, GoDebug and DebugRoutine.
// ========================================================
.var DebugOn = 0
.pseudocommand GoDebug {
jsr SUB_Debug
.var DebugOn = 1 }
.pseudocommand DebugRoutine {
// some routine to show debug info
}
/* code here */
:GoDebug
/* more code */
/* at the end of all code */
SUB_Debug
.if (DebugOn == 1) :DebugRoutine
// ========================================================
The idea is that if :GoDebug is called (and not commented out), the :DebugRoutine will be added to the code.
If :GoDebug isn't called, there will be no code following the SUB_Debug label.
This, however, doesn't work, because the if-statement doesn't see DebugOn as 1 even if :GoDebug is called.
What could be a solution for this problem?
How weird... it suddenly works, without changing anything, just by compiling it again?! |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
It doesnt work because you declare several DebugOn variables. When you write:
.var x=0 you declare the variable x. If you write
.var x=0
.var x=0 // This gives an error You will get an error for redefining x since you cant have two variables with the same name. In you example you don't get an error because you are redefining the variable inside a scope:
.var x=0
{var x=1} // This declares another x variable inside a scope So what you really want to do is to modify you existing variable not declare a new one. This is done with the eval command:
.var x=0
.eval x=1
Edit: Saw you fixed the problem. Still guess you should check the .var command.. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Ok, fixed the problem with the .text issue. Since the problem only existed from this morning and until now, there will be no new release number.
I happend to change the java source format to UTF-8 thinking 'That doesn't make any difference for the final code' and then some speedtest on the new ftp site by timing the uploading - Well, it turns out it did matter. Sorry for the inconvinience. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
Question:
is there any way i can transform a char from a string to a numeric ascii value ?
asNumber obviously doesn't work.
ie.
.macro mymacro(str)
{
for (var i = 0; i < str.size(); i++)
{
.var asciivalue = ASCIIVALUE(str.charAt(i))
}
}
|
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Knowing that Kick-Ass internally uses ISO-8859-1 and that the scripts seems quite close to java perhaps something like this would work:
.var asciivalue = s.charAt(i)+0;
But I dunno ofcuorse... :) |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
JackAsser's solution almost works, except the 0 has to be prefixed:
.var asciivalue = 0 + s.charAt(i) |
| |
Mace
Registered: May 2002 Posts: 1799 |
@ Pantaloon: RTFM, especially paragraph 4.7.
Your question is answered there in full detail and it's much easier than you think. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
GREAT! |
| |
Mace
Registered: May 2002 Posts: 1799 |
I'd like to do a LoadBinary and redistribute the bytes into the memory in another way than in the original file.
Byte 1 @ $x000
Byte 2 @ $x040
Byte 3 @ $x080
Byte 4 @ $x0c0
.
.
.
Byte 9 @ $x001
Byte 10@ $x041
.
.
.
Byte 17@ $x002 etc.
In other words: byte 1 + n*8 in order, byte 2 + n*8 etc.
My solution now is:
.var theData = LoadBinary "data.prg"
.for (var TelA=0; TelA<8; TelA++) {
.pc = NewData + TelA*64
.for (var TelB=0; TelB<64; TelB=TelB) {
.byte theData.get(TelA + [TelB*8])
}
}
Is there a quicker way to do this?
Like, with some nifty scripty thingy? |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Something like this?
.fill theData.size(), theData.get(mod(i,8)*$40 + floor(i/8))
|
| |
Mace
Registered: May 2002 Posts: 1799 |
Exactly! \o/
Thanks, I knew it was possible, but those floor and mod always seem to slip my mind...
|
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
Hi! I am coding a nice (double Y) text scroller. It repeats infinitely starting from the start, over an over again.
Lately I had implemented a SID file (from the HSVC) with the Loadsid function of Kickass, and it works cool... but when the SID comes to silence, it doesn't repeat again.
I'll put a "jsr music.init" as soon as someone tells me how to detect that a song has ended playing. Thanks a lot.
|
| |
Mace
Registered: May 2002 Posts: 1799 |
Do some SID hacking, find the register that shows the song has ended.
Or find the editor in which the SID is made and change the end into a loop.
Of use a SID that loops. |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
thanks mace, I was asking here to avoid doing things like that, wondering if kickass has an easier or comfortable way to know the end of the sid. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Guess there is a little misunderstanding. KickAssebler just helps you read the sid file format. Inside is the musicdata and a player, so when you do jsr music.init / jsr music.play you call the init routine and player thats stored in that particular sidfile.
KickAssembler has nothing to do with how the player works, so if you do some SidHacking, you have to do it each time you change sid.
|
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
The brute force no-brain way would be to just increase a counter each time the player is called, and then find out which value that actually corresponds to the end of the song, without looking inside the tune at all... Not necessarily that much of a hassle, and may not have take more time than peeking into the player flow anyway. |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
@Slammer: much clearer. I thought so. Just wondering what if there was something that escaped me in this regard.
an excellent idea, Frantic. I was thinking about a timer too.
I'll try it. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Frantic: With Warpmode your approach might be the fastest way. |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
hi!
strings are not working with .import directive...
I am trying to do:
.var workpath="c:\kickass\Retroinvaders\"
.import source workpath+"include\macroslib.asm"
.import source workpath+"include\16bitcmds.asm"
.import source workpath+"include\graphics.asm"
and I have the following error:
Error: Unknown symbol 'workpath'
It will be cool if this little detail is corrected as a little improvement to kickass. Or maybe, I am doing something wrong? Thanks in advance!
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi Lobogris,
It not an error. The import directive is executed in a preparse so functions, macros and pseudo commands are imported and ready to use anywhere in your sourcecode.
Try using the -libdir parameter instead. Something like:
java -jar KickAss.jar -libdir "c:\kickass\Retroinvaders\" source.asm
You can have as many libdir's as you like. Now, everytime you import stuff, the assembler will look in the libdirs if it cant find the file in the current dir. So now you just do: .import source "include\macroslib.asm"
.import source "include\16bitcmds.asm"
.import source "include\graphics.asm" |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
Thats good. Many thanks! I have -libdir now added in kickass.cfg file
One last question, if I wanna add more paths to -libdir it will work separating it with ";"? or maybe ","?
for example:
-libdir "C:\kickass\Retroinvaders\;c:\mainlibs\"
|
| |
bepp
Registered: Jun 2010 Posts: 263 |
You can specify the -libdir parameter multiple times on the command line. See top of page 14 in the manual. |
| |
Lobogris
Registered: Oct 2010 Posts: 22 |
It was more a curiosity for future projects, so I looked quickly the manual (I have my head full of algorithms right now!) I need to print the manual because in pdf I miss some parts sometimes! sorry for that, and thanks bepp! |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Cheers
Is the a way to reliable determine the size of a immediate value (8/16/32 bit)?
I'm guessing that you can fetch the arg.getvalue+1 / +2 etc and check if they are zero but maybee there is a even more slick method?
-TWW |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Im not sure exactly what you want, but you can write a bytesize function like this:
//Examples of use
.print "$12->"+byteSize($12)
.print "$123->"+byteSize($123)
.print "$123456->"+byteSize($123456)
// The function
.function byteSize(x) {
.if (x==0) .return 0
.return 1+byteSize(x>>8)
} |
| |
TWW
Registered: Jul 2009 Posts: 541 |
I was thinking (yeah I do that sometimes too) that I could construct "universal" pseudocommands for example:
:ADD x ; y ; z
and then get the pseudo to determine if it needs to utilize 8, 16, 24 or 'n' bits addition.
That is instead of making multiple pseudos like :ADD8 / :ADD16 f.ex.
Making a function like the one you made here returning the number of bytes in a passed argument looks to be a step in the right direction 8-) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
That would be nice to have. I think there is a problem though. The destination will be a memory adress and we have to know if the data on that adress is 8 bit or 16 bit. If you want to do:add #1 ; label Then the value 1 can be contained in one byte (byteSize=1) but if 'label' is pointing to a 16 bit number you still have to make and adc to both the low and the high-byte in order to handle the carryflag when the lowbyte makes an overflow.
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
I see your point.
However I have another issue:
.pseudocommand MEMFILL destination_address ; number_of_bytes ; value {
.if (number_of_bytes.getValue()<=5) {
"DO THE FIRST THING"
}
.if (number_of_bytes.getValue()>5 && number_of_bytes.getValue()<=256) {
"DO THE SECOND THING"
}
.if (number_of_bytes.getValue()>256) {
"DO THE THIRD THING"
}
}
After i put in the doube boolean check on the second thing I get a message: "Made no progress and cant solve the program.. You should have gotten an error. Contact the author!"
If I change the 2nd entry to a single boolean check (i.e. more then 5 f.ex.) it works like a charm.
Any suggestions? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Update to Kick Assembler v3.15. If you are already running on v3.15 then you have found a bug. Send me a piece of failing code and I will se what I can do about it.
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
There you go! Ask Slammer and it's good to go. Should have checked latest version myself before posting (smacks forehead). Somehow I imagined I 'had' the latest version... Time to cut down on the jack&cokes^^
Edit: I saw Pantaloon requested a ".ifdefined" function for determining if a variable have been defined earlier. I could not find anything regarding this in you updates page (or the manual(I admit though I only browsed it lightly^^)) so I guess what I'm asking is: Is it still on your to_do list? 8-D |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
It's not forgotten, but dont expect it soon. These days im a bit busy with other projects (like work).. |
| |
Digger
Registered: Mar 2005 Posts: 421 |
Guys, I am trying to split my source into logical parts using import source "file.asm"
How to define global variables in the main.asm (so that other imported files have access to them) other way than having a globals.asm file that gets imported into every linked .asm file?
Can I use namespaces for that?
Cheers big ears.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
My guess is that you do like this:
-----------main.asm---------------
.import source "file1.asm"
.import source "file2.asm"
.var myNumber=42
-----------file1.asm---------------
lda #myNumber
This will not work since the variable is declared after file1.asm is included, so the variable is used before it is declared.
There are two solutions:
1. Define your vars before the import statements
2. Define your vars as labels (this will cost you an extra pass when assembling since the value first will be ready in pass two, but you probably don't care about this)
The following should work:-----------main.asm---------------
.import source "file1.asm"
.import source "file2.asm"
.label myNumber=42
-----------file1.asm---------------
lda #myNumber |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Or import globals.asm as the first file in main.asm, that way it doesn't need to be imported into all the other files. |
| |
Mace
Registered: May 2002 Posts: 1799 |
There is no way to incorporate binary data as ASCII in the source with KickAss, is there?
Something like BASE64? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
You can write a decode macro that does it. Something like:
.var base64Str = "sfkjfsjdfisjhfijsifjsdkjfskdjf";
:Base64Decode(base64Str)
.marcro Base64Decode(str) {
// for all chars in str look up value in decode table and make a .byte directive to output the data
} I'm curious, how is this useful? |
| |
Mace
Registered: May 2002 Posts: 1799 |
So I could post on forums a source that includes binary data, without having to type all bytes with .byte. :-)
It's not that I really NEED it, but I was just wondering. |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
I have a question about scoping. Is there anyway to access variables within a scope block, such as:
lda #$03
sta scroller.rowCount + 1
scroller: {
rowCount:
ldx #$03
...
rts
}
note: example only
Otherwise I'd have to expose the entire 'function' and its labels/variables to the rest of the program. Yes I am a JAVA programmer :D
Steve |
| |
Mace
Registered: May 2002 Posts: 1799 |
@ Conjuror: yes, check pages 18 and 34 of the manual.
Also, you could place your label inside the scope better, so that it points to the address itself instead of having to do calculations outside the scope. |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Thanks Mace, thats just embarrassing. I was very tired today. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
As Mace said, it is supported. Another example of 'auto namespacing' is when you put a label before a macro execution. This will enable you to access the labels inside the macro which is quite useful. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Quote:Another example of 'auto namespacing' is when you put a label before a macro execution. Blimey, I needed that! Thanks :-) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Alright, here is a question;
I have a .BMP logo which takes more then 2K (Larger then a char bank). The gfx only uses 3 collors + background.
Traditionally I would do the conversion from koala to char-screen in my own C64 native converter.
What I do on is to take 4x8 Multicollor Pixels and compare they 1 by 1 as I go along and "reuse" any duplicate "char-blocks" to conserve memory and allow fullscreen char-gfx using only 1 char-bank. At the same time the routine also produces the character-set map which is needed to display the gfx.
I reckon a simmular aproach is needed for this in Kickasseblers aswell and hope someone can point me in the right direction on how to aproach this?
I am thinking LoadPicture function with some PC-memory buffer used to sort out the data before filling the c-64 memory...
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
@tww: I'd use a hash table indexed by the char contents somehow. If 64-bit variables are allowed use that, otherwise just create the index by concatenating toHexString(<byte>) of all the char bytes. Make the hash entry contain a number indicating which char value it corresponds to.
When you match a char in the hash, just pick that number as char value. Keep the char mem in a list. When all is done, output the contents of the hash and the char mem using .fill or similar.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
It is possible to do big conversions in Kick Assembler (See Cruzer pictureconverter on codebase64) and tlr got a point in using strings and hashtables for fast char-matching - The search process might be time critical since it is a script language.
If you are in the right mood for coding then go for the Tlr approach, if you want an easier way you can start by searching CSDb to see if someone else have done an 'other platform tool' for charpacking which can save you some time.
Tlr : all numeric values are treated as doubles and I guess you want to use a 64-bit integer.
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
I actually made an equal char packer using a hash table recently. It packs a 320x200 hires pic, but it should be easy to change it to multicolor and extend the size...
.macro equalCharPack(filename, screenAdr, charsetAdr) {
.var charMap = Hashtable()
.var charNo = 0
.var screenData = List()
.var charsetData = List()
.var pic = LoadPicture(filename)
.for (var charY=0; charY<25; charY++) {
.for (var charX=0; charX<40; charX++) {
.var currentCharBytes = List()
.var key = ""
.for (var i=0; i<8; i++) {
.var byteVal = pic.getSinglecolorByte(charX, charY*8 + i)
.eval key = key + toHexString(byteVal) + ","
.eval currentCharBytes.add(byteVal)
}
.var currentChar = charMap.get(key)
.if (currentChar == null) {
.eval currentChar = charNo
.eval charMap.put(key, charNo)
.eval charNo++
.for (var i=0; i<8; i++) {
.eval charsetData.add(currentCharBytes.get(i))
}
}
.eval screenData.add(currentChar)
}
}
.pc = screenAdr "screen"
.fill screenData.size(), screenData.get(i)
.pc = charsetAdr "charset"
.fill charsetData.size(), charsetData.get(i)
}
:equalCharPack("pic.png", $2800, $2000)
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Nice one.. Btw. There is an error directive so you can fail if the number of chars exceeds 256. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Awesome!
A small patch to fix the size issue:
// Graphics should fit in 8x8 Single collor / 4 x 8 Multi collor blocks
.var PictureSizeX = pic.width/8
.var PictureSizeY = pic.height/8
.for (var charY=0; charY<PictureSizeY; charY++) {
.for (var charX=0; charX<PictureSizeX; charX++) {
And perhaps letting the gfx-mode (SC/MC) being passed as a argument to the Macro and we've got ourselves a fricking hot converter here.
Perhaps the RGB collors can be passed as an argument aswell so one can keep track of which collor goes to which bit-combination... Goddam! |
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
I added the script to codebase (including TWW's addition). If you make further additions/improvements to this script, don't hesitate to modify the codebase version too! It is here:
http://www.codebase64.org/doku.php?id=base:kick_assembler_macro.. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
Here are some code to find the closest c-64 color index from an RGB value, usefull when doing image conversion.
there are ofcourse better ways to find the best match but this works ok if you have images with c-64 colors allready.
i use it for my kickasm image converters, can convert sprites / hires / multicolor etc.
.struct RGB {r,g,b}
.var s_palette = List().add(
RGB(0,0,0), // black 0
RGB(255,255,255), // white 1
RGB(104,55,43), // red 2
RGB(131,240,220), // cyan 3
RGB(111,61,134), // purple 4
RGB(89,205,54), // green 5
RGB(65,55,205), // blue 6
RGB(184,199,111), // yellow 7
RGB(209,127,48), // orange 8
RGB(67,57,0), // brown 9
RGB(154,103,89), // light_red 10
RGB(91,91,91), // dark_gray 11
RGB(142,142,142), // gray 12
RGB(157,255,157), // light_green 13
RGB(117,161,236), // light_blue 14
RGB(193,193,193) // light_gray 15
);
.function colorDistance(c1,c2)
{
.var cr = c1.r-c2.r
.var cg = c1.g-c2.g
.var cb = c1.b-c2.b
.return sqrt([cr*cr] + [cg*cg] + [cb*cb])
}
.function getClosestColorIndex(rgb)
{
.return getClosestColorIndex(
rgb, s_palette
)
}
.function getClosestColorIndex(rgb, palette)
{
.var distance = colorDistance(rgb, palette.get(0))
.var closestColorIndex = 0
.for (var index = 1; index < palette.size(); index++)
{
.var d = colorDistance(rgb, palette.get(index))
.if (d < distance)
{
.eval distance = d
.eval closestColorIndex = index
}
}
.return closestColorIndex
}
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Pantaloon: Nice! My approach is usually to add an extra line to the gfx with the palette, and load them from there to avoid having to type them in manually. But this would be even easier, if it works with all the different colorschemes around. |
| |
MagerValp
Registered: Dec 2001 Posts: 1055 |
Quote: Pantaloon: Nice! My approach is usually to add an extra line to the gfx with the palette, and load them from there to avoid having to type them in manually. But this would be even easier, if it works with all the different colorschemes around.
...or just save the image as a 16 color PNG or BMP and ignore the RGB values altogether. |
| |
algorithm
Registered: May 2002 Posts: 702 |
Quote: Nice one.. Btw. There is an error directive so you can fail if the number of chars exceeds 256.
The below tool can be used to pack a full screen image (or many images) to 256 chars. non-lossy if there are less than 256 unique 8x8 blocks. Lossy if more.
CSAM V3
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Maybe this has been discussed before but:
If I do this...
.const str = "TESTING"
text:
.fill str.size(), str.charAt(i) & $3f ...or this...
.const str = "TESTING"
.function to_scr(c) {
.return c & $3f
}
text:
.fill str.size(), to_scr(str.charAt(i)) ... Kick Assembler 3.18 fails to recognize the '&' operator.
however this works:
.const str = "TESTING"
text:
.fill str.size(), $3f & str.charAt(i)
My guess that this is a problem with implicit casting of chars, no?
It took a while to figure out. I'd prefer if both ways of ordering worked or if it was at least documented... ;) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Good question.
Kick Assembler works with objects, just like object oriented languages like C++, C# and java. Each class of objects has
assigned a set of functions and operators. Eg. a String object has a charAt function, but the number function hasn't.
The & operator is placed on the number object and not on the char object (See documentation).
When you write:.var a = 'x' & 1 The & operator is called on the char object. But it isn't defined so you will get an error.
But this work: .var b = 1 & 'x' The & operator is called on the number object which cast the char object parameter to a number value and performs the and operation.
Guess it would be nice if we could explicitly typecast objects - That will probably be in the next release. Until then you can make a dirty typecast to convert chars into numbers like this: .var a = [0+'x'] & 1
EDIT: So yes, it is a issue of casting cos how should the assembler know that we meant the & operator on the number object and the perform the cast to a number? Theoretically, we could have defined an & operator on the String value that appended two strings - should we then implicitly cast to a number or to a string (or to a third value). So the assembler cant decide this and gives an error.
|
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
@Slammer: The simple solution would be (as in Java) to treat chars as a kind of number, hence the &-operator would exist on char-objects aswell. I.e. simply allow the &-operator on char-objects. Or let char-class be a subclass of the more general number-class.
Regarding &-operator on strings to concatenate => fine, since string != char. "foo"&"bar" == "foobar" vs 'x'&'y' == 0xSomething. Right? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Making the char class a subclass of the number class is absolutly a possibility. Im a bit defensive about these things since its easy to implement features with unwanted side effects you cant get rid of cos of backward compatibility.
In java 'o'+'k'=218 but 'o'+'k'="ok" seems more logical, so taking the java approach may also lead to surprises (In this example you can consider the char a subclass of a string).
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quote: Making the char class a subclass of the number class is absolutly a possibility. Im a bit defensive about these things since its easy to implement features with unwanted side effects you cant get rid of cos of backward compatibility.
In java 'o'+'k'=218 but 'o'+'k'="ok" seems more logical, so taking the java approach may also lead to surprises (In this example you can consider the char a subclass of a string).
Actually for someone (me) who has programmed assembly and C a lot I think 'o'+'k' = 218 is much more logical.
It's pretty common to do LDA #'<char>' and things like that so we should be quite used to seeing it as a number.
Explicit casting instead of 0+'<char>' would be acceptable but the above would be better IMO.
Can it be done with "<string>" + '<char>' still working? |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: Making the char class a subclass of the number class is absolutly a possibility. Im a bit defensive about these things since its easy to implement features with unwanted side effects you cant get rid of cos of backward compatibility.
In java 'o'+'k'=218 but 'o'+'k'="ok" seems more logical, so taking the java approach may also lead to surprises (In this example you can consider the char a subclass of a string).
Imo if you wish to include the more logical approach ('o'+'k'="ok") then do it via some specific concatenate operator, like the dot (.) in PHP. Let +-*/&| always be arithmetical imho, to keep things more clean and predictable.
Having char as a subclass of string sounds just weird actually. It's more like a string is composed by chars which might be a subclass of a number or not.
But then again... :) It's your assembler and your decision and I don't even use it, although I'm deeply impressed by it so keep up the good work! :D |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Jackasser: For java strings the '+' operator is used for append, so it would counter intuitive to use another operator here for chars, and ind java 'o'+"k"= "ok" (char+string appending).
The string subclassing example was just point out that a char can be viewed as a string of length 1 as well as a number. If you write print('x') you would expect the string "x" as output and not the string "120", so in some respect it is a string and in other cases its a number.
However, I guess the number class is probably the most dominant one (it has more useful methods) so i guess that the primary object of inheritance. (So I actually agree with you, but just dont wan't to rush into an implementation with unwanted sideeffects)
|
| |
Angel of Death
Registered: Apr 2008 Posts: 210 |
Call me n00b, call me blind, call me stupid, whatever. But where were the executables of kick assembler again?
(can't find them on the designated spot)
Because Java just isn't my thing... |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi,
The exe version ain't supported anymore. Dependend on which os you use, java might already be installed which means the only difference between the exe version and the java version is that you have to write java -jar KickAss.jar mySource instead of KickAss.exe mySource Usually people set this up in some kind of configuration (scripfile or editor command), so it aint that much of a difference.
Also check out Pantaloons KickVice.exe (KickVice)
Btw. I made a few improvements on LCP.. V3.19 should be out soon.
|
| |
Angel of Death
Registered: Apr 2008 Posts: 210 |
@Slammer
thx for the quick reply. I have a working config already. But I like to work with executables. (has to do with mobile workstations etc.) And last time I updated java it somehow changed the location of the javaw.exe and I spend some time fixing the problem. (was a pain since I was a long way away from my server)
It's just to make my life a lot easier.
thanks again for this great product. |
| |
Trap
Registered: Jul 2010 Posts: 222 |
I am trying to load a piece of music that is located at $f000 using the LoadSid directive. However, when I do that the program crashes the machine. Is there anything I need to be aware of when trying to do this with KickAssembler? |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quote: I am trying to load a piece of music that is located at $f000 using the LoadSid directive. However, when I do that the program crashes the machine. Is there anything I need to be aware of when trying to do this with KickAssembler?
Does KickAssembler crash or does the resulting binary crash? |
| |
Killsquad Account closed
Registered: Jun 2005 Posts: 17 |
Quote: I am trying to load a piece of music that is located at $f000 using the LoadSid directive. However, when I do that the program crashes the machine. Is there anything I need to be aware of when trying to do this with KickAssembler?
I guess Vice is crashing because you're trying to load over ROM. Try to add the following parameter to the Vice cmdline: -autostartprgmode 1
An alternative is to pack it before you run it.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Also remember to switch off the rom and use $fffe/$ffff for irq. |
| |
Trap
Registered: Jul 2010 Posts: 222 |
Thanks for the replies everyone. Decided to go with a simple relocation, but I'll try the Vice switch next time. |
| |
Shadow Account closed
Registered: Apr 2002 Posts: 355 |
I'm getting some strange behaviors with pseudopc set to a zeropage address.
I have some code that I assemble into memory, then copy to zeropage runtime. However, the self modifying parts of it doesn't get properly assembled to the ZP versions of the instructions if I reference a label that is further ahead in the code.
Here's an example that demonstrates this:
.pc=$1000
.pseudopc $90
{
some_label:
lda $1000
inc some_label+1
inc some_other_label+1
some_other_label:
lda $1000
}
This get assembled into:
AD 00 10
E6 91
EE 99 00
AD 00 10
I would have liked it to be:
AD 00 10
E6 91
E6 98
AD 00 10
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
You have stumbled upon an interesting detail. To simplify a bit, look at the following:.pc = $fd
lda label
label: In the case the position of the label depends on the size of the command, and the size of the command depends on the position of the label so the only way to determine if the command can use its zeropage form is by trial and error, which might get quite complex and lead to more passes.
Instead Kick Assembler tries to reduce the command to its zeropage form when it first meets the command, and since it doesn't know the value of the label, it fails and marks the command as using the absolute addressing mode. This is the reason why the first command in your example is reduced to the zeropage form and the second isn't.
So what do you do then?. You can use this little magic trick to tell the assembler that you want a zeropage command: .pc=$1000
.pseudopc $90
{
some_label:
lda $1000
inc some_label+1
inc CmdArgument(2, some_other_label+1)
some_other_label:
lda $1000
}
The magic is the argument type constant 2 which actually is 'AT_ZEROPAGE' which is not exposed in the current version but will be in the next release (Nobody I know of have had this problem before - placing code on the zeropage seems kind of special, but might be a smart optimization?)
Previously I have had plans for making it easier to force addressing modes like this:inc.zp label
lda.abs $0000
and they can be reintroduced on the todo list if there is a demand for it.
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quoting SlammerPreviously I have had plans for making it easier to force addressing modes like this:inc.zp label
lda.abs $0000
and they can be reintroduced on the todo list if there is a demand for it.
It should be possible to resolve it in most cases using additional passes but I'd vote for your solution with extensions.
I've used .z and .a in dasm quite a lot.
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
I second tlr. Sometimes i use abs-mode for zp addresses for VIC timing reasons, to make it take a cycle more. In this case I do it like this:
.by LDA_ABS
.wo zpAdr
This approach can be used the other way around too of course, but it's a bit clumsy in the long run.
|
| |
Shadow Account closed
Registered: Apr 2002 Posts: 355 |
Sorry Slammer, I write strange code for strange platforms, so I guess I end up hitting those cases noone thought of! :)
I'll try the workarounds posted here! |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Typo:
buf_zp:
.fill 4 do <ctrl>-t here
^ |
v
Error: Invalid number of arguemnts
at line 122, column 2 in test.asm
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Thanks. It's corrected in the next release. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I just release v3.20. One of the new features is that you can force addressing modes like this:inc.zp label
lda.abs $0000 orinc.z label
lda.a $0000 Btw. the 'chars inheriting from number' issue was implemented in v3.19
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Great! |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quote: I just release v3.20. One of the new features is that you can force addressing modes like this:inc.zp label
lda.abs $0000 orinc.z label
lda.a $0000 Btw. the 'chars inheriting from number' issue was implemented in v3.19
Hmm, in 3.20 do:
.pc = $0801
ldy.a $c000,x
sta.z $fb,x
This will silently ignore the indexed addressing mode (= bad).
Also this could be resolved in a nicer way as we know that it must be <zp>,y: .pc = $0801
stx lab,y
.label lab = $fb
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Try version 3.21 where you can force all the arguments types. Zeropage and zeropage,x are considered two different types so: ldy.a $c000,x // Abolute mode - No indexing
ldy.ax $c000,x // Absolute,x
sta.z $fb,x // Zeropage mode - No indexing
sta.zx $fb,x // Zeropage mode,x
I skimmed the Dasm manual and had the impression that they have a similar approach? However i like the simplicity of only having to memorize two extensions so I will take a look at the implication once i get some sparetime.
Nice stx lab,y observaton.
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quoting SlammerTry version 3.21 where you can force all the arguments types. Zeropage and zeropage,x are considered two different types so: ldy.a $c000,x // Abolute mode - No indexing
ldy.ax $c000,x // Absolute,x
sta.z $fb,x // Zeropage mode - No indexing
sta.zx $fb,x // Zeropage mode,x
I skimmed the Dasm manual and had the impression that they have a similar approach? However i like the simplicity of only having to memorize two extensions so I will take a look at the implication once i get some sparetime.
Dasm does have that approach but I consider it very confusing.
I've even changed that in my own version of dasm. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Hey!
Is there a clever way to count the amount of bytes used in a routine within KickAss?
something like (creating an index table):
.pc = begin
CODE
.pc = end
.for (var i = 0 ; i < 128 ; i++) {
.byte <STUFF+[i*[end-begin]]
}
cheers! |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Something like this?...
.var length = end - start
start:
nop
end:
.print "length:" + length
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Quote: Something like this?...
.var length = end - start
start:
nop
end:
.print "length:" + length
Yepp, Exactly like that 8-D
Easier then I thought^^
Thanx! |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Am I missing something here?
This works:
.pc = $1000
.const TEST_ENABLE = true
.macro test(v) {
.byte v
}
.if (TEST_ENABLE) {
:test(2)
}
This doesn't:
.pc = $1000
.const TEST_ENABLE = true
.if (TEST_ENABLE) {
.macro test(v) {
.byte v
}
:test(2)
}
(fails with "Error: Macro command 'test' not defined")
Seems pretty unintuitive to me, especially as the if is enabled by a constant.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
No, it's just a bad error message. Macros can't be defined inside if statements. They are collected in a preparse which makes it possible to define macros after you use them (eg. macro definitions in the bottom of your sourcefile).
Why do you want to place it inside an if? I'm guessing you have made a libraryfile and only want to define the macro once in the case the library is imported sevaral times? If thats the case, place an .importonce directive in the top of your library-file. It works as the if you had placed an #ifndef, #define XYZ, #endif in C++:
--------- KickAss Library File: ---------
.importonce
... your code
--------- C++ Library File: ---------
#ifndef __MYLIB__
#define __MYLIB__
... your code
#endif |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quoting SlammerNo, it's just a bad error message. Macros can't be defined inside if statements. They are collected in a preparse which makes it possible to define macros after you use them (eg. macro definitions in the bottom of your sourcefile).
Why do you want to place it inside an if? ...
The .if in this case is for conditional compile. In this case the macro only relates to the code within that code block. Then it makes sense to be able to define the macro close to the code that actually uses it.
As a side note, not being able to set constants in the global scope from within an .if (in the conditional compile use) is rather inconvenient.
Should I be using some other construct for conditional compile? |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
ohh, i didnt know of the importonce, lovely!!! |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Tlr: Like in java, you can't reach a variable declared inside an if (or for). If you want to access it outside the scope of the if, then declare it outside of the scope and set it inside.
Panta: Thanks :-)
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quoting SlammerTlr: Like in java, you can't reach a variable declared inside an if (or for). If you want to access it outside the scope of the if, then declare it outside of the scope and set it inside.
Will give predeclaration a go.
What's causing the confusion is that there is no preprocessor style if.
Other assemblers usually treat both if's and macros in a preprocessor sense, often even using multiple passes to resolve conflicts.
This of course causes some other problems (like oscillations) which you solve in kick assembler with much stricter parsing rules.
I'll see if I can figure out a way to adapt my coding style to this difference.
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Feature Request:
Maybee this is a posibility already but here goes:
Allow Suffixes to Pseudocommands according to some fixed syntax.
Ex:
A multiply routine can be called with either:
:MUL_S <- for Signed Mul (suffix being the "_S")
or
:MUL_U for Unsigned (Suffix is "_U").
This is just an example and so is the syntax but it would allow you to put both these routines inside one file instead of two (there would ofcourse have to be some way to use these suffixes inside the pseudo to make descicions).
Another thing:
Did the ".IfDefined" feature requested by someone before see the day of light?
Cheers! |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
TWW: Why not use a parameter for that? |
| |
TWW
Registered: Jul 2009 Posts: 541 |
That's what I'm currently doing so yes, this is a luxory feature request 8-D |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
I thought I'd post a few things I've run in to lately. If the suggestions are too crazy, feel free to disregard them. :)
1:
I tried just now to write a file format header using kick assembler and discovered that there is no pseudo op to output ascii. (.text converts lower case to screen codes.)
.ascii "Header Ident!"
.byte 0 That would be useful!
2:
Consider this:
.pc = $1000
start:
lda #<msg
ldy #>msg
jmp $ab1e
msg:
.text "LEN $"+toHexString(end-start)
.byte 0
end: In this example toHexString() will generate lowercase, which is fine. However how do I convert it automatically to upper case? A custom to_upper(str) will fail because the string isn't fully resolved in the first pass.
3, A suggestion:
It would be useful to be able to generate UC-mode/LC-mode screen codes/petscii in some structured way.
.text_u "HELLO WORLD!"
.text_l "Hello World!"
.scr_u "HELLO WORLD!"
.scr_l "Hello World!" A function wrapper could be a substitute, but see 2 above.
4, another suggestion:
It would be useful to be able to mix bytes and strings.
.text "STRING",0
.byte TOKEN_SYS,"2061",0,0,0 I guess some of this could be emulated with macros, but I usually prefer the short form. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
tlr: Good suggests!
Cruzer: Just to add: I find it a bit akward to use numerical parameters to pass on to a pseudo which should dictate what way it should operate.
i.e:
:MUL "S" ; #$04 ; #$10 ; $1000
would work fine but since I can't pass strings and you need to remeber that 1 = signed and 2 = unsigned etc. it doesen't look and feel that tidy to me anymore.
So: just allow a suffix to be passed OR allow passing of strings and it's all Rock and Roll Rulletobakk after that. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
You can allready use _ in commandnames. Why don't you use two extra lines to define the two pseudo commands:.pseudocommand MUL_S a ; b ; tar { :MUL 1 ; a ; b ; tar}
.pseudocommand MUL_U a ; b ; tar { :MUL -1 ; a ; b ; tar}
.pseudocommand MUL sign ; a ; b ; tar {
/* CODE..
Use .if (sign==1) {...} etc.
*/
} |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Thanks for the suggestions.. I have had several whishes for uppercase/lowercase selection so that will be put high on the list. |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quote: Thanks for the suggestions.. I have had several whishes for uppercase/lowercase selection so that will be put high on the list.
Great!
In case it wasn't clear enough:
in 3 I am suggesting that .text_u generates petscii suitable for printing with the uppercase charset, and .text_l generates the same suitable for printing with the lowercase charset.
.scr_u and .scr_l does the same but with screen code output.
In 1 I mean plain ASCII, or perhaps ISO-8859-1.
In 2 either some kind of conversion function, or better yet, solve the resolution problem in some way.
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Halleluja! Ask slammer and he has a way!!!
Beers on me if we ever meet!
About the ".ifdefined" thing, any news about this? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
No .ifdefined yet. What are you going to use it for? |
| |
TWW
Registered: Jul 2009 Posts: 541 |
F.ex:
I want a spudocommand/routine to behave in three different ways:
#1 - Set a global constant (ex: .const SafeMode = 1) which the automatically preserves all registers within pseudocommands.
#2 - Call up a pseudo with a SafeMode setting which then might overrrule the global setting to allow individual routines behave differently if I so choose.
#3 - If none of them are defined, force a default mode
So basically I want to check if a Constant or a Variable is defined from before.
However I am sure, by your question, you already got a(nother) method to do this^^ |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I would do something like this:
//---------------------------------------------
// Mode Control
//---------------------------------------------
.enum {MODE1, MODE2, UNSET}
.const defaultMode = MODE1
.var mode=UNSET
.function getMode() {
.if (mode==UNSET) return defaultMode
.return mode
}
//---------------------------------------------
// Commands
//---------------------------------------------
.psesudocommand myCmd a; b {
.if (getMode()==MODE1) {
/* DO SOMETHING */
}
.if (getMode()==MODE2) {
/* DO SOMETHING */
}
} |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
A little request: When a branch distance gets too far, it would be nice to know by how much. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
I wrote a useless test with a zooming 2x2 char fonts, here is the routine in KickAsm that precomputes all the scaled characters if someone is interested.
.pc = $6000 "Zoomed Font"
.const c_zoomLevelCount = 19
.const c_zoomMin = 0.15
.const c_zoomMax = 1
.const c_charCount = 30
//
// load the font into 16x16 pixel chunks
//
.var originalFont = List()
.var charsetFont = LoadPicture("data/fonts/2x2_formaterad.gif", List().add($000000, $ffffff))
.for (var c = 0; c < c_charCount; c++)
{
.var theChar = List()
.for (var y = 0; y < 16; y++)
{
.for (var x = 0; x < 16; x++)
{
.var p = charsetFont.getPixel(x + c * 16, y) & 255
.eval theChar.add(p)
}
}
.eval originalFont.add(theChar)
}
//
// create zoomed versions
//
.function linearInterpolate(a,b,t)
{
.return [a*[1.0-t]] + [b*t]
}
.macro scale16x16(source, dest, zoom)
{
.var xratio = zoom
.var yratio = zoom
.var xoffset = [1-xratio] * 8
.var yoffset = [1-yratio] * 8
.for (var dy = 0; dy < 16; dy++)
{
.var sY = round([dy * yratio] + yoffset)
.for (var dx = 0; dx < 16; dx++)
{
.var sX = round([dx * xratio] + xoffset)
.eval dest.set(sX + sY*16 , source.get(dx + dy * 16))
}
}
}
.for (var c = 0; c < c_charCount; c++)
{
.for (var zoom = 0; zoom < c_zoomLevelCount; zoom++)
{
.var t = zoom / [c_zoomLevelCount-1]
.var zoomLevel = linearInterpolate(c_zoomMin, c_zoomMax, t)
.var originalChar = originalFont.get(c)
.var destChar = List()
.for (var i = 0; i < 256; i++)
.eval destChar.add(0)
:scale16x16(originalChar, destChar, zoomLevel)
.for (var j = 0; j < 2; j++)
{
.for (var y = 0; y < 16; y++)
{
.var theByte = 0
.for (var x = 0; x < 8; x++)
{
.var yy = y
.var xx = x + j * 8
.var addr = xx + yy * 16
.if (destChar.get(addr) == 255)
.eval theByte = theByte | [1 << [7-x]]
}
.byte theByte
}
}
}
}
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
I found a bug (i think) with the .importonce directive.
Lets say i have A.s containg this
.importonce
.var tracksector_hashtable = Hashtable()
.eval tracksector_hashtable.put("STARTUP",TRACKSECTOR(1,0))
And another file, B.s looking like this:
.import source "A.s"
.var ts = tracksector_hashtable.get("STARTUP")
Will produce this error:
Error: Unknown symbol 'tracksector_hashtable'
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Panta: Late night coding i guess? :-)
My guess is that you have several .import statements and that the first one is inside a scope, so when you want to access the variable from another file it's out of scope?
I will have to see some example source to say anything precise.
You can check in which scope the tracksector_hashtable is placed yourself by:
1. Change the tracksector_hashtable to a label (.label tracksector_hashtable =...)
2. Comment out the line that fails
3. Assemble and look in the symbol file in which scope tracksector_hashtable is placed.
The symbolfile is not meant for reading (but for .importing) but it should be readable.
Btw. Making a more structured solution to scoping (also for functions and macros) is something thats on the TODO list for a version 4.0. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
Thanks Slammer, i will try it out. If i can't find any obvious errors i'll send you the sourcecode :)
-panta |
| |
Dr.j
Registered: Feb 2003 Posts: 276 |
2 fast quest. from a newcmmer to KickAsm.2
i really new with this stuff so try to easy with me.
1. i want to create macro which just print the
value of $d012 .
2. can i send chunk of data to a list? f.ex: i want
to send location lets say $400-$500 to macro/func. and it
will add it to a list and then do some calc. and store
it back or to the same or other location. to simplify
lets say we add $06 to all the list and store it back.
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Dr.J: Macros etc. are for making life easier at compile time, not at run time. So you can't operate on memory content or registers. If you want manipulate the content from $400-$500, you have to keep it in Lists until all the calculations are done before storing it to memory.
|
| |
Dr.j
Registered: Feb 2003 Posts: 276 |
@Cruzer: can you show me ex. of precalc how do i
send the $400-$500 to a list and store it back.
i know how do create bytes from list but didn't see
the opposite.
|
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: @Cruzer: can you show me ex. of precalc how do i
send the $400-$500 to a list and store it back.
i know how do create bytes from list but didn't see
the opposite.
What exactly are you trying to accomplish?!? I mean... the assembler can not know what the memory contents on the real device are when assembling.
If you would like to simply add the value 6 to all bytes between $400-$500 you either write a simple assembly loop, or use Lists and macros to generate speed code. |
| |
Dr.j
Registered: Feb 2003 Posts: 276 |
i want to do something like that.. but i guess its not possible...
.macro mymacro(location) {
.define mymacro {
.var mylist=List()
.for (i=0;i<256;i++)
mylist.add (value of location)
mylist.add ($06) - lets say add to all elements..
//;dump to memory
.fill mylist.size(),mylist.get(i)
}
}
:mymacro($0400)
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Nope, not possible. But since you're in control of what gets into $0400-$0500 in the first place, you should wait with the dumping to memory and keep the data elsewhere so it can be used in the macro. And when all calculations are done, it's time for dumping. |
| |
Dr.j
Registered: Feb 2003 Posts: 276 |
Ok Guyz..10x for the help |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
Slammer, the bug with .importonce and .struct is really annoying for me :) could you take a look at it and perhaps fix it :) please :)
It's very easy to reproduce:
File1
.importonce
.struct TRACKSECTOR { track, sector }
fILE2
.import source "File1"
.var tracksector_hashtable = Hashtable()
.eval tracksector_hashtable.put("STARTUP",TRACKSECTOR(1,0))
parsing
flex pass 1
.import source "File1.s"
.var tracksector_hashtable = Hashtable()
.eval tracksector_hashtable.put("STARTUP",TRACKSECTOR(1,0))
^
Error: Unknown function : TRACKSECTOR
/Panta |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I'll check it in the weekend.
(I guess the missing .s in the sourcecode is a typo) |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
yes that is a typo :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Ok, bug is corrected. There will be an official released version later, but until then you can use this:
www.theweb.dk/tmp/KickAss.jar
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
thanks alot slammer!!! :) |
| |
Shadow Account closed
Registered: Apr 2002 Posts: 355 |
I apologize in advance for discussing non-C64 related stuff on CSDB, but since this is the defacto thread for everything KickAssembler related, I'll take my chances here.
I'm using kickass for my Atari 2600 coding, and I have some minor issues when doing bankswitching stuff.
For example, say I have two 4k banks, each should be assembled with $1000-$1fff addressing. Then I can do like this:
// Bank 1
.pc=$1000
lda foo
sta bar
..
.pc=$1400 "Some routine"
lda this
sta that
...
// Bank 2
.pc=$2000
.pseudopc $1000
{
lda foo
sta bar
..
}
And it works fine. However, say I want to place a routine at $1400 in the second bank. Then I have to break the pseudpc block, set the pc to $2400, and then start a new pseudopc block, like this:
// Bank 2
.pc=$2000
.pseudopc $1000
{
lda foo
sta bar
..
}
.pc=$2400
.pseudopc $1400
{
lda foo
sta bar
..
}
While it works, it gets a bit cumbersome to keep track of all the pc's and pseudopc blocks when you get more than a few.
Anyone have a good idea on how to work around this?
|
| |
andym00
Registered: Jun 2009 Posts: 44 |
In a really tenuous connection to Shadow's question above, but I figure now's the time to ask :) Is there ever likely to be support of the .pc directive for addresses >64K ?
It would make life assembling cartridge based stuff that's destined for >64K cartridge images a lot easier without a link stage to bolt all the banks together afterwards, and that's the simple case where there isn't code spanning these other banks and you want to share symbols etc..
I don't imagine it's a small change though, but had too ask :)
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Shadow: I don't know Atari coding so you will have to be a little more specific of what solution you had in mind.
Are you looking for something like this:
// Bank 2
.pc=$2000
.pseudopc $1000
{
lda foo
sta bar
..
.align $400
lda foo
sta bar
..
}
Or perhaps some kind of macro that makes it easier to set up the blocks? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Andym: I guess making support for files larger than 64k is not that big a problem. But since I'm not doing cartridge development i'll need someone to test it and see that the concept i really useful (eg. is this a good way to do it and what else would you need to do cartridge development).
|
| |
Shadow Account closed
Registered: Apr 2002 Posts: 355 |
Slammer: What I'm trying to accomplish I guess is setting the PC without having to break the pseudopc block.
Ideally I'd want something like this:
.pc=$2000
.pseudopc $1000
{
lda blabla
...
.pc=$1400
bla (code that ends up on $2400 here)
.pc=$1f3c
blabla (code that ends up on $2f3c here)
}
But maybe the solution you posted will solve that!
Would replacing the
.pc=$1f3c
with
.align $0f3c
in my example work?
Eh, I guess I can just test that myself! :D
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I don't think .align $0f3c is what you are looking for. The align directive is made so you can easily can align source code to page boundaries, så typically you would do:
.align $100
table: .byte 1,2,3,4,5,..
The align command reads the current memory position and inserts zeros until the next boundary is reached. Eg the pc=$107f and you write .align $100, then $81 zeros is inserted so the pc is now $1100.
In your first example it seemed like you wanted $400 block alignment :-)
Currently you cant set the pc freely inside an pseudocommand statement. You can make somekind of macro that advances the pc (and pseudope). Something like :
.macro setPos(pos) {
.var length = pos-*
.fill length, 0
}
but this will not work if pos is less that the current pc.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi, I got a mail from Alex who made a Kick Assembler plugin for Kate editor.
http://redlumf.blogspot.com/2011/12/kickass-plugin-for-kate.html
He would post it himself but had troubles signing up on CSDb. |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Slammer,
I have a couple suggestions for features:
1. Allow the ability to access variables from user-defined structures by index.
That way we can pass in a List or HashTable containing UDS's to a function and apply an action based on the variable's index rather than the name, which could be different for each UDS.
Great for library building.
2. Call an external JAVA program, passing in Strings, Floats, Integers, Lists & HashTables with UDS's and return the same back into KickAssembler variables.
I could get the functionality by having my JAVA code generate KickAssembler script but this could get quite large for Collections.
Would be nice to have this inline.
Steve
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Quote: Slammer,
I have a couple suggestions for features:
1. Allow the ability to access variables from user-defined structures by index.
That way we can pass in a List or HashTable containing UDS's to a function and apply an action based on the variable's index rather than the name, which could be different for each UDS.
Great for library building.
2. Call an external JAVA program, passing in Strings, Floats, Integers, Lists & HashTables with UDS's and return the same back into KickAssembler variables.
I could get the functionality by having my JAVA code generate KickAssembler script but this could get quite large for Collections.
Would be nice to have this inline.
Steve
1. Yep, I guess it's easily done. Im not sure i understand how to benefit from this in libraries. (Looking forward too see en example of use!)
2. Yep, can be done. Is in fact on the todo list, but it's will take a bit of work so i have postphoned it a bit. One of the reasons for restructuring the assemble mekanism so it could handle a flexible number of passes and to cache script results, was to be able to call external programs - Both with script parameters and assembled code (if you want to do crunching or encrypting etc.) |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Say I had a multi-field sorting routine this time for point{x,y} I could pass in a List of points.
Another time the names could be different or sort by even more fields.
I recently did a 2 field sort with a Hashtable and Lists. The Keys been the Y values which I called sort on, then called sort on Lists (Hashtable values).
That got me the result I wanted but I'd rather have a more generic solution.
But if suggestion #2 comes soon this will be irrelevant as I will just use full blown JAVA Collections and its interfaces (hmm still indexed fields would still be useful there saves
calling invoke on named methods).
And great to hear that it is on your list. That will make any other 'missing' functionality just go away. Cant wait! |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I don't think #2 will come that soon. Im pretty busy at the moment so there is not much time for coding for fun. However #1 is a small task. I guess it will be in the next release. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
coding is always fun :) |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Thanks Slammer that will help heaps.
So tempted to work the other way around and make JAVA spit out Kick Assembler script and ASM, but then I live in JAVA world all day.
Quote:coding is always fun :) Says the game programmer. Well coding is always fun, programming not always.
|
| |
Style
Registered: Jun 2004 Posts: 498 |
Ive asked this once before, and found some workaround at the time that Ive forgotten, but I lost my kickass libs and had to revert to ca65 again - and now, once again, Im converting to kickass ;)
So... the question once again - if I have a macro, how do I tell if the parameters were passed or not? ie, can I implement nonmandatory parameters?
thanks
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi Style
Normal macros have to have the right number of arguments.
Pseudocommands can have empty parameters |
| |
Style
Registered: Jun 2004 Posts: 498 |
any chance you can overload macros? :)
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
No, not at the moment.
Supplying too few parameters for a macros (like you can on pseudocommands) and setting the parameter to null when left out is possible. I left it out to avoid too much confusion when users supply to few arguments by mistake (Clearer errror messages vs flexibility) - If flexibility is in great demand, i'll open up that feature.
Since its a weakly typed script language something like the following is kind of against that nature of the language:
.macro myMacro(NumberValue x) {
//do something
}
.macro myMacro(String x) {
//do something else
}
If people miss this(?), it can be made possible by a type() function on objects:
.macro myMacro(x) {
if (x.type()==NUMBERVALUE) :myMacro_value()
else (x.type()==STRING) :myMacro_string()
else .error("Unkown Type")
.macro myMacro_value(x) {
//do something
}
.macro myMacro_string(x) {
//do something else
}
Btw. Can you give an example of where you will use this feature. |
| |
Style
Registered: Jun 2004 Posts: 498 |
yeh, on ca65 I had a macro, next_irq, which accepted conditional parameters of the address and raster position. If you didnt provide them, it merely dec $d019 (ie, there is only 1 IRQ)....
small point I know, but like I said Im trying to convert sources over the kickass.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Then i suggest you use pseudo commands. Here is an example of how to do:
// Use it like this
:irqEnd #$60 ; #irq2
// The macro
.pseudocommand irqEnd nextIrqYpos ; nextIrq ; extraArg {
.if (nextIrqYpos.getType()!=AT_NONE) {
:mov nextIrqYpos ; $d012
}
.if (nextIrq.getType()!=AT_NONE) {
:mov16 nextIrq ; $fffe
}
.if (SAVE01==extraArg.getValue()) {
:mov _ds_irq01 ; $01
}
lda _ds_irqa
ldx _ds_irqx
ldy _ds_irqy
rti
}
The above have optional parameters for next ypos, next irq address, and an option to save $01. (The mov commands are 'pc style' pseudo commands that moves data) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Conjuror: Finally found some time to make a new release. Made the following functions on user defined structs:
getStructName() - returns the structure name
getNoOfFields() - returns the number of defined fields
getFieldNames() - returns a list of field names
get(fieldName) - returns a field value by field name.
get(index) - returns a field value by field index
set(index, value) - sets a field by field name
set(fieldName, value) - sets a fields by field index
|
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Slammer,
Great work! thanks. This will really help with more flexible code creation.
Nice to see the ternary operator in there too.
|
| |
McKrackeN
Registered: Feb 2011 Posts: 20 |
Hey ppl! I have a newbie question: is there a way to use constants inside a macro?
For instance, I need to be able to do something like this:
.const MyConst = $d012
.macro myMacro(val)
{
ldy #val
sty MyConst
}
But I get an error when compiling.
Thanks in advance! :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Constants are visible after you have defined them. So the example you give, will work if you declare your const before you use the macro:
:MyMacro($32) // This won't work
.const MyConst = $d012
:MyMacro($32) // This will work
.macro myMacro(val)
{
ldy #val
sty MyConst
}
However, labels can be seen in the whole scope so they can be used before they are declared:
:MyMacro($32) // This will work
.label MyLabel = $d012
.macro myMacro(val)
{
ldy #val
sty MyLabel
} |
| |
McKrackeN
Registered: Feb 2011 Posts: 20 |
Thanks for your help!
I think i'm declaring the constant before using the macro but i'm still getting the compiler error.
I have two separate files. One called system.asm and the other test.asm.
// System.asm
.const MyConst = $d012
.macro myMacro(val)
{
ldy #val
sty MyConst
}
Then in the test.asm:
// test.asm
.import source "system.asm"
// some code
:myMacro(0)
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I Just tried it and it works fine here. My guess is that you define the macro+constant inside one scope and execute your macro outside the scope. Eg. if you start you system.asm file with a .filenamespace directive.
|
| |
McKrackeN
Registered: Feb 2011 Posts: 20 |
Yes!! That's it!! Thanks for your help and for this amazing compiler!! |
| |
TWW
Registered: Jul 2009 Posts: 541 |
How would I go about doing a:
.fill 256,invert(data.get(i))
i.e. invert the data filled into memory on the fly? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Suppose by invert you mean exclusive or you can:
.fill 256,data.get(i)^$ff |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
i found this bug:
test1.asm:
.if (1 == 1) {
.import source "test2.asm"
}
test2.asm can be whatever (even empty file)
assembling results in the following error:
.if (1 == 1) {
.import source "test2.asm"
^
Error: Unknown import type 'source'
at line 3, column 5 in test1.asm
additional question: if there are labels defined in test2.asm, then how do i export them outside the scope of the if statement? (i find it really super useless and annoying that if statements have their own scope to be honest, it effectively prevents me from being able to use them properly :/)
eg i am used to do stuff like this:
.if testing = 1
screen = $0400
chars = $0800
.else
screen = $e400
chars = $e800
.endif
how do you do this in kickass? (assuming there are many more such labels, replacing them all by a function is really not an option)
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
Yepp, that's exactly what I ment. Thanx Slammer! |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I see your problem. You can't use the .import source directive this way, it can't be nested inside a .for or an .if. The reason is that the .import source directive is evaluated in a pre parse that collects pseudocommands, macros, functions, etc so you can use them in the evaluation, but the error message is wrong. Should be something like 'Cant use an import source directive here'.
If you are importing libraries and only want to import them once, then use the .importonce directive instead.
btw. booleans are implemented so you can do: .if (true) { ..}
----
About labels/Constants/Variables:
Constants: Is defined like '.const myConst=25' and can only be accessed after they are defined. Constants can't change values.
Variables: Is defined like '.var myVar=true' and works like constants. The only difference is that you can change the value of a variable. e.g.: '.eval myVar=false'
Labels: Is defined like 'myLabel1:' or '.label myLabel2="HelloWorld" and can be accessed before they are declared (Note that they don't necessarily have to be numbers). Labels can't change values.
Now back to your question. To do a test setup like the one you describe you can do it in two ways. The first way defines your constants in a really compact way:
// Define Mode
.const TEST = true
// Define Data
.const screen = TEST ? $0400 : $e400
.const chars = TEST ? $0800 : $e800
Another way, that keeps the test setup more separated from the normal setup, is to define the datafields as variables and assign them insides ifs:
// Define Mode
.const TEST = true
// Define Data
.var screen .var chars
.if (TEST) {
.eval screen = $0400
.eval chars = $0800
} else {
.eval screen = $e400
.eval chars = $e800
} |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:I see your problem. You can't use the .import source directive this way, it can't be nested inside a .for or an .if. The reason is that the .import source directive is evaluated in a pre parse that collects pseudocommands, macros, functions, etc so you can use them in the evaluation, but the error message is wrong. Should be something like 'Cant use an import source directive here'.
If you are importing libraries and only want to import them once, then use the .importonce directive instead.
urks :( i am selectively including other sourcefiles there, depending on some other settings (ie, its not an include-guard). bummer, that will be tricky to solve :/ |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I once considered making a set preprocessing commands so you could do things like this, but I guess it will be really confusing to have two if commands, two var commands, etc. And I guess the .importonce directive covers 99% of the needs.
Dependent on how complex you includes are, there might be a hack. Since normal directives aren't evaluated during the preprossing pass, you can't create normal .var's or .const's to use in the '.import source' directive.. However, you can give variables to the assembler by the command line and use these as the include filename. Create an empty file to include, if you don't want to include anything..
Eg:
--- Commandline ---
java -jar KickAss.jar mySource.asm :loader="irqloader.asm"
--- mySource.asm ----
.import source cmdLineVars.get("loader")
NB. Its only the .import source directive that is effects by this issue. Other imports can be placed inside if's |
| |
Norrland
Registered: Aug 2011 Posts: 14 |
I'm trying to convert from 64tass-religion to KickAss-religion. When using 64tass, I've been using command line option -L alot. From 64tass docs:
Quote:
-L <file> List into <file>
Dumps source code and compiled code into file. Useful for debugging code, it's much easier to identify the code in memory within the source files.
Example
64tass -L list.txt a.asm
*=$1000
ldx #0
loop dex
bne loop
rts
result (list.txt):
;6502/65C02/65816/CPU64/DTV Turbo Assembler V1.4x listing file of "a.asm"
;done on Fri Dec 9 19:08:55 2005
.1000 a2 00 ldx #$00 ldx #0
.1002 ca dex loop dex
.1003 d0 fd bne $1002 bne loop
.1005 60 rts rts
;****** end of code
I can't seem to find a similar command line option in Kick Assembler docs. Does that exists? |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
@H Macaroni: Seems like a cool feature, but no, you can't do that in KickAss. What I usually do is simply to print out the address of the point I wanna inspect in the monitor like this:
.print "here: " + toHexString(*)
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
If i where you, I would export a vice symbol file (option -vicesymbols) and see your code in the vice monitor (including your labels).
There actually is a secret option a bit like the one you want, but with a much higher detail level so I won't recommend it for debugging programs in general (I use it for debugging the assembler). However, It might be interesting for people who wants a sneak peak of whats going on while assembling. The option is -parsetree which shows the state between each pass. The output looks like this: rasterbar.asm 45:4 : #NAsmCmd(ldy, EAsmArg(EVarRef(rasterColor)))
rasterbar.asm 46:4 : #NAsmCmd(cpy, EAsmArg(EConst(!255.0)))
rasterbar.asm 47:4 : #NAsmCmd(beq, EAsmArg(EVarRef(o1)))
rasterbar.asm 48:4 : #NAsmCmd(lda, EAsmArg(EConst(!53266.0)))
rasterbar.asm 49:4 : #NAsmCmd(cmp, EAsmArg(EConst(!53266.0)))
rasterbar.asm 50:4 : #NAsmCmd(beq, EAsmArg(EObjFuncCall(-,EPcRef(),EConst(!3.0))))
rasterbar.asm 51:4 : #NAsmCmd(sty, EAsmArg(EConst(!53280.0)))
rasterbar.asm 52:4 : #NAsmCmd(inx, EAsmArg())
rasterbar.asm 53:4 : #NAsmCmd(jmp, EAsmArg(EVarRef(l1)))
Beware, It easily gets complicated and is not supported in any way (Originally only intended for me to read). However, if you are really interested whats going on in line 50, you might be able to tell.
|
| |
Norrland
Registered: Aug 2011 Posts: 14 |
Thanks for the answers, I'll try them. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Why do I get an error (Uknown function) on the - in [max-min] in de code below?
Using KickAss v3.25.
.pseudocommand sinData min;max;freq {
.var amp = 0
.eval amp = [max-min]/2
.fill 256, amp + amp * sin(toRadians(i*[360*freq]/256))
}
.pc = $1000
:sinData 0;255;1
|
| |
Killsquad Account closed
Registered: Jun 2005 Posts: 17 |
To get the numeric value of the params use max.getValue(), min.getValue() and freq.getValue().
|
| |
Killsquad Account closed
Registered: Jun 2005 Posts: 17 |
Would it be possible for enums to continue from the next number after an explicit value?
Example:
.enum { var1 = $10, var2, var3 }
should give var2=$11, var3=$12
As it is now var1=$10, var2=$00 and var3=$01
Thanks for the massive effort by the way. Excellent assembler! |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Mace: Seems more like a job for a macro. Then you don't have to use getValue() |
| |
Mace
Registered: May 2002 Posts: 1799 |
Thanks Killsquad.
@Cruzer: yeah, probably... was just foolin' around 'n stuff ;-) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Mace: What Killsquad and Cruzer said. Pseudocommands is macros that takes assembler instruction arguments. So you can write :myCmd #$20 or :myCmd $20 and the command will know that the first one is an immediate argument and the second one is an absolute argument although they both have the value $20.
Killsquad: Thanks! Good Point. I actually considered that solution when I made the enum directive and it could just as well have been that solution. However, I'm rather sensitive to things that destroys backwards compatibility so I'm not planning on changing it. |
| |
ruk
Registered: Jan 2012 Posts: 43 |
Hi,
This does not compile:
.var hashtable = Hashtable()
.const booleanOption = hashtable.containsKey("booleanOption") && hashtable.get("booleanOption")
The error is "Error: Can't get a boolean representation from a value of type Null", so I guess there is some issues with lazy evaluation?
As a workaround I have defined the following function:
.function getValue(hashtable, key, defaultValue) {
.if (hashtable.containsKey(key))
.return hashtable.get(key)
else
.return defaultValue
}
So that I can do e.g.
.const underTest = getValue(cmdLineVars, "testing", false)
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
@Ruk:
You're trying to make a boolean and (&&) of false (the result of containsKey) and null (the result of get), which doesn't make sense.
Your function seems to do the job, but you could also do it like this:
.const booleanOption = hashtable.containsKey("booleanOption") ? hashtable.get("booleanOption") : false
|
| |
ruk
Registered: Jan 2012 Posts: 43 |
Sure, np, but I've gotten used to lazy evaluations in boolean expressions.
Thing is, if containsKey() == false the '&&'-operator shouldn't evaluate the term to the right since the whole expression is bound to be false.
It just struck me as odd that Kickass complained.
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Ah, so that's what you meant. Wasn't familiar with the term lazy evaluation. Guess KickAss doesn't use it, but I guess it would be smart from a performance viewpoint. |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
It's also commonly known as "short circuiting" operators. It is well defined for many C-like languages. I would guess it applies to Java as well. |
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
Can't remember last time when I encountered a language that did NOT use lazy evaluations. Indeed something that I have also gotten used to using. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
KickAssembler will probably support short circuiting in one of the future versions, as it converges towards the Java/C++ style. The idea is that, the more ways KickAss Script is similar to C++/Java, the easier it is to learn since you can use what you already know.
Frantic: Don't know if its still the case, but Visual Basic?
Once I had to work in Visual Basic for a shorter period of time and one of the things I really missed was short circuiting, which really ruled out a lot of ways to express things. So I fully understand why you miss it.
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
i think this is a bug =) this works:
.import source "../framework/framework.asm"
this gives an error:
.if (1 == 1) {
.import source "../framework/framework.asm"
}
flex pass 1
.import source "../music/music2.inc"
.if (1 == 1) {
.import source "../framework/framework.asm"
^
Error: Unknown import type 'source'
whatthehell ? :)
edit: lol. i already reported it a while ago =) and i still think its an error, its totally not how you'd expect it to work and it makes more complex stuff almost impossible to do. too bad really, things like that drive me back to ca65, despite the many nice features in kickass :/ (.if always adding a scope around the enclosed block also makes it a lot less useful than it should be, unfortunately) |
| |
ruk
Registered: Jan 2012 Posts: 43 |
I think what we're lacking is preprocessor stuff à la C since things like conditional compilation can't be solved by the scripting facilities of KickAss.
At least this is what I suspect.
So, I propose the introduction of #if, #ifdef, #ifndef, #else, #elif and #endif directives. It would solve many things, at least for me. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Found a workaround that might do the trick...
.import source 1 == 1 ? "framework.asm" : "emptyFile.asm"
It can't use vars or anything fancy in the condition though, except for command line args.
.import source cmdLineVars.get("importFramework") == "true" ? "framework.asm" : "emptyFile.asm"
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
yes, indeed. for the scripting and table generating stuff the current set of features is great.... for anything else not so much. |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
@Ruk, @Groepaz: Well... cpp is free, easy to use and easy to integrate into your makefiles so... :) |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:Found a workaround that might do the trick...
that might work for my specific case, thanks :)
Quote:Well... cpp is free, easy to use and easy to integrate into your makefiles so... :)
that would however add another dependancy, and also completely defeats the point of using kickass as an all-in-one solution (which is the only reason for me to use it really, i can do the same with a bunch of external tools anytime, however the idea is NOT to have to do that) |
| |
ruk
Registered: Jan 2012 Posts: 43 |
@JackAsser: Sure, it has struck me to involve another tool for this kind of operations, but as Groepaz said - it would be nice to have an all-in-one solution.
However, this is not a showstopper for me. I'm very happy with KickAssembler, but there's potential for it to become even better =)
Btw, haven't read all posts, but have Slammer ever considered going open source?
|
| |
Shadow Account closed
Registered: Apr 2002 Posts: 355 |
Yeah, then perhaps someone could create a Z80-version as well! :D
(Yeah, I know it's blasphemy to even speak about that CPU on this site, but as a multi-platform guy, I really miss KickAssembler when I venture to the non 6502-based systems!) |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
try RGBDS then, it has quite some of the features that stand out in kickass (its somewhat buggy though, and afaik no source available and only exes for dos) |
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
In fact, there are sources available for RGBDS:
http://www.otakunozoku.com/rednex-gameboy-development-system/ |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
oh, that wasnt the case when i was using it :) (but that was like 10 years ago or so) |
| |
Carlos Account closed
Registered: Mar 2009 Posts: 15 |
Anyone have a Kick Ass syntax highlighting for Notepad++? i've tried the one in codebase: http://codebase64.org/lib/exe/fetch.php?media=tools:kickassembl.. but seems to crash the IDE.
|
| |
Maxlide
Registered: Apr 2003 Posts: 29 |
This syntax highlithing file was uploaded by me.
I've just downloaded and checked it again. No problems here.
I am using the latest Notepad++ version 6.1.3. |
| |
Conrad
Registered: Nov 2006 Posts: 833 |
Is there a commandline to output files bigger than 64K? ... for the case of writing .crt files? |
| |
JAC
Registered: Aug 2002 Posts: 56 |
In -dtv mode, are the illegal instructions of 6510 still valid? I first thought no, but then DTV would not run plain C64 stuff. But then again DTV could have 2 modes of operation. ... Please enlight me, so I can do the highlighting correctly. |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quote: In -dtv mode, are the illegal instructions of 6510 still valid? I first thought no, but then DTV would not run plain C64 stuff. But then again DTV could have 2 modes of operation. ... Please enlight me, so I can do the highlighting correctly.
Undocumented 6510 opcodes are mostly supported by the C64DTV. A few do not work correctly. DCP has some problems IIRC. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Conrad: No, Not right now. I have never worked with .crt files, but it sounds like a minor adjustment or? What are the requirements for such files?
JAC: Kick Assember assembles all illegal instructions in DTV mode.
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
V3.23 is out now. There are some improvements:
- The && and || operators are now short circuiting.
- You can now use escape sequences to insert " in strings.
As a new feature you can write your own macro plugins in java, graphics Converters etc. If you make some good ones feel free to send them to me so they can be downloaded from the website or included in KickAssembler.
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
slammer, NICE! |
| |
Conrad
Registered: Nov 2006 Posts: 833 |
Quote: Conrad: No, Not right now. I have never worked with .crt files, but it sounds like a minor adjustment or? What are the requirements for such files?
JAC: Kick Assember assembles all illegal instructions in DTV mode.
There's no real major adjustment for .crt files other than just allow output files to be bigger than 64K. As long as ".pseudopc" is used in code that will be assembled outside the 64K range, I wouldn't think there would be an issue.
This is primarily for developing EasyFlash carts that can be 1MB big. :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Conrad: So you never want a start address above $ffff? The following source would be a problem because the format of the output file only have two bytes to note the start address:
.pc=$11000
.byte 1,2,3
|
| |
Conrad
Registered: Nov 2006 Posts: 833 |
Quote:Conrad: So you never want a start address above $ffff?
No, not for .crt files. They have their own header at the start of the file and don't have, let's say, a "start address" unlike normal .prg files.
check:
http://codebase64.org/doku.php?id=base:crt_file_format
so in essence, I would set .pc to $0000, and each "CHIP" block of data would always be mapped at $8000,$a000/$e000 (using .psuedopc) and would never be out of range.
I know that this additional feature would break the rule for normal .prg files, but that's the coder's choice really. If it's going to fuck up things like object-mapping, then by all means don't include it. I can find other ways around it. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Ok, no problem, I did a more flexible memory block management routine yesterday. There will be a new version out soon.
I guess you can use the -binfile option to make a binary file (So you won't get the two address bytes at the start of the file). Then don't worry about setting the .pc to zero, just write the header bytes and include the code in pseudo blocks. I guess you can write .crt files directly this way without any workarounds. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Very nice with the new Java plugin feature! I think that would call for more than the usual 0.01 increase in version number. I converted a pretty heavy precalc script, which immediately reduced the compile time from about 45 to 7 seconds, and there's even still some unconverted scripts left in the asm code.
Feature requests:
- Booleans as parameters for the Java macros
- List's and other "advanced" data structures as parameters. At least a list of numbers (double values) would be nice.
- Access to some of the usual KickAss functionality, e.g. for getting single/multicolor bytes from pics. |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Slammer,
Thanks for the JAVA plugin, didn't expect it so soon! This will really help with my plan to build more in JAVA before ASM but then reuse the data model.
Great work!
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
V3.24 is now on the website
Conrad: With the -maxaddr option you can set the maximum memory address or set unlimited memory.
Cruzer: Thanks. To make it a major number higher something has to change with the underlying algorithm or framework:
Version 1 (which was never released) was a normal assembler.
Version 2 made it object oriented (values was not just numbers) and the script language was added.
Version 3 made it a flexible pass instead of a fixed pass assembler. Script calculations of previous passes are saved so they only get to be calculated once etc.
Seen in this context, plugins are just an extra feature.
Booleans was intended to be in the first release, but just didn't make it. List of values was saved for a later release. Both of them will come soon and probably other standard data structures such as hash tables. Specialized values like pictures are not the plan though.
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Sounds good, Slammer! I didn't mean pictures as parameters, but to have access to an API with some of the same tools as you can currently access from KickAss scripts, e.g. for picture import. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi. It's now possible to write modifier plugins. With these its possible to modify assembled bytes, eg. do packing, crunching, encrypting, call external executables or whatever. You can modify small pieces of code or the whole file.
Eg://----------------------------------------------------------------
jsr depack
jmp effect
//----------------------------------------------------------------
depack: .modify Pack(PK_INCLUDE_DEPACK) {
.pc = $2000
effect:
lda #12
sta $1234
.pc = $8000
data: .byte 1,2,3
}
//----------------------------------------------------------------
Kick Assembler won't be open source in the nearest future, but If you want to help improve Kick Assembler, then do a cool plugin and share it. |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
@slammer: Very cool feature! |
| |
gryf Account closed
Registered: Aug 2006 Posts: 14 |
Slammer,
Good job!
BTW, is it possible to attach short changelog for each release, just to make it easier to track changes/additions in the assembler syntax/additional directives?
It would be much easier to synchronize syntax highlighting for example. Also, documentation in html form would be awesome too :)
BTW, if anyone interested, i've made syntax highlight for vim (http://www.vim.org/scripts/script.php?script_id=4121) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
The change log can be found here: http://www.theweb.dk/KickAssembler/Updates.php
I have been thinking of having the documentation in html on the website. But I also want to make the work cycle for a release as short as possible, which means make testing, creating zips and docs.
So can anyone tell me, is there an editor+text format that can generate both a pdf file and html pages from the same 'source text'? |
| |
andym00
Registered: Jun 2009 Posts: 44 |
Not exactly the answer you're looking for I think, but I've been recently started using MS Word 2010 for generating both PDF and HTML versions of docs I've been writing.. It's not pretty HTML, but it does the job for me :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Andy: Is it possible to make word generate a new html page for each chapter in the document or will all 60 pages be stored in the same html file? |
| |
MagerValp
Registered: Dec 2001 Posts: 1055 |
Quoting SlammerSo can anyone tell me, is there an editor+text format that can generate both a pdf file and html pages from the same 'source text'?
Lots and lots: http://en.wikipedia.org/wiki/Comparison_of_documentation_genera..
I prefer Markdown which spits out HTML. To create PDFs I just print the preview window and save as PDF. As a bonus the source itself is nicely formatted ascii that can be released as is. Plenty of Markdown processors too, pick one which suits your workflow: http://en.wikipedia.org/wiki/List_of_Markdown_implementations |
| |
Conjuror
Registered: Aug 2004 Posts: 168 |
Joomla allows you to download pages as PDF. I'm sure other CMS's allow that too. |
| |
andym00
Registered: Jun 2009 Posts: 44 |
slammer: I'm not sure, since I've not tried that kind of thing.. I'll have a look through it and see if there's some option for that.. |
| |
gryf Account closed
Registered: Aug 2006 Posts: 14 |
Slammer,
There is loads of doc generating systems out there. Beginning from LaTeX (lots of latex2[you-name-it] converters) through standalone documentation systems, which are able to generate output in various format (Sphinx for example), to some markup languages which output can be set to anything.
I would use some restructured text format for source documentation and use rst2pdf and rst2html, or LaTeX because I'm mostly familiar with those. Also Sphinx seems to be right choice for this task, but it may require more time for getting grip with. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Thanks for the input. I'll check it out. |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
overkill imho. text, pdf, html, all works and word can do those. all I need is ctrl+f to have a useful documentation. if sum1 cant use these he cant code 6510 either. :) |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
for a java program i'd not even think and use javadoc. if only because everyone does the same and solving a problem using google is a breeze.
and i'd strongly advice against using someones personal favourite - if it isnt one of the two majorly used ones =)
that said, vice uses TeX with texinfo - you can generate lots of different target formats with that. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Javadoc doesn't make sense for KickAss, since it's not a Java API, but a program that interprets something very different. Too bad there still don't seem to be any perfect solutions for writing a document in PDF and HTML in one go. But I think HTML would be sufficient. PDF is mostly targeted for printing, but who really needs that? |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Question:
Is there a fancyschmancy way to do this:
.const SomeString = "abcdef"+toHexString($1234)
Thus producing the new string: "abcdef4r"
where "4r" is a lo-hi byte (as it would go into memory) presentation of $1234 ($34 = "4" & $12 = "r")?
Oh and a minor suggestion: Please index your manual for kickass. links and a content list on the side would make the manual world class ;-) |
| |
ruk
Registered: Jan 2012 Posts: 43 |
@TWW
On the top of my head, and I bet there exists a fancier way =)
.const table = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ !\"#$%&'()*+,-./0123456789:;<=>?"
.function byteToString(val){
.return table.charAt(val).string()
}
.function wordToString(val){
.return byteToString(<val) + byteToString(>val)
}
.const SomeString = "ABCDEF" + wordToString($1234)
.print SomeString
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
@Ruk: That would of course require a 256 chars long table to avoid index out of bound. |
| |
ruk
Registered: Jan 2012 Posts: 43 |
@Cruzer
It was merely a proof of concept. But yes, it will break easily. AND:ing 'val' with $3F keeps you in range I suppose =) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
TWW: Im working on a new setup for the manual. Clickable table of contents and clickable list of directives are part of it.
Overkill?, Perhaps so. But Word have been bugging me for some time now, and integrating pdf+html generation in the builder will make new releases easier in the long run. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
@ Ruk: Thanx for pointing me in the right direction. I can do hi and lobytes from $00 to $40 8-D.
I'm not sure how I would succeed with and'ing to rid the two MSBs though. Is there a way to build the complete tabel somehow instead of manually typing it?
@ Cruiser: Yeah, and how to fricking fill in the rest of the "special and inverted characters".
@ Slammer: Nice! Looking forward to it. It's a good manual.
So I then have a refined question;
Is there a way to go from a byte (00-ff) to the corresponding petscii character without using a lookup table within the script language (probably not but can't hurt to ask)?
ex:
.print char(0) = "@"
.print char(3) = "C"
etc. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
@TWW: Yeah, that's what I was thinking from the start. :)
@Slammer: KickAss IS overkill, that's what makes it awesome :) |
| |
Conrad
Registered: Nov 2006 Posts: 833 |
Found another possible bug(?)...
I'm using KickAss (version V3.25) on a linux system (SlackoPuppy)... via the commandline:
"java -jar /mnt/sda3/CBM/TOOLS/KickAssembler/KickAss.jar -maxaddr -1 -aom -binfile -o /mnt/sda3/OC_SERVER/CBM/test.crt %f"
("OC_SERVER" is a mounted directory to a shared network drive of my Windwos PC, where WinVice is installed.)
The source I compile should output a large crt (EasyFlash format) which is roughly 129K... but when compiling the output binary through this shared network drive, it outputs around 69K (i.e. loss of file data).
Compiling the binary locally and then copying that file across to the network drive works fine.
I don't know if this is a Linux-Windows issue or not. When mounting the network drive, I use "nounix" and "noserverino" as parameters. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
>The source I compile should output a large crt (EasyFlash format) which is roughly 129K... but when compiling the output binary through this shared network drive, it outputs around 69K (i.e. loss of file data).
I assume you get no error messages. Since it outputs 69k it seams like you have set the maxAddr correctly.
1. Is the output cut when you compile it normally (no network drive, no binary)?
2. Is the output cut when you compile it as a binary?
3. Is the output cut when you compile it as a binary on the networkdrive?
(Also check if the code reallly should be 69k)
If 1 or 2 fails, i'll need some failing code to see whats wrong.
|
| |
Martin Piper
Registered: Nov 2007 Posts: 634 |
Network paths can operate slightly differently to local devices.
This problem can be caused by an unflushed fseek.
Before each fseek do a fflush. A flush before a fclose can also help. |
| |
Conrad
Registered: Nov 2006 Posts: 833 |
@Slammer
Quote:1. Is the output cut when you compile it normally (no network drive, no binary)?
2. Is the output cut when you compile it as a binary?
No, in both of these cases it outputs the full size fine. No errors etc.
Quote:3. Is the output cut when you compile it as a binary on the networkdrive? Yes, I'm executing KickAss from my laptop (linux OS), but the output path is via a network, where this problem occurs. The source code can be stored on either the network side or local side, but there is no difference. There's nothing wrong with my source code on its own.
@Martin: Yes I agree. I remember having this problem with network drives at where I work... having to using some flushing C functions as you mentioned. Maybe the java functions have the same issue? The JRE libraries on Linux might have issues too, but I don't know. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Try this one, http://www.theweb.dk/KickAssConrad.jar |
| |
Conrad
Registered: Nov 2006 Posts: 833 |
Quote: Try this one, http://www.theweb.dk/KickAssConrad.jar
Thanks Slammer, that one works perfect! :) |
| |
Claus_2015
Registered: Oct 2012 Posts: 53 |
Is there a reason why nested .pseudopc blocks are not allowed in KickAssembler? I stumbled over the problem when trying to relocate a loader (i.e. loading it to $0801 and moving it to $0300 for later use), that contains drive code, which is again in a .pseudopc block.
I would imagine that handling nested pseudopc blocks would be straightforward, as the outer block does not influence the inner block at all, or do I miss something here? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I wasn't aware that anybody would do that. It takes some extra management to keep track of all the simultaneous memory positions, so thats why it want implemented in the first place.
|
| |
Claus_2015
Registered: Oct 2012 Posts: 53 |
I would love to see this in an upcoming release. I think only with this feature you can reasonably have pseudopc's in a library, as relocating library code is something that at least I tend to do frequently. And pseudopc's are needed at least for all drive code.
When trying to circumvent this, I created the probably most ugly mess of {}-blocks that mankind has ever been exposed to :-). |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
This old idea I posted would allow for that and more: http://noname.c64.org/csdb/forums/?roomid=11&topicid=26156#44932
Perhaps it won't free you of all braces though. ;) |
| |
Claus_2015
Registered: Oct 2012 Posts: 53 |
Hi tlr,
I am not sure if I correctly understand your idea with the segments (I guess you are refering to his? The link only jumps to the beginning of the thread). It is more or less splitting memory areas into several parts, with the content being defined (or reserved) at arbitrary places in the source code, correct? How would that help the problem with the nested pseudopcs?
|
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Nested segments can contain different .pc which could be made to allow generating what you want.
Segments aren't strictly necessary but a concept of nestable scopes with different .pc settings will do the trick.
A way of dereferencing a particular label in any of the available scopes would be very useful too. I.e getting the non-virtual address of any virtual label an vice versa. I've suggested that elsewhere.
This of course gets a bit trickier to express with nested virtual .pc. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
New Manuals are out now.
- The PDF-version can be found here. (Now clickable)
- The WebHelp-version can be found here here. (Even more clickable)
Btw. I added a suggested reading for new users in the introduction. |
| |
Digger
Registered: Mar 2005 Posts: 421 |
Love you Slammer! Just-in-time before the X! :) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Hiho
I would like to code some stuff which gets encoded (rearranging bits and such) in the output file. Anyone who can give me a pointer on how to approach this task with the KA-Script language?
instead of:
lda #$00
becomming
#$a9 #$00
it would become somthing else when assembled.
Also, typo in your manual, page 16, table 4.2. String Values, "Converts the string to a oolean value (eg,
true.asBoolean())."
Should probably be "boolean value" |
| |
Mace
Registered: May 2002 Posts: 1799 |
I suggest you read chapter 10 of the manual, Modifiers. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
As Mace said, look at the modifiers functionality:
http://theweb.dk/KickAssembler/webhelp/content/cpt_Modifiers.ht..
Currently you will need to do it as a java plugin:
http://theweb.dk/KickAssembler/webhelp/content/cpt_Plugins.html
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
ok mace/slammer, thanx. That's what I thought. Time to brush up on java :-) |
| |
The Gothicman Account closed
Registered: Aug 2011 Posts: 40 |
Since this a Kickass-thread, this might a suitable place for my (surely stupid) question...
After 25 years I decided to have a little fun with c64 again.
Some things work, some not...
Anyway! My problem is:
Back in those days I used the following code to put some datas somewhere:
lda $0f00 (assume this would be located at $1000)
sta $d800,x
inx
blabla.
and then
inc $1001
lda $1001
cmp #$60
beq xxx
...
lda #$00
sta $1001
But how the hell can this be done in Kickass???
I'm sure it's fucking simple, but actually it drives me fuckin' crazy... :(
Thanx in advance... |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
simply use labels :)
yourlabel:
lda table,x
...
inc yourlabel+1
...
table:
|
| |
The Gothicman Account closed
Registered: Aug 2011 Posts: 40 |
That's exactly what I tried...
And it doesn't work...
As I said: Probably easy as hell, but something turns to be wrong... :( |
| |
The Gothicman Account closed
Registered: Aug 2011 Posts: 40 |
Allright...
I DIDN'T use labels...
I used vars... :(
Haha... I'm so... ... ... ;)
Thanx... |
| |
raven Account closed
Registered: Jan 2002 Posts: |
Hi
I'm trying to convert an old source of mine to KickAss format, but having a problem with something very basic.
I have sections of const declarations and code that sit inside if/else sections (works just like #if, #else in C).
I've been scratching my head for quite some time now, trying to find a simple solution, but couldn't!
If I use .if blocks, the consts I declare inside the .if scope are not seen outside, unless I use .define outside the .if, but thats really annoying with lots of consts...
Also, this does not work with labels & I dont feel like wrapping everything with blocks of .define and .if.
What am I missing?
Thanks :) |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Raven: If you use vars you can:
.var value = 0
.if (something) {
.eval value = 1
}
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:this does not work with labels & I dont feel like wrapping everything with blocks of .define and .if. What am I missing?
generally kickass does NOT have a preprocessor as you know from other assemblers, the .if stuff works fundamentally different. i find this very annoying myself, it often requires quite fucked up (and typing intensive) workarounds to do a whole lot of things i am used to from other environments. |
| |
raven Account closed
Registered: Jan 2002 Posts: |
Hi Cruzer
I'm doing this (just an example):
.if (DEBUG == 1) {
.const SomeVar1 = $4000
.const SomeVar2 = $4800
} else {
.const SomeVar1 = $5000
.const SomeVar2 = $5800
}
Problem is, the consts are not seen outside the if/else scope, without also using .define.
And what about labels, how do I make them seen outside?
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
you cant - fucked up workarounds are needed as i said (and be sure you only have two possibilites as in your example - if you have three or more things become *really* fucking ugly =P)
one that works for two is to write it like this (yes its annoying)
blabla = DEBUG == 1 ? $1234 : $5678 |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
How about this:
.var SomeVar1 = 0
.var SomeVar2 = 0
.if (DEBUG == 1) {
.eval SomeVar1 = $4000
.eval SomeVar2 = $4800
} else {
.eval SomeVar1 = $5000
.eval SomeVar2 = $5800
} Unless there's something consts can that vars can't. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Making a label visible outside requires a workaround like this:
.var label = 0
.if (true) {
label2: nop
.eval label = label2
}
jmp label
Doesn't work if you wanna access it before though, which I gotta agree is quite annoying. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Can you give me some 'real world' examples. I see two roads:
1. Create the possibility of multiple var declarations in the same var to ease the declarations outside the scope. Eg: .var a,b,c,d
2. Create some preparse commands, but I'm afraid to confuse people by having (Almost) the same functionality twice so I will need some code that shows how big the need are. |
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
What about adding something kind of handling of scope levels? ...such as being able to define lables with global scope within a sub-scope, as well as making a variable visible in its parent scope(s).
.if (CONDITION1) {
.if (CONDITION2) {
.var @0SomeVar1 = $4000 ;Make visible in global scope
.var @-1SomeVar2 = $4800 ;Make visible in parent scope
.var @-2SomeVar3 = $5000 ;Make visible in two levels of parent scope
} else {
.var @0SomeVar1 = $8000 ;Make visible in global scope
.var @-1SomeVar2 = $8800 ;Make visible in parent scope
.var @-2SomeVar3 = $9000 ;Make visible in two levels of parent scope
}
.var @0SomeVar4 = SomeVar2*2
}
More or less this is how it works in a few other assemblers I have tried. ..and it also resembles common keywords in all sorts of languages like putting the "global" keyword in front of variable declarations within a scope (e.g. "global int SomeVar = 0x04800;". |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Frantic, That is a possibility. The notation is a bit cryptic but i will do the job. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
I still don't get why people wanna declare vars inside if-blocks. Can't they just assign them? Of course it requires more typing to declare them before, but as Slammer suggested, it might help if you could declare multiple vars in one statement. I don't think this is worth introducing a new notation for.
Accessing labels inside if-blocks I can see the need for, although it's very seldom that I have actually needed it. But it would be nice to be able to use them like any other local labels inside blocks:block:
.if (true) {
label: nop
}
jmp block.label Of course there should be an error if the if-condition is false, but that would be like any other reference to a non-existing label I guess. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Yes. Examples is important to see whats nice or not. If xyz.myvar does the job then making hashtables implement this kind of notation is a nice solution.
.var opt = Hashtable()
.if(something)
.eval opt.myvar = 1234
else
.eval opt.myvar = 6789
jmp opt.myvar
It depends on the context in which the variables are used. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
sorry to say, but this looks needlessly overcomplicated. you guys really never used .if/.endif like they were supposed to be used in any other assembler? i somehow cant believe this =) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Its modelled after java/c++ and in this context it makes sence. There is also some evaluation concerns involved. You can evaluate a lot more with .if than a preparse #if and I guess if we make preparsing people will automaticly assume that you can put anything in the #if condition. Im not against preparsing and its absolutely a possibility, but I don't want to rush things and get alot of fixes that solves specific problems instead of one clean concept that can solve them all.
Can I see the code contructs you are using? Is it labels or options you are setting up this way?
Btw I just got a letter in my mailbox saying that I should demand tags on csdb in return for preparsing. :-)
Nothing is certain yet, but right now i'm considering a Kick Ass 4:
1. More flexible parse mekanism (Possiblity for ; as line comment,* instead of .pc and normal paranthesis instead of [] and leaving out : in front of macros/pseudocommands)
2. Possible to do 'skins' so you can support other assembler formats
3. Possibility to cover other processor types (while keeping the script language)
4. Making small constrains in the evaluations mekasnism to simplify the code in order to go open source.
5. Point 2 and 3 should be doable by plugins/ 3rd party development
So send me an example of 'ugly code' and preparsing will be taken into consideration.
|
| |
ruk
Registered: Jan 2012 Posts: 43 |
I've been using cmdLineVars in order to inject global constants, e.g. "debug", and some macros / functions to support this:
.function isDebug() {
.return cmdLineVars.get("debug") != null && cmdLineVars.get("debug").asBoolean()
}
.pseudocommand debugD020 {
.if (isDebug()){
inc $d020
}
}
.pseudocommand rebugD020 {
.if(isDebug()){
dec $d020
}
}
Works like intended, and I can surround debug code with isDebug() or use debugD020 without worrying where the debug-symbol is defined.
But it is a little quirky having to declare ":debug=true" on the commandline. I would rather see something similar to Java's "final static" in addition to the cmdlineVars hash.
Also, vars, consts and friends should respect the namespace they are declared in.
@Cruzer:
What about
block: {
label:
.if (true) {
nop
}
}
jmp block.label
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
"Can I see the code contructs you are using? Is it labels or options you are setting up this way?"
both. i use conditional assembling with labels inside if/then a lot, and also headers with defines that are switched for different configurations. and i honestly dont feel like showing more code just to see another proposed super ugly workaround as a response =)
"So send me an example of 'ugly code' and preparsing will be taken into consideration."
if whats shown in this thread doesnt already convince you, then all hope is lost - forget it. maybe kickass is for tables and not for code =P
"vars, consts and friends should respect the namespace they are declared in."
yes. and it should be possible to explicitly export them into the parent namespace. thats how any other sane assembler does it anyways =P |
| |
FATFrost Account closed
Registered: Sep 2003 Posts: 211 |
hi, i have a problem running Kickass, in osx i get
Exception in thread "main" java.lang.NoClassDefFoundError: kickass/jar
Caused by: java.lang.ClassNotFoundException: kickass.jar
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247
Do i need to update or install anything?
Any help would be appreciated!! :)
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
FATFrost: Did you remember -jar? E.g. java -jar KickAss.jar |
| |
FATFrost Account closed
Registered: Sep 2003 Posts: 211 |
er...let me have look// :)
|
| |
FATFrost Account closed
Registered: Sep 2003 Posts: 211 |
Yeahz!! got it working nice!! Thanks Cruzer!! |
| |
TWW
Registered: Jul 2009 Posts: 541 |
So Mads, I've got one question:
Question: Before I go ahead and make too many pseudocommands, is there any plans for implementing the 65816 OPC set? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
TWW: The short answer is no. I'm considering doing a hand made lexer/parser which allows people to insert their own instruction sets (from whatever processor you wish) while reusing the script language. This will take some time, so earliest release date (if any) will be about a year from now. So if I were you I would just go ahead with the pseudo-commands. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Fair enough. You've done very well to suply the sceene with this tool never the less. And hey, it's not that long to christmas ;-)
I have a question regarding pseudo-cmds (again):
.pseudocommand STZ val {
.if (val.getType()==AT_ABSOLUTE) {
// .if (val.getValue()<256) {
// .byte $64, <val.getValue() // Stupid ZP fix
// } else {
.byte $9c, <val.getValue(), >val.getValue()
// }
}
.if (val.getType()==AT_ABSOLUTEX) {
.byte $9e, <val.getValue(), >val.getValue()
}
.if (val.getType()==AT_ZEROPAGE) { // The pseudo don't recognize ZP adressing...
.byte $64, <val.getValue()
}
}
When I call the routine with a :STZ $00 the result produced is absolute and not ZP. AbsoluteX works fine though. Am I doing something wrong? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
When getting an argument like $80, and yet not know in which command its used, you don't know what address mode going to be used. It could be absolute, relative or zeropage.
jmp $80 // Absolute
lda $80 // Zeropage
bne $80 // Relative So the most basic form, absolute, is passed around and its up to the commands to decide if a specialised form is going to be used instead.
You can see the addressmodes pseudocommands recieve in table 7.2 here:
http://www.theweb.dk/KickAssembler/webhelp/content/ch07s03.html
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
So my "Stupid ZP fix" wasn't so stupid after all then 8-D
Not really important but any plans on including mnemonic extensions (ref. Table 3.4. in the manual) for psuedos? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Never thought of that. If there is a need then I'll put it in the todo list. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Good idea, TWW! I vote for putting it on the TODO list. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Aaannd... If you're really feeling like boored, include some more adressing modes in the extensions;
Program Counter Relative Long
BRL $1234
Stack Relative
LDA 15,S
Stack Relative Indirect Indexed Y
LDA (9,S),Y
Block Move
MVP 0,0
Absolute Long
LDA $123456
Absolute Long Indexed X
LDA $123456,X
Absolute Indexed Indirect
JMP ($1234,X)
Absolute Indirect Long
JMP [$1234]
Direct Page Indirect
LDA ($12)
Direct Page Indirect Long
LDA [$12]
Direct Page Indirect Long Indexed Y
LDA [$77],Y
Anyways, just a suggestion (And a boon for those of us who wishes to play more with the 65C816). |
| |
Carlos Account closed
Registered: Mar 2009 Posts: 15 |
Maybe this is a bit silly question but i'm starting with KickAss (and with asm in general...)
I have made a small macro library (change vic bank, change vic mode and things like that...) i have, for instance, a macro like:
.macro setBackground(color)
{
lda #color
sta $d021
}
nothing fancy, works ok if i use it.
Now i want use it from my mainloop to change the background color when i move the joystick up:
.var color = 0
read_joy:
lda $dc00
lsr
bcc joy_up
jmp read_joy
joy_up:
.eval color++
:setBackground(color)
jmp read_joy
i tought that the .var directive was the answer to my problem but seems that's only evaluated while assembling not during execution (so this code only works once).
Any idea how to set some kind of 'variable' in my main loop and use it as a parameter to a macro? |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Yes, variables and other fancy stuff is only evaluated during assembly. Nothing but the machine code is compiled to the executable, so it's not like a normal programming language where you can do color++ in "realtime". In your case you need a memory location to hold your color value, and a machine code way of incrementing it:
read_joy:
lda $dc00
lsr
bcc joy_up
jmp read_joy
joy_up:
inc color
lda color
sta $d021
jmp read_joy
color: .byte 0
|
| |
Carlos Account closed
Registered: Mar 2009 Posts: 15 |
Yeah.. this was my second approach but, as far as i know, i can't use a memory location as the parameter of a KickAss macro. I have tested it and the assembler gives no error but nothing happens:
read_joy:
lda $dc00
lsr
bcc joy_up
jmp read_joy
joy_up:
inc color
:setBackground(color)
jmp read_joy
color: .byte 0
|
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Change the macro to this, to avoid immediate addressing mode:
.macro setBackground(color) {
lda color
sta $d021
} |
| |
Carlos Account closed
Registered: Mar 2009 Posts: 15 |
Great! didn't notice that.. thks Cruzer. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Once you get more comfortable with the basic stuff, you can start using pseudocommands, which support both things at once.
.pseudocommand setBackground(color) {
lda color
sta $d021
}
:setBackground #color // Use predetermined value (immediate mode)
:setBackground color // Use value from memory (absolute mode)
Btw. The background color macro is just an example of how to create and use a macro. I guess you cant benefit much by using this particular macro.. |
| |
Carlos Account closed
Registered: Mar 2009 Posts: 15 |
Interesting Slammer, i will try it.
Another question: User defined structures. Can the fields of the structure be of any size or each field is always a byte?
.struct foo {x , y) (i want x be a word and y a byte) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
The struct directive is just a collection of fields with no particular type. The fields can be anything: Numbers, lists, strings, etc. For example:
.stuct MyStruct {a, b}
.var myVar = MyStruct(27, "Hello World")
.byte myVar.a // is the same as .byte 27
.print myVar.b // is the same as .print "Hello world"
In the above example only the '.byte myVar.a' directive will produce output to the assembled .prg file. It will be a byte because a .byte directive is used, but if you had written .word myVar.a it would have been a word.
hope it helped..
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
mmmmh. whats the difference between a struct and a namespace then? *shrug* |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
groepaz, you dont know the difference between namespace & structs ? i hope you are trolling :) |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Groepaz doesn't even know the difference between .align and .fill :P |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
Probably I'm off with this here, but do we really need all this mumbo jumbo for some simple 8 bit demo effects? Namespaces, structs, macros and whatnots ? :) Anyway its just probably only me still stuck in '96 or so, it would be nice to see some examples on how are these *really* useful. when it comes cycle counting and it comes to that even with non timing critical code, you'll WANT to see the code. Speedcode generators have to be written eventually when linking the demo (so why write once a macro, once a real version?)
etc.. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Pantaloon: Yeah, Obviosly trolling :-)
Oswald: No you don't need it, but it can make life easier. Just take the things you find useful into your programming routine and ignore the things that doesn't appeal to you. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Hiho
Got a strange error:
.eval BMPByte = BMPByte|[BMPPattern << [6 - Pixel*2]]
^
Error: Unknown function : <<
The code itself comes from this loop:
.for (var Pixel = 0 ; Pixel < 4 ; Pixel++) {
.eval PixelColor = Graphics.getPixel([[8*BlockNumber]+[[Pixel<<1]&7]]-[320*[floor(BlockNumber/40)]] , [8*floor(BlockNumber/40)]+Byte)
.eval BMPPattern = ColorIndex.get(PixelColor)
.eval BMPByte = BMPByte|[BMPPattern << [6 - Pixel*2]]
}
Which is inside a macro which I call 3 times and no problems but the 4th, this occurs.
If I reuse the macro a 4th time with earlier parameters, it works fine so it's something with the data processed the 4th time which makes it kneel.
Ideas?
EDIT: Found it. Wrong pallette in the gfx. Pro'lly caused some invalid data to be processed. |
| |
Carlos Account closed
Registered: Mar 2009 Posts: 15 |
Which is the most efficient way to do a simple multiplication (8bit operands and product) in KickAss? i mean without using tables.
The operands are not constant numbers instead variables (zeropage normally).
I have checked:
.function mul(op1,op2)
{
.return op1*op2
}
but this multiplies the value (address) of op1 and op2 not the value that are referenced by these address.
|
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
You can't. You can see kickasm as a preprocessor only. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Yup, the scripting language doesn't compile to c64 code. So a multiplication routine in KickAss would be pretty similar to any other assembler. |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
in the manual it should be made clear that Kickass will not compile stuff like this into multiplications and other magic stuff for you.
Maybe it would be a good idea though to create such a macro library tho, pseudo commands for mul/div, etc. it looks like there's a need. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
the manual is quite clear what can be done and not with macros. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
A macro/pseudocmd library would be great. Im sure most of us have our own. However, there is a difference between having a private library and a public one. When going public you will have to maintain it, and make a decent test of all ways of use. But It would be great if someone took the task. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
(EDIT: Use a wide screen to view this)
Some people have asked, 'do we really need the script language?', and the answer is 'no, but it can make life easier'. Some might think its only made for doing speed code and while you have to do code generators for the the final product anyway, so why bother? Well, I use it for rapid prototyping of speed code, but also for also for other cases, and here is one of them - generating (big) effect tables.
I find that when you are editing an effect table (control parameters for your demopart), or another kind of data structure, it's nice to have the values placed close together on the same line when you edit them, e.g.:
effect1: .byte Param1, Param2, Param3, Param4
effect2: .byte Param1, Param2, Param3, Param4
..
Why this is so, will become obvious when we later look at a practical example. However, the most effective way of accessing the parameters is to have each byte in a separate table so you can just write lda param1,x instead of having to calculate the start of the effect parameters, adding the offset etc.
Param1: .byte effect1, effect2,
Param2: .byte effect1, effect2, ...
Param3: .byte effect1, effect2, ...
Param4: .byte effect1, effect2, ...
To overcome this we write a structure for editing the parameters. To see this in action, here is a real life example. First we define a structure and some constants to be used when defining the effects.
.struct EffectParam { duration,
xstart1, xstart2, xadd1, xadd2, xscale1, xscale2, xcountAnd1, xcountEor1,
ystart1, ystart2, yadd1, yadd2, yscale1, yscale2, ycountAnd1, ycountEor1
}
.const NONE = 8
.const bar = 80
.enum {Scale1=0, Scale2=1, Scale3=2, Scale4=3, Scale0 = 4 }
And then the effect table. It's timed after the music and is rather large (You have to play the music through 3 times to see all effects), but luckily we can now write comments so we will know where we are relative to the music and what the effect does. (The comments might be deprecated, I just copy pasted this from actual code):
.var effectList = List().add(
// Song variation 1: Free first moves
EffectParam(/*Duration*/8*bar, /*X*/0,2,3,4,Scale2,Scale3,%1111,%000, /*Y*/4,6,1,5,Scale2,Scale2, %111,%000),
EffectParam(/*Duration*/8*bar, /*X*/NONE,NONE,1,7,Scale2,Scale2,%1111,%000, /*Y*/NONE,NONE,4,4,Scale2,Scale2, %111,%000),
// Song Variation 2
EffectParam(/*Duration*/4.5*bar, /*X*/0,0,4,4,Scale2,Scale2,%111,%000, /*Y*/2,2,4,4,Scale2,Scale2, %111,%000), // Circle
EffectParam(/*Duration*/3.5*bar, /*X*/0,0,4,4,Scale3,Scale3,%111,%000, /*Y*/6,6,4,4,Scale3,Scale3, %111,%000), // Circle inv
EffectParam(/*Duration*/4.5*bar, /*X*/0,0,4,4,Scale2,Scale2,%111,%000, /*Y*/2,2,4,4,Scale2,Scale2, %111,%000), // Circle
EffectParam(/*Duration*/3.5*bar, /*X*/0,0,4,4,Scale3,Scale3,%111,%000, /*Y*/6,6,4,4,Scale3,Scale3, %111,%000), // Circle inv
//--------------------
// Song Intro
EffectParam(/*Duration*/8*bar, /*X*/NONE,NONE,1,5,Scale3,Scale3,%1111,%000, /*Y*/NONE,NONE,3,7,Scale3,Scale3, %111,%000),
// Song variation 1
EffectParam(/*Duration*/3*bar, /*X*/NONE,NONE,3,7,Scale3,Scale3, %111,%000, /*Y*/NONE,NONE,5,6,Scale2,Scale4,%111,%000), // Call:
EffectParam(/*Duration*/1*bar, /*X*/ 7, 7,10,10,Scale1,Scale1,%111,%000, /*Y*/ 0, 0,2,0,Scale2,Scale2,%111,%000), //
EffectParam(/*Duration*/3*bar, /*X*/NONE,NONE,3,7,Scale2,Scale4, %111,%000, /*Y*/NONE,NONE,5,6,Scale2,Scale2,%111,%000), // Answer:
EffectParam(/*Duration*/1*bar, /*X*/ 3, 3,10,10,Scale1,Scale1,%111,%000, /*Y*/ 0, 0,2,0,Scale3,Scale3,%111,%000), //
EffectParam(/*Duration*/3*bar, /*X*/NONE,NONE,3,7,Scale2,Scale2,%111,%000, /*Y*/NONE,NONE,5,6,Scale2,Scale2,%111,%000), // Call:
EffectParam(/*Duration*/1*bar, /*X*/ 7, 7,5,10,Scale1,Scale1,%111,%000, /*Y*/ 0, 0,2,0,Scale2,Scale4,%111,%000), //
EffectParam(/*Duration*/3*bar, /*X*/NONE,NONE,3,7,Scale2,Scale2,%111,%000, /*Y*/NONE,NONE,5,6,Scale2,Scale2,%111,%000), // Answer:
EffectParam(/*Duration*/1*bar, /*X*/ 0, 0,2,0,Scale2,Scale4,%111,%000, /*Y*/ 3, 3,10,10,Scale1,Scale1,%111,%000), //
// Song Variation 2
EffectParam(/*Duration*/4.5*bar, /*X*/0,0,4,4,Scale3,Scale3,%111,%000, /*Y*/2,2,4,4,Scale3,Scale3, %111,%000), // Circle
EffectParam(/*Duration*/3.5*bar, /*X*/0,0,4,4,Scale4,Scale4,%111,%000, /*Y*/6,6,4,4,Scale4,Scale4, %111,%000), // Circle inv
EffectParam(/*Duration*/4.5*bar, /*X*/0,0,4,4,Scale3,Scale3,%111,%000, /*Y*/2,2,4,4,Scale3,Scale3, %111,%000), // Circle
EffectParam(/*Duration*/3.5*bar, /*X*/0,0,4,4,Scale4,Scale4,%111,%000, /*Y*/6,6,4,4,Scale4,Scale4, %111,%000), // Circle inv
//---------- Funny moves-------
// Intro
EffectParam(/*Duration*/8*bar, /*X*/NONE,NONE,7,2,Scale1,Scale2,%1111,%000, /*Y*/NONE,NONE,5,2,Scale1,Scale1, %011,%100), // + on y
// Song variation 1
EffectParam(/*Duration*/8*bar, /*X*/0,2,3,6,Scale2,Scale3,%111,%010, /*Y*/1,3,3,6,Scale2,Scale3, %111,%010), // Weird bump on both x and y
EffectParam(/*Duration*/8*bar, /*X*/NONE,NONE,3,7,Scale2,Scale0, %111,%000, /*Y*/NONE,NONE,5,6,Scale2,Scale0,%111,%000), // Single sine
// Song variation 2
EffectParam(/*Duration*/8*bar, /*X*/NONE,NONE,5,2,Scale2,Scale2, %101,%000, /*Y*/NONE,NONE,3,1,Scale2,Scale2,%111,%010), // Crazy push double sine
EffectParam(/*Duration*/4.5*bar, /*X*/0,0,4,4,Scale2,Scale2,%111,%000, /*Y*/2,2,4,4,Scale2,Scale2, %111,%000), // Circle
EffectParam(/*Duration*/3.5*bar, /*X*/0,0,4,4,Scale3,Scale3,%111,%000, /*Y*/6,6,4,4,Scale3,Scale3, %111,%000), // Circle inv
//-------------------
// Intro
EffectParam(/*Duration*/8*bar, /*X*/NONE,NONE,1,5,Scale3,Scale3,%1111,%000, /*Y*/NONE,NONE,3,7,Scale3,Scale3, %111,%000)
).lock()
Don't panic if you don't understand the meaning of all the parameters, its not important. Instead notice that we can now easily comment the data and divide it into sections. Its also easier to edit - copy/pasting or moving a set of parameters from one place to another suddenly becomes easy.
Now we have to store the parameters. But we also want to process the data a little before we store them. The duration can be more than 256 frames so we have to use two bytes, and the start parameters is only 4 bit wide so we can pack two of them into one byte with a lille function. Don't mind the details, just note that you can write your data in an easy understandable way and then process them to more optimal forms before storing them in memory. In our case it looks like this:
.function toStartByte(startPos1, startPos2) {
.var res1 = startPos1==NONE ? 1 : [startPos1<<1]
.var res2 = startPos2==NONE ? 1 : [startPos2<<1]
.return res1|[res2<<4]
}
.label noOfEffects = effectList.size()
durrationLoTab: .fill effectList.size(), <-[effectList.get(i).duration]
durrationHiTab: .fill effectList.size(), >-[effectList.get(i).duration]
xaddSin1Tab: .fill effectList.size(), effectList.get(i).xadd1
xaddSin2Tab: .fill effectList.size(), effectList.get(i).xadd2
xsinStartTab: .fill effectList.size(), toStartByte(effectList.get(i).xstart1,effectList.get(i).xstart2)
yaddSin1Tab: .fill effectList.size(), effectList.get(i).yadd1
yaddSin2Tab: .fill effectList.size(), effectList.get(i).yadd2
ysinStartTab: .fill effectList.size(), toStartByte(effectList.get(i).ystart1,effectList.get(i).ystart2)
xcountEorTab: .fill effectList.size(), effectList.get(i).xcountEor1
xcountAndTab: .fill effectList.size(), effectList.get(i).xcountAnd1
ycountEorTab: .fill effectList.size(), effectList.get(i).ycountEor1
ycountAndTab: .fill effectList.size(), effectList.get(i).ycountAnd1
xscale1Tab: .fill effectList.size(), effectList.get(i).xscale1 + >scale100Tab
xscale2Tab: .fill effectList.size(), effectList.get(i).xscale2 + >scale100Tab
yscale1Tab: .fill effectList.size(), effectList.get(i).yscale1 + >scale100Tab
yscale2Tab: .fill effectList.size(), effectList.get(i).yscale2 + >scale100Tab
Finally notice that the scale tab parameters (last four tables) are added with the hi byte of the first scale table (scale100Tab). The scripting is dependant on the code (scale100Tab) and the code is dependant on the effect table (The labels of the parameter tabs and the noOfEffect label). This two way dependancy makes it awkward to separate the generation of the effect table in another file, using another language and a makefile. In any case, I find it nice to have it right besides the rest of the code, without having to do additional setup.
So what we have done is:
1. Defined the effect table in the script language in an more readable and editable format
2. Transformed it in to a more machine friendly format automatically, instead of manually.
Without the ability to do this, I doubt I would have had the patience to set up effects for three runs through the music, and I wouldn't have the overview of the effect table that I have, if It was defined in the standard old fashion form. So clearly you can do a large effect table without the script language, but its pretty handy to have it available. |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
@slammer: interesting read on a good example! Cudos! |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Can't you do the same with 23 command line snippets and makefile? It will assemble AT LEAST 0,023 seconds faster...
/Irony off
Yeah I know, trolling isn't allowed but I couldn't resist. Sue me^^
Very good example illustrating the power and flexibility of using scripting. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
i cant conditionally include a sourcefile or define constants without pulling the ugliest stunts ever - but thank god i can do super specific stuff like this =) making life easier the java way =) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hello Gropaez. Im sure you have already found another assembler. If not, I can only encourage you to do so. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Hehe @ TWW... Yeah, very good example by Slammer. Other uses:
Generating small chunks of speedcode and data, that are so small that it doesn't make sense to do a c64 generator for them, e.g.
lda spriteColor
.for (var i=0; i<8; i++) {
sta $d027 + i
}
Generating bigger chunks of speedcode and data that are so complex that generating it on c64 would take longer than loading it from disk.
And my favorite, randomizing parameters and printing them out. Then you can just assemble the code over and over to see new variants of the effect, and whenever something looks good, copy/paste the params into the code. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
slammer: convince peacemaker to use another assembler, and i won't touch kickass ever again - promised =P |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Gropaz: Lol. You do realise that your behaviour have put all of your requests to the backend of the queue, right? If you really are forced to use Kick Assembler, putting yourself in a position with no influence on future features, really seams like an excellent strategy. ;-) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
sorry, couldnt resist:
; x1 y1 etc
effect1: .byte Param1, Param2, Param3, Param4 ;circle1
effect2: .byte Param1, Param2, Param3, Param4 ;circle2
init
lda #<effect1
sta zp+0
lda #>effect1
sta zp+1
rts
setupeffect
ldy #$00
lda (zp),y
sta durationlo
iny
lda (zp),y
sta durationhi
iny
lda (zp),y
sta xadd1
iny
lda (zp),y
sta xadd2
iny
lda (zp),y
asl
asl
asl
asl
iny
ora (zp),y
sta xstart1&xstart2
iny
lda (zp),y
sta yadd1
iny
lda (zp),y
sta yadd2
iny
lda (zp),y
asl
asl
asl
asl
iny
ora (zp),y
sta ystart1&ystart2
iny
lda (zp),y
sta xeor
iny
lda (zp),y
sta xand
iny
lda (zp),y
sta yeor
iny
lda (zp),y
sta yand
iny
lda (zp),y
clc
adc #>scaletab
sta xscale1
iny
lda (zp),y
clc
adc #>scaletab
sta xscale2
iny
lda (zp),y
clc
adc #>scaletab
sta yscale1
iny
lda (zp),y
clc
adc #>scaletab
sta yscale2
iny
tya
clc
adc zp
sta zp
bcc *+4
inc zp+1
|
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: sorry, couldnt resist:
; x1 y1 etc
effect1: .byte Param1, Param2, Param3, Param4 ;circle1
effect2: .byte Param1, Param2, Param3, Param4 ;circle2
init
lda #<effect1
sta zp+0
lda #>effect1
sta zp+1
rts
setupeffect
ldy #$00
lda (zp),y
sta durationlo
iny
lda (zp),y
sta durationhi
iny
lda (zp),y
sta xadd1
iny
lda (zp),y
sta xadd2
iny
lda (zp),y
asl
asl
asl
asl
iny
ora (zp),y
sta xstart1&xstart2
iny
lda (zp),y
sta yadd1
iny
lda (zp),y
sta yadd2
iny
lda (zp),y
asl
asl
asl
asl
iny
ora (zp),y
sta ystart1&ystart2
iny
lda (zp),y
sta xeor
iny
lda (zp),y
sta xand
iny
lda (zp),y
sta yeor
iny
lda (zp),y
sta yand
iny
lda (zp),y
clc
adc #>scaletab
sta xscale1
iny
lda (zp),y
clc
adc #>scaletab
sta xscale2
iny
lda (zp),y
clc
adc #>scaletab
sta yscale1
iny
lda (zp),y
clc
adc #>scaletab
sta yscale2
iny
tya
clc
adc zp
sta zp
bcc *+4
inc zp+1
Yes and Slammer's point was that you get the same readability in the code (i.e. parameters kept together in chucks _AND_ directly in the source). However Slammer's example will produce more effective code on the C64-side. Instead of having to "parse" the params manually on the C64 each time you setup the effect this is done at compile time. This yields:
* Smaller code
* Faster code
* Same readability
win/win/win
And yes, the faster/smaller point will probably be insignificant anyway so... use whatever method you're comfy with.
:D |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
agreed.
for me more of a selling point is the nice capability of importing gfx/textures, or calculating sines, but am simply yet too lazy to make the move. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Just make the move for new stuff. No need to convert all your unreleased stuff right away. I still have old crappy routines in MxAss and TurboAss format lying around. |
| |
soci
Registered: Sep 2003 Posts: 473 |
Right, 1.46 is quite bit outdated now. Creating sine and other tables is easy on 1.5x if that helps.
Importing raw data is no problem with almost any assembler. If it needs serious processing beyond chopping it up into pieces (e.g. conversion, compression, etc.) it's better to use the most suitable language/tool to do that part of the job first. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:Gropaz: Lol. You do realise that your behaviour have put all of your requests to the backend of the queue, right? If you really are forced to use Kick Assembler, putting yourself in a position with no influence on future features, really seams like an excellent strategy. ;-)
i realised its pointless to argue about these things many moons ago, and that omitting certain core features is apparently a design goal of this assembler. if you think i am still expecting you to fix them, no. you have made clear you dont care at all and dont even understand why you should do that. (another point for ca65 here, or rather for Uz) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
tastes are different there are enough types of assemblers out there for everyone, kickass is amongst the best, and I respect slammer for it. compilers are amongst the most complex things one may code. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Groepas: I actually agreed with you, that some of your request would be nice to have and put them on the todo list. But since they didn't get implemented at once you got very aggressive and insulting. Do you actually expect people to hurry up using their spare time to implement the features you want, after you insult them? I thinks that your behaviour against me and several other people here on csdb speaks for it self. You really owe a lot of people an apology. |
| |
Burglar
Registered: Dec 2004 Posts: 1031 |
now, now, boys. no need to get all frisky ;)
I like kickass a lot, and it would be even better if the suggested changes got implemented (like incbin). |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Burglar: Incbin is one of the things that is on the todolist. Meanwhile check this thread for how to define a macro in 4 lines that can do the exact same thing : Need a coder |
| |
Lead
Registered: Dec 2004 Posts: 20 |
I couldnt find a better topic to post this in, but I've got a naming challenge for macros with Kick.
If I use one of the macro's of Codebase, or write one myself, I would like to use the filename of this macro to name the memory area properly in the Memory map output of Kick. But whatever I seem to do, I cannot attach the filename to be part of the name of the memory area.
There's probably a way to do it but I cant find it in documentation, this form or anywhere.
The macro might look something like (pseudocode):
.macro MacroName (filename, address) {
.pc = address "Tables"
}
I would like to add the filename as send to the macro the the memory name (MyName) so it would be something like "Tables "+filename but i keep getting errors.
What is the proper way to use one of the variables send to the macro as part of the memory area name ? |
| |
ruk
Registered: Jan 2012 Posts: 43 |
@Lead: I've previously failed numerous attempts of doing the same thing. My conclusion is that the .pc directive can *only* take a string and not an expression as an argument for the name.
If you're reading this Slammer, +1 for supporting this :-) |
| |
Lead
Registered: Dec 2004 Posts: 20 |
Yes I'm afraid so aswell, hope Slammer sees, support for variable names would be awesome for those that want to keep an organized eye on the memory map.
I was afraid the way I subscribe was not beeing understood by people as there was little reply. I will try to explain a bit more accurate so people know what I mean for sure ;)
Here's some coding, this is not a function I created to use in production but more as a test :
.macro getFile(fileName, loadAdr) {
.pc = loadAdr "Image"
.var picture = LoadPicture(fileName, List().add($444444, $6c6c6c,$959595,$000000))
.fill $800, picture.getMulticolorByte(i>>7,i&$7f)
}
use with :getFile("image.png", $2000)
This will correctly load a file to memory at $2000 and will show up in memorymap like this when you have more images :
Memory Map
----------
$0801-$080c Basic
$0900-$0910 Main Code
$2000-$27ff Image
$2800-$2fff Image
$3000-$37ff Image
That's where I want to keep my namings in order ;) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi, I do check this thread, so any questions asked will be answered eventually. Also, I wanna stay a bit in the background to give other users room for stating their views and experiences.
In the case of the PC directive, you are right, the .pc directive only takes a string, not an expression. I don't think it will be a big deal to change so I'll see what I can do. |
| |
Lead
Registered: Dec 2004 Posts: 20 |
Hi Slammer thanks for confirming, I understand and think you do the right thing with staying a bit in the background so others can share their thoughs aswell.
In this case though it seems that there are very little people the came across this iussue or had anything to say about it (other than Ruk). You're right on the fact that eventually stuff gets answered in this thread... I've been reading this one all the way. there's some good stuff hidden below ;) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Lead: Its always cool to know how other people does things, and with discussions in the KickAss-facebook group and by mail together with doing a bit of demo stuff and some other projects its hard to get time to code new features for Kick Assembler. That why i really want to encourage people to help answering questions.
Btw. The official 'Kick Assembler Wish List' is in the facebook group. Feel free to drop by and enter your wishes. |
| |
Lead
Registered: Dec 2004 Posts: 20 |
I just got on the MickAss facebook and saw there is no need for me to add it to the feature request list as it allready is there :
- Auto naming of memory blocks after variables, so you can write: .pc = coolRoutine, and it shows up as coolRoutine in the memory map, instead of "unnamed".
At least, I assume this is the same as I requested. I'll keep an eye on that page and hope this will be implemented in a future update :)
If I come up with other idea's you;ll see them either here or there... |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I gave it a look and found out that both the name and virtual parameters are optional which makes it impossible if we shall maintain backwards compatibility since the parser can see the difference between a string and a indentifer, but not between an expression and an identifer.
Technical talk, i know.. However the wish stays on the wish list. I might revice the .pc syntax in a later version. |
| |
Mace
Registered: May 2002 Posts: 1799 |
What about a .name directive with a more elaborate syntax, in addition to what is already possible?
.pc = $2000
.name fileNameOfMacro + " at " + * // result: myMacro.asm at $2000
|
| |
Fresh
Registered: Jan 2005 Posts: 101 |
Hi slammer,
first of all thanks for a great tool.
I have a little problem with "arrays of labels". This kind of problem is partially solvable (pantaloon already pointed out a working solution in this thread) but it can't be used in every contexts.
The sample code:
.var test=List()
.for(var i=0;i<10;i++)
.for(var j=0;j<random()*20;j++)
{
.eval test.add(*)
.byte i
}
main:
lda test.get(0)
rts
This works fine but using a List to store the addresses brings some problem if I need to swap code and data:
.var test=List()
main:
lda test.get(0)
rts
.for(var i=0;i<10;i++)
.for(var j=0;j<random()*20;j++)
{
.eval test.add(*)
.byte i
}
This clearly doesn't work because I'm trying to get values from a List which is still empty.
So, based on my example, what to do if the code needs to be located *before* the data? Maybe defining a List of ".label" which may be evaluated after some passes? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Good question. I can tell you that I had the same problem as late as december where i had some cyclic references in the code, meaning no matter which code you place first you will always get an error. Currently, I got no solution ready yet, but I am thinking about some approches.
If you need a solution now, you might try to have two versions of you code. A virtual (.pc = $1000 virtual), and a non virtual (.pc = $1000), and place them in this order:
1. Virtual version of code, that calculates the label array
2. Dependant code that uses the label array
3. Real (nonvirtual) version of code
If you place the code inside a macro with the label list as argument you only have to define it once. I havn't tried that approch yet though. |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Hi,
I'm still new to kickassembler and found this thread - in need to continue with the question about conditional assembly.. But it's not exactly the same. I needed something like this to remove some debug code from the final product (simplified example):
.label DEBUG_MODE=1
.if (DEBUG_MODE==1) // debug mode
{
lda #$00
sta $d020
MODIFY_THIS:
lda #$00
sta $d020
}
lda #$00 // normal or debug mode
sta $d020
.if (DEBUG_MODE==1) // debug mode
{
inc MODIFY_THIS+1
}
rts
..which gives "Error: Unknown symbol 'MODIFY_THIS'"
So i needed to pull all labels like MODIFY_THIS out of .if, to get it compiled:
.if (DEBUG_MODE==1) // debug mode
{
lda #$00
sta $d020
}
MODIFY_THIS:
.if (DEBUG_MODE==1) // debug mode
{
lda #$00
sta $d020
}
lda #$00 // normal or debug mode
sta $d020
.if (DEBUG_MODE==1) // debug mode
{
inc MODIFY_THIS+1
}
rts
Are there any better way of doing similiar conditional assembly such like this? I don't even know which order kickass parses the asmfile, but this is just strange. Is that the same scope issue in question? I got a plenty of SMC labels like Something=*-1 so my code looks like ANYTHING else but CLEAN because of this :)
How you would create that kind of label touching code? I spent just several hours just because of this... |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
To my knowledge the labels are limited to it's scope.
One way of doing the thing you want could be this.
.label DEBUG_MODE=1
.var MODIFY_PTR = 0
.if (DEBUG_MODE==1) // debug mode
{
lda #$00
sta $d020
.eval MODIFY_PTR = *
lda #$00
sta $d020
}
lda #$00 // normal or debug mode
sta $d020
.if (DEBUG_MODE==1) // debug mode
{
inc MODIFY_PTR+1
}
rts |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
seems overcomplicated.. how about:
lda #debug_mode
sta $d020
or:
if debug_mode
inc $d020
else
sta $d020
etc. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:Are there any better way of doing similiar conditional assembly such like this?
use an assembler that properly supports scoping. |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
i was waiting for that comment from Groepaz :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I guess Groepaz is the kind of person who goes down to the store to buy a tool so he can cook an egg. The clerk sells him a frying pan and the next day he comes back complaining that the pan is a terrible pot and that he can't get the egg hard-boild!
Groepaz: I think you mean an assembler that does not support scoping, not an assembler that supports scoping properly. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
i mean exactly what i said. and no, "not the right tool for the job" does not apply here at all. hardly any other assembler is broken like this. |
| |
soci
Registered: Sep 2003 Posts: 473 |
Works as designed, it seems. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
i am not doubting that at all :) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
"I got a plenty of SMC labels like Something=*-1 so my code looks like ANYTHING else but CLEAN because of this :)
How you would create that kind of label touching code? I spent just several hours just because of this..."
I guess its a matter of habit what's comfortable & clean to you. I usually do this:
smod lda #$00
sta $d020
inc smod+1
this keeps the label and the instruction on the same line *-x wont fuck up, since you cant insert extra instruction inbetween, furthermure its obvious where the label points no *+ fucking, and one label is enough to reach lo/hi / instruction.
if the branch is really close then just:
inc $d020
jmp *-3
lda #$03
adc $02
sta $02
bcc *+3
inc $03
but I only use it in very simple cases like this. if you insert an instruction and forget to update the * you're fucked. |
| |
soci
Registered: Sep 2003 Posts: 473 |
Oswald, that was a good example why using *+ and *- is really error prone:
bcc *+3
inc $03
|
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
hey, that way debugging never becomes a bore! =) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
Quote: Oswald, that was a good example why using *+ and *- is really error prone:
bcc *+3
inc $03
*+4, got me there. I use those without knowing what happens, now I got exposed. i never know if the * refers to the instruction or the operand... and just too lazy to think about it for a minute O:-) I only use them to avoid the 125th skip label. |
| |
soci
Registered: Sep 2003 Posts: 473 |
The current location symbol (*) is traditionally the location at the beginning of the line in many assemblers. That is before any bytes are output for opcodes and other stuff.
Unfortunately the handling of this is broken in this assembler (e.g. in v3.34), or at least it's hard to defend the way it works.
Simple stuff is fine, e.g.:
jmp *
results in (assembled to $2000):
00 20 4c 00 20
But let's see something else:
.word *, *
results in:
00 20 04 20 04 20
while the expected result is:
00 20 00 20 00 20
Yes, I also got this wrong too in some special cases in a different way just until 3 years ago.
For those hundreds of skip labels I use "anonymous" labels. Of course moderately, as copy-pasting skip label containing code in between is a sure way to get a long lasting debug session ;) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
well, 16 bit addition like that sort of works like a macro from my head, unless I get rusty like now. Editing is a bit easyer if you dont have to carry around the anonymous label definition ("+") too, just have the *+. :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Soci: Interesting details about the *. I didn't know of the 'start of line' convension for all directives and never used * together with '.word'. Could you give an example of where this is usefull with the word/byte directive? Which assemblers use it, and which don't? Since KickAssembler, like languages as C# and Java, are throwing lineshifts away in the preprocess, it will be a 'start of directive'-convention instead of 'start of line' (In kickass, you can write several commands on one line). Seams like a good convention. |
| |
soci
Registered: Sep 2003 Posts: 473 |
Start of directive/opcode is fine instead of line start, then it's consistent at least.
It works like this in acme, dasm, dreamass, tasm/tass, xa, nasm and maybe some others. ca65 has it wrong just as old 64tass versions, but at least both give correct results for code like below.
A useful example which stores 7 at len instead of 6.
txt: .text "abcdef"
len: .byte *-txt
|
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Looks like Pantaloon's example solved the issue, thanks! - Ofcourse partially only, but it looks nicer now.
Oswald, the reason why i put it in .if is that when i give my code to another guy, he can just set DEBUG_MODE=0 flag in the beginning and compile to get SMC optimized final product.
So, if the very original code looked like this:
// (!) Remove the section below from final product!
SET_AVAR .byte 0
SET_XVAR .byte 0
SET_YVAR .byte 0
...
DEBUG_proggie:
lda SET_AVAR
ldx SET_XVAR
ldy SET_YVAR
...
SMC-converted program would be something like this: (faster+smaller):
// (!) Remove the section below from final product!
DEBUG_Proggie:
lda #0 .label SET_AVAR=*-1
ldx #0 .label SET_AVAR=*-1
ldy #0 .label SET_YVAR=*-1
...
Cute and nice. And I don't need to tell the another coder that he has to change all "sta SET_AVAR" etc into "sta SET_AVAR+1" (or +2 for words etc..) instead. That's the whole idea. But there's another thing left: The "Remove this section"... well, think there were 10 cases each put somewhat 10 pieces, that would result up to 100 code pieces to check through. There comes conditional assembly handy.
So instead of mentioning "Remove these sections.." i can just
.label DEBUG_MODE=1
...
.if (DEBUG_MODE==1) {
DEBUG_Proggie:
lda #0 .label SET_AVAR=*-1
ldx #0 .label SET_AVAR=*-1
ldy #0 .label SET_YVAR=*-1
}
But ofcourse not it doesn't work like this, so it turned out something like this:
.label DEBUG_MODE=1
...
DeBUG_Proggie:
.if (DEBUG_MODE==1) {
lda #0 }
.label SET_AVAR=*-1
.if (DEBUG_MODE==1) {
ldx #0 }
.label SET_XVAR=*-1
.if (DEBUG_MODE==1) {
ldy #0 }
.label SET_YVAR=*-1
And that was barely somehow readable...
Before someone nitpicking this was actually an oversimplified example. :) |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
About the * issue.. i was in thought that such errors shouldn't occur.. considered it a bug... so i did a choose to only use labels (tass), just to make sure avoiding erraneous pointers after compile.
One thing i never understood: Why anonymous labels and such, why not using plain labels anyway for branches and all? (Be it that C64 tass has limited space for labels, but for crossdev stuff like kickass we try to keep labels at minimum..?!) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
"lda #0 .label SET_AVAR=*-1"
now which one is more readable that or
"avar lda #0" ? :)
"And I don't need to tell the another coder that he has to change all "sta SET_AVAR" etc into "sta SET_AVAR+1" "
other coder should realize what you're doing after having seen how AVAR is defined and used. my method or yours, doesnt matter. if he is defined method agnostic :)
how about this:
"lda $1000 .label SET_AVARLO=*-1 .label SET_AVARHI=*-2"
still readable ?
the problem with your debug code is kickass, it shouldnt define the conditinal code sections as scopes automagically.
I dont like all that bracketing stuff either, in 64tass its just .if .fi the end.
* stuff, after the 12000th label you get tired of having to think of and type in another dummy one, which wasnt already used. bcc *+4 can be written without any thinking, duplicate checking. |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
The latter is more readable ofcourse. But its readability is just for me, the other coder doesn't need to edit it at all. Only compile in general. And all data variables that previously pointed to some .byte array now points to SMC operand and still no need to change any labels in his code to point to *+1 instead.. See what i mean. :)
I see your point, but is there any other means at all to nicely access the operand by label pointer instead of opcode? Atleast that i haven't seen such in any assembly specifications... you know better.
And the point of having conditional assembly and flags is to get rid of that code easily. A good example is SDI, it's almost a miracle that some conditional assembly works in c64 tasm! ;) |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Well i use nowadays some prefix to labels and stuff, f.e. music routine calls could be just M_INIT, M_PLAY and M_PLAYMSPD. Can't mix. The * stuff was never self-explanative to me and easily messed up with some other similiar looking routine. For zeropage variables i always named the labels as ZPnnn and ZWnnn (for wordsize). Not just lda ($fa),y stuff, which was possibly conflicting pointer by other routine.. for example. I leave the other methods for True Programmers :) |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
"s there any other means at all to nicely access the operand by label pointer instead of opcode?"
dont know anything better. possibly you can script this in kickass by generating labels from stuff like:
VAR lda #$00
in 64tass style: var2 = var +1 ;)
btw I'm still guilty of using (fa) (fe), but I keep them now as labels (no $ infront), its just faster to type them out, and I have my own patterns where I use them and what to. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:the problem with your debug code is kickass, it shouldnt define the conditinal code sections as scopes automagically.
noooooooo /o\ |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
I have a suggestion to kickass developers.
I think there is atleast 3 possible ways to deal with scopes (if you want to take my note on future versions of kickass)
The first one is a dirty addition:
{ // This is a scope
}
#{ // This one is unscoped
}
It could be also "-{" or "{{" instead of "#{" or such, you got the idea. Will be treated as same level as parent scope or main.
The another method could be a Global assignment to a label/var/constant definition:
.global label yesbox=$1234
...and "yesbox" could be then accessible from anywhere the whole source file, visible to all scopes. That's not standard assembly, but is kickassembler syntax any standard assembly anymore at all? :)
Then the third idea:
.scopeless (or .disable_scoping)
...and all scopes below this line would be treated as non-scopes, until .enable_scoping is reached to enable
Shouldn't be hard to implement in future version kickass and neither would break the current codings made with kickass i guess? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Soci: Thanks, Its corrected in the new version 3.39 just released.
Agemixer: Thanks. If you join the facebook group (https://www.facebook.com/groups/RetroAssembler/) you will get access to the official Kick Assembler Wish List, where you can enter your ideas. It's also a good place for discussing ideas.
I don't know if you have noticed, but you can enter normal scopes like this:
Function1: {
col: lda #01
sta $d020
rts
}
Function2: {
inc Function1.col+1
rts
}
This will ofcause not solve the if-problem. |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Because i haven't found any examples how to produce C64 ascii with kickassembler, here is mine:
.function pet2asc(p) { .eval p = [ p>$40? p+=$80 : p ] .return [ p<$20? p^$40 : p ] }
.macro asctxt(str) { .fill str.size(), pet2asc(str.charAt(i)) }
.macro asctxtCR(str) { :asctxt(str) .byte $0d }
ldx #$00
loop: lda text,x
beq end
jsr $ffd2
inx
bne loop
end: rts
text: // C64 ascii
.byte 5 // color = white
.byte 147 // clr+home
.byte 9,14,8 // case change: enable C= + shift, set locase, disable
:asctxt("Hello World!")
:asctxtCR(" 1,2,3,4...")
:asctxtCR("")
:asctxt("The quick brown fox ")
:asctxtCR("jumps over the lazy dog")
.byte 0 |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Thanks Slammer |
| |
Murphy
Registered: Jul 2006 Posts: 10 |
Slammer: Thanks for this awesome assembler!
Support of |= (and &=) operators are planned? |
| |
Murphy
Registered: Jul 2006 Posts: 10 |
I found a strange issue with the asserts.
.assert "Key is valid=", tab.containsKey(key), true
.var actList= List().addAll(tab.get(key))
The tab is a Hashtable which contains lists.
When the value of the key is invalid, i get an error:
cml.kickass.values.NullValue cannot be cast to cml.kickass.values.ListValue
It looks, the assert interpreted later than the addAll. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi Murphy
|= and &= can easily be implemented so it goes on the todo list (Feel free to enter the Facebook group and add them yourself).
In some cases KickAssembler can skip parts of evaluation if it doesnt have enough information to do the evaluations. Assert is not asserting before both values are valid and invalid values can occur if you base you calculations on labels that is not yet resolved.
However I would like to see your code, Could you shortend it to a small example and send it to me? You where not supposed to get a cast execption but a "Invalid argument. It has to be a list."-message in case of null. |
| |
Murphy
Registered: Jul 2006 Posts: 10 |
Thanks Slammer! The source was sent in PM. |
| |
Murphy
Registered: Jul 2006 Posts: 10 |
I know this is a complex request...
but string concatenating for label names can be very usefull in macros. Of course, only when the label can be 'exported' out of the scope of the macro.
Example code: register saver macros for irq.
.macro SaveRegsImm(reg_cache) {
sta reg_cache#_a
stx reg_cache#_x
sty reg_cache#_y
}
.macro LoadRegsImm(reg_cache) {
.label reg_cache#_a = *+1
lda #0
.label reg_cache#_x = *+1
ldx #0
.label reg_cache#_y = *+1
ldy #0
.public reg_cache#_a
.public reg_cache#_x
.public reg_cache#_y
} |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I just released v3.40, where you will get a normal errormessage instead of a class cast exception when you suply a non-list-value to the addAll method.
I don't see anything that could be tricky with the assert, and it asserts fine here. Are you sure the given parameter is in the table?
About concatenating label names. I think it will a bit too complex. Basically, I have to be able to scan for labels and know their names. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Murphy: Btw. are you aware that you can access variables of executed macros by adding a label on the line that executes the macro:
.macro SetColor() {
color: lda #00
sta $d020
}
...
lda #1
sta x.color+1 // Set color in first execution of macro
lda #2
sta y.color+1 // Set color in second execution of macro
x: :SetColor()
y: :SetColor()
Perhaps this will solve your concatenation problem. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Btw. One thing about the assert commands. They don't stop execution if they fails. Instead they remember the error and print them out at the end of execution (If no 'hard' errors occurs.) They are primary made so I could have a testsuite to run before each release (currently 615 asserts)
I guess this explains your original problem :-)
http://theweb.dk/KickAssembler/webhelp/content/cpt_Testing.html |
| |
Murphy
Registered: Jul 2006 Posts: 10 |
Thanks Slammer!
Your solution is much more elegant than mine!
It's a shame that I haven't noticed this in the documentation. :) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
From my -PNGtoKOALA routine I get the following error:
.for (var Pixel = 0 ; Pixel < 4 ; Pixel++) {
.eval PixelColor = Graphics.getPixel([[8*BlockNumber]+[[Pixel<<1]&7]]-[320*[floor(BlockNumber/40)]] , [8*floor(BlockNumber/40)]+Byte)
.eval BMPPattern = ColorIndex.get(PixelColor)
.eval BMPByte = BMPByte|[BMPPattern << [6 - Pixel*2]]
^
Error: Unknown function : <<
I've used it before and it worked fine so what the heck am I missing?
EDIT: Found out. Had some "ghost pixels" with different RGB codes in the GFX I was converting... Funtion works as intended. SOLVED. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
BMPPattern contains a value for which the << operator is not defined. Could it be null? |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Yepp. That was precisely it. |
| |
Killsquad Account closed
Registered: Jun 2005 Posts: 17 |
Any update on .ifdef/.ifndef directives? Would be very handy. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
The basic directives are implemented as know from C# (#define, #if, #else, #elif, #endif, #undef). Currently missing is setting definitions from the commmand line and boolean operatiors. But they will be there, don't worry.
Other nice things which are already implemented are:
- The * is back, *=$1000. (You can still use .pc)
- You can now use normal ( ) aswell as [ ]
- You can add an optional ; in the end of commands, eg: .eval x=27;
+ Some other goodies
The reason it takes time is that they are part of a bigger modification, where the entire parsing routine is reimplemented. Instead og using a parsergenerator, most of it is now done by handwritten code which gives more flexability. This will be in the next major version (4.0). I guess it will take at least a couple of months finish. |
| |
Murphy
Registered: Jul 2006 Posts: 10 |
Slammer: Really great improvements!
I can't wait! :) |
| |
Killsquad Account closed
Registered: Jun 2005 Posts: 17 |
That is great news, Slammer. Looking forward to it. |
| |
subjik
Registered: Dec 2001 Posts: 5 |
Is anyone else having problems after updating OSX to El Capitan? On Build & Run everything works fine except that Vice exits immediately after it starts. Any tips how to solve this? |
| |
Pantaloon
Registered: Aug 2003 Posts: 124 |
great news, will 4.x version be released before christmas ? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Panta: Yes, thats the plan. The main functionality has been ready for two months or so, but is not testet properbly. There is probably also going to be some adjustments before errormessages from the new parsing is good.
Right now I'm experimenting with some extra functionality that can give info about the source code (syntax elements and errors) + info of build in directives and macros back in realtime to editors (not necessarily written in java). With that it gets a bit easier to test the new parser and perhaps more advanced editors if people are going to incooperate it ;-)
So the plan is that Kick Assembler 4 will be release this year, and if time is running out some of the editor functionality will be left for next version. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
subjik: I haven't updated yet. Hoping to hear from others who have. |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Are there plans to introduce more handy arrays with x dimensions instead of workaround with list and hashtags? ;) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Quote: Are there plans to introduce more handy arrays with x dimensions instead of workaround with list and hashtags? ;)
Not currently. You can use lists of lists to get multidimensional arrays.
If you need it, you can put it in the wishlist on the facebook-page. |
| |
Dr.Science
Registered: Oct 2011 Posts: 39 |
Having the same issue as Subjik on OSX! |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Ok, Could I get you to post the exact commandline you are using to run KickAssembler |
| |
Dr.j
Registered: Feb 2003 Posts: 276 |
@Slammer: could be nice if possible to do such thing
like: .align $100 "my label" for the memory map. so to
expand the names not only for the .pc=$1000 "my label" .
your KA is the ultimate tool for coding in my eyes ;) |
| |
Magic Man Account closed
Registered: May 2015 Posts: 3 |
I have the same problem with OS X El Capitan. I found out that there is a very small workaround.
Just put the following directive somewhere in the code (i have it last):
.var elCapitanStartFix = LoadPicture("fix.gif", List().add($000000, $ffffff))
And have a fix.gif file which is like a one dot gif. Since you never do anything with the variable it doesn't change you produced program.
~Stephan
Magic Man/Crazy |
| |
Dr.j
Registered: Feb 2003 Posts: 276 |
sorry for not resist myself and a big off the the topic
but Welcome Magicman i love your stuff back on "Crazy" days you were more than cool :) nice to see you here |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I upgraded to El Capitan today, and I see your problem. I have also found a cure, but it requires some manual parsing of the arguments list since it starts the process differently. I guess there will be a release that fixes the problem this weekend. |
| |
Magic Man Account closed
Registered: May 2015 Posts: 3 |
Hi Slammer,
let me first say that I really like the good work you do with KickAssembler. It's quite a bit of fun coding with it since you can structure assembler at a very good way.
I have however a feature request. Why not have a "List" style pseudo command. For instance I wan't to fill multiple addresses with a single value. So what I want is something like
:mov #$00; [$2800; $2900; $2300]
the command would be like this
.pseudocommand src;[tar] {
lda src
.forall(t in tar) {
sta tar
}
}
I just used a pseudo for loop rather than the correct one. It's just to get the idea. Currently I have multiple mov commands defined putting the value into one, two, three or four destinations.
So since I haven't coded in 100 years on a C64 (I think in real it is 22 years) this maybe a stupid request ;-) If so flood it to the 00!
~Stephan
Magic Man/Crazy |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Magic Man: A kind of '...' notation for an argument list like in java. Interesting. Right now the priority is v4, but perhaps later. However try this:
:mov #1 ; $1000
:mov #2 ; $1000 ; $1001
:mov #3 ; $1000 ; $1001 ; $1003
.pseudocommand mov value;tar1;tar2;tar3;tar4;tar5;tar6;tar7;tar8;tar9;tar10 {
lda value
sta tar1
.if (tar2.getType()!=AT_NONE) sta tar2
.if (tar3.getType()!=AT_NONE) sta tar3
.if (tar4.getType()!=AT_NONE) sta tar4
.if (tar5.getType()!=AT_NONE) sta tar5
.if (tar6.getType()!=AT_NONE) sta tar6
.if (tar7.getType()!=AT_NONE) sta tar7
.if (tar8.getType()!=AT_NONE) sta tar8
.if (tar9.getType()!=AT_NONE) sta tar9
.if (tar10.getType()!=AT_NONE) sta tar10
} |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Hi, A couple of questions..
How are you guys experiencing the Vice-early-exit bug under El Capitan? Do you always get it or is it only sometimes? Right now it seams to me its only first time after a restart of the OS and I never get it when running from Eclipse.
Perhaps some timing issues are involved. If Vice need some info given by java (environment settings? Startup dir?) and java is terminating before vice has read those, it might cause Vice to crash. Any Vice-Guys here who can tell if there is a log that could cast some light on why Vice exits just after launching? |
| |
Magic Man Account closed
Registered: May 2015 Posts: 3 |
I get the bug at any time when I build and run from sublime3. Only when I add the work around I posted above it works all the time. It is regardless if it is the first time after restart or not. It either works (with workaround fix) or it doesn't work (without the fix).
I try the one with the commands. When I added a command which wasn't filled I got an error that all arguments have to be set so I didn't dogged into it. I give it a try thank you :-)
~Stephan |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
I finally got time to look at the Vice problem and might have found a solution.
First of all, the bug seems to have nothing to do with Kick Assembler. A simple test program in a few lines can trigger it. Seems like it is Vice and Java on OSX El Capitan that don't like each other. I made a little test program that start up 4 programs, one of them is Vice, and the only one crashing is Vice. Vice is run with no parameters, so it can't be a half written .prg file or breakpoint file that makes it crash.
I'm not sure if it has anything to do with it, but OSX complains about Vice using some deprecated libraries on each startup:
1. "using the deprecated Carbon Component Manager for hosting Audio Units. Support for this will be removed in a future release. Also, this makes the host incompatible with version 3 audio units. Please transition to the API's in AudioComponent.h"
2. "The gestalt selector gestaltSystemVersion is returning 10.9.1 instead of 10.11.1. This is not a bug in Gestalt -- it is a documented limitation .Use NSProcesssInfo's operatingSystemVersion property to get correct system version number."
I guess there are timing issues involved, since the bug come and goes.
However I managed to tweak it to work, atleast it seems so (you never know for sure with timing issues involved). Explicitly redirecting the stdout and errout seems to make a difference. THERE IS A NEW VERSION ON THE WEBSITE NOW. Try downloadling it, and if you get the error then send the file 'ExecuteOutputLog.txt' to me. |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Does Kickass allow for using parametric memory block labels? I need to save series of prg files with filename and suffix like 001 002 003. Is fixed string value is the only option? Whatever I try, I get block with label 'Unnamed' ;) |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:Any Vice-Guys here who can tell if there is a log that could cast some light on why Vice exits just after launching?
the OSX port is currently unmaintained and subject for deletion - the VM we are using to at least keep it in a state that it compiles is running 10.8 (mountain lion) for that matter. anything after that.... no idea, noone cares apparently. there is no log other than what is printed to console for that matter :)
PS: anyone who is interested in keeping the OSX port alive is invited to freenode #vice-dev :) |
| |
ruk
Registered: Jan 2012 Posts: 43 |
Quote:
the OSX port is currently unmaintained and subject for deletion - the VM we are using to at least keep it in a state that it compiles is running 10.8 (mountain lion) for that matter. anything after that.... no idea, noone cares apparently. there is no log other than what is printed to console for that matter :)
PS: anyone who is interested in keeping the OSX port alive is invited to freenode #vice-dev :)
Say what? I bet there are a lot of us using OS X as the preferred weapon of choice.
If VICE wasn't on OS X, I really wouldn't know what to do :-(
Guess I'll be joining #vice-dev... Anyone care to join me?
PS. I recently submitted a patch for bug #637 (Keyboard presses cause lag in Vice for MacOS) and reported some other stuff while at it. |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: Quote:
the OSX port is currently unmaintained and subject for deletion - the VM we are using to at least keep it in a state that it compiles is running 10.8 (mountain lion) for that matter. anything after that.... no idea, noone cares apparently. there is no log other than what is printed to console for that matter :)
PS: anyone who is interested in keeping the OSX port alive is invited to freenode #vice-dev :)
Say what? I bet there are a lot of us using OS X as the preferred weapon of choice.
If VICE wasn't on OS X, I really wouldn't know what to do :-(
Guess I'll be joining #vice-dev... Anyone care to join me?
PS. I recently submitted a patch for bug #637 (Keyboard presses cause lag in Vice for MacOS) and reported some other stuff while at it.
I'm sure both me and Mr.Sid can contribute, being Cocoa-developers... :) |
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
I can't really contribute to the coding part of this, for various reasons, but being a mac user (10.10.5) I could at least do some testing if needed. |
| |
JackAsser
Registered: Jun 2002 Posts: 1989 |
Quote: Hi, A couple of questions..
How are you guys experiencing the Vice-early-exit bug under El Capitan? Do you always get it or is it only sometimes? Right now it seams to me its only first time after a restart of the OS and I never get it when running from Eclipse.
Perhaps some timing issues are involved. If Vice need some info given by java (environment settings? Startup dir?) and java is terminating before vice has read those, it might cause Vice to crash. Any Vice-Guys here who can tell if there is a log that could cast some light on why Vice exits just after launching?
Run it through dtruss (https://opensourcehacker.com/2011/12/02/osx-strace-equivalent-d..) and check if there is some active exit or a crash. It might try to open a resource that it can't find (-1 on open()) that you'll see etc. |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
I need to compile bin without first two bytes but I constantly get 'Warning. Allready have an inputfile. Wont use '-binfile'
' everytime. What should I do? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Jammer: Could you post the line you use to run KickAss. That would make it easier to see whats going on. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
Quote:I'm sure both me and Mr.Sid can contribute, being Cocoa-developers... :)
by all means, do it :) |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Quoting SlammerJammer: Could you post the line you use to run KickAss. That would make it easier to see whats going on.
Sure, a bit of spoiler here, be warned ;)
java -jar kickass.jar DMCreloc.asm -log !DMCreloc.txt -o PsychoJammer.bin -binfile -showmem |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Jammer: It works fine here, except for the ! in the log file name, but i guess its ok on the operating system you use (Otherwise you would have gotten a different error). Which version are you using? |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Damn, I did it again and pasted old kickass.jar into project. I'll never learn :D Works like a charm, thanks!
Any idea how to help me with an issue few posts above, too? :) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Jammer: If I understood You correctly, You want to import a binary and ignore the two address bytes in the beginning of the file?
.import c64 "yyy.c64"
.import binary "xxx.bin"
documented further in the manual and also clarified in early posts above. |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
TWW, Slammer has already pointed me to the right answer. I was asking rather about export thing :) |
| |
IanC Account closed
Registered: Sep 2010 Posts: 2 |
Quoting GroepazPS: anyone who is interested in keeping the OSX port alive is invited to freenode #vice-dev :)
I've been submitting the odd patch, mostly to ensure that it continues to build on OS X. I'll do what I can, but I'm not proficient in Cocoa unfortunately. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Quote: Does Kickass allow for using parametric memory block labels? I need to save series of prg files with filename and suffix like 001 002 003. Is fixed string value is the only option? Whatever I try, I get block with label 'Unnamed' ;)
Currently no. It might change but that will mean a change in syntax for the .pc directive. Lets say you have the block: .pc=$1000 virtual This could both be a virtual block at $1000 or a block which name is determined by the string placed in the variable 'virtual'. |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Yeah, I know radical changes might mess things a bit up ;) How about separating .pc and .vpc? (instead of 'virtual' suffix :P) |
| |
The Gothicman Account closed
Registered: Aug 2011 Posts: 40 |
Not that'd be the topics before.
It's just because I'm drunk and I don't get some simple movement from, let's say, 1000 to 4000 and vice versa, get done.
Played around with those stuff, but in the end nothing worked.
SO: Either go to sleep or wait for a short (and probably logical) answer...
Right NOW I say: X, Y, Z: Fuck you!!!
Sorry for the shit, I'd say... |
| |
The Gothicman Account closed
Registered: Aug 2011 Posts: 40 |
Wow! I -was- drunk...
Haha... Fuck the shit... :) |
| |
soci
Registered: Sep 2003 Posts: 473 |
No way, I don't buy that. You can do those simple movements in VICE as "T 1000 1FFF 4000". |
| |
The Gothicman Account closed
Registered: Aug 2011 Posts: 40 |
Believe me: I WAS drunk. If you'd know me you wouldn't doubt, at all.
And I wasn't speaking of a transfer from 1000 to 4000, but I was speaking from 1000-1fff to 4000 and, simultaneously, transfering 4000-4fff to 1000.
But, since I'm sober again, that's fixed. ;) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Hello,
When passing an argument to a pseudo:
:pseudo_test 1234
would result in that the figgure "1234" is enterpreted as AT_ABSOLUTE (in decimal). Why not AT_NONE (as no addressing mode is really defined)? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Well a number in Kick Assembler indicates an absolute adressing mode: nothing - no argument
number - absolute (or abs zeropage)
# - immediate
(number),y - indirect zeropage,y
etc. How would you indicate absolute mode?
(AT_NONE is what you use in nop, sei, cli, etc. while commands like lsr can both use the argument types AT_NONE and AT_ABSOLUTE with different results) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
I was thinking a prefixed with "$" ($02 or $1234) indicating absolute. However i see Your point With the othe OPcodes (LSR etc.).
How about AT_NONE for no addressing mode ("1234") and AT_NULL for no argument ("")? Labels or const/var's would have to be prefixed somehow internally then I Guess.
I'm just trying in a pseudocommand to differentiate between an argument not being passed at all (which may result in an assertion error) and an argument passed without a prefix (which would result in an assertion warning) but it's nitpick.
Brgds! |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
What a nice feature... I'd also like to know, so perhaps an example would do? I would have required that years before but never tested (Whadda lazy bustard!!! :)) Can they be defined by mnemonic extensions?
Also is it possible to pass a function inside a function to be called anyhow with kickasm scripting? Because i think that's more comfy than passing by arguments like if(a==1) {.eval Arg=Num*ber .eval x=blabla(Arg)} if (a==2) {.eval Arg=Num*bah .eval x=blabla_2(Arg)}
Thinking about something like .function DoSomething(NumMultiplier,MyFunction()) but that doesn't work... so if that's already possible i'm with love to :)
3rd question... Can i exit a .for loop? Or a .goto style of directive. How you would do that in kickasm? |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Also some days ago, i think i found a bug in kickassembler: If i changed .var i value in .for (i....) loop (sorry i don't have this code which failed anymore..) ...it hangs kickassembler (and halts relaunch64) but ends with some Java heap overflow (if i remember correctly). Is this a bug or did i just mess up some internal counter? And should i just NOT skip or touch .var i inside a for loop? :D (My lameness, but it was necessary to skip certain values from a huge set which i simply knew those would fail anyway.)
Any help appreciated :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
TWW: $ means the number is written in hexadecimal, just like % means its in binary. So the following 3 executions gives the same result: :pseudo_test $1234
:pesudo_test 4660
:pesudo_test %1001000110100 just as this is the same: lda $1234
lda 4660
lda %1001000110100 On the inside of the pseudocommand all arguments are filled with pairs of (argumenttype, value). If no argument is given, the argumenttype is AT_NONE. If you want to test if no argument is given you could do something like this.pseudocommand pseudo_test arg1 {
.if (arg1.getType()==AT_NONE) .print "No argument is given"
else .if (arg1.getType()==AT_ABSOLUTE) .print "the argument is absolute: "+ arg1.getValue()
else .print "the argument is something else!"
}
:pseudo_test
:pseudo_test 4660
:pseudo_test $1234
:pseudo_test ($30),y This will give: No argument is given
the argument is absolute: 4660
the argument is absolute: 4660
the argument is something else!
So by testing for AT_NONE you can see if an argument is given or not. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Agemixer: Currently there are no 'break', 'goto' or 'continue' directives to modify the flow of loops. Also, there are no lamdaexpression. This migth change, especially with 'break' and 'continue' and perhaps with lambda expressions (just for the fun of implementing it :-) ) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Agemixer: If you can reconstruct the error, then send it to me and i will look at it. It might be that the loop is not terminating? |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
I couldn't just reproduce it same way but this does the same:
.for (var i=0; i<=10; i=i+0.1) { .if (i>5) .eval i=5 .print "i="+i }
...and the error:
parsing
flex pass 1
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3210)
at java.util.Arrays.copyOf(Arrays.java:3181)
...
Anyway, not sure if this helps, but something like this triggered it, and IIRC the pow[] was in .for loop comparison though. But that example is gone. (perhaps integer .var comparison vs float .var failed? Even if i<=x, just an assumption..)
.var x = pow(2,fractionbits) // generate some LUT...
.var diffi .var wanha=0
.for(var i=0;i<=x;i++)
{.eval freq = round(Base_Freq * pow(2,[i/x/12]))
.eval diffi = myfreq - wanha .eval wanha = freq
// ..sorry not everything revealed here.. =)
}
Anyway i think it could just have been human error :) |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
Then an another little puzzle, which could ease up the programming a bit for sure... (atleast if you branch a lot =)
When a relative branch exceeds its short branch limits in multiple places in the code, it could get annoying to replace it with long jumps, but optimize back a bit later if not needed... So i wanted to automate some long branch generation a bit, instead of several compile time complaints. BUT! Is this possible to do properly in kickassembler? As i know kick can do multiple passes depending on your code, until all variables are known and all code generated properly? :)
What do you think? How this should be done? My idea is this (and it halfway works already!)
.const BEQ=$f0 .const BNE=BEQ^$20
.const BMI=$30 .const BPL=BMI^$20
.const BCC=$90 .const BCS=BCC^$20
.pseudocommand far OPCODE;OPERAND {
.var PC = *
.var branch = OPERAND.getValue()-PC
//.if (branch ?? InvalidNumber) { .print "label not found yet" } //...should this work?
.if ( branch < -126 || branch > 129 ) {
.byte OPCODE.getValue()^$20, 3 // [BEQ] *+5, jmp long_branch
jmp OPERAND
.print"FAR BRANCH at location $"+toHexString(PC)
} else {
.byte OPCODE.getValue(), branch-2 // [BNE] short_branch
// For the above .byte code, is there possible to feed OPCODE for pseudocommand like those argument types for operand?
}
}
.pc=$2000 // some testing...
before:
.fill 127,[NOP]
:far BNE; before // this branch works
:far BCC; after // this branch gives "Error: the condition must be able to evaluate in first parse)"
.fill 128,[NOP]
after:
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
Quote:.for (var i=0; i<=10; i=i+0.1) { .if (i>5) .eval i=5 .print "i="+i }
The error in the above example is happening due to an endless loop (but I guess you knew thats why you made the example). I dont think i have alot to go on but if you get the error againg let me know. (NB. all numbers in KickAss is pratically doubles, so I dont think it got anything todo with int vs float comparison)
Regarding the branch thing. I had the same thouht once but concluded that this kind of functionality have to be implemented in a 'trial and error' kind of way. When deciding if the branch is a short or a long one you should know the target address of the branch. But the target address of the branch could depend on wether its a short or a long branch, so this is a problem. Further more several branches could be dependand on each others decitions (short vs far) so this makes it more complicated. This is a thing for the assembler to support by first assuming short jumps and then reassemble with long jumps until all branches fits. I have a note on the which list for implementing this as jne, jeq, jmi, jpl, etc but this is a biggie so it wont be this year. |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Question about functions/macros. There's clear division which does what in manual. How about piece of code that is mix of assembler and script conditions/variables - should I define the one below as macro or function?
.if(usefreqtable1)
{
.if(usefreqlo1)
{
ldx #$00
checkch1freq:
lda ch1freq, x
cmp #$fe
bne updatech1freq
ldx #$00
stx checkch1freq - 1
jmp checkch1freq
updatech1freq:
sta $d401
.if([usefreqhisweeptable1] || [constfreqhisweep1 != $00])
{
sta dofreqhisweep1 + 1
}
inx
lda ch1freq, x
sta $d400
.if([usefreqlosweeptable1] || [constfreqlosweep1 != $00])
{
sta dofreqlosweep1 + 1
}
inx
stx checkch1freq - 1
}
else
{
ldx #$00
checkch1freq:
lda ch1freq, x
cmp #$fe
bne updatech1freq
ldx #$00
stx checkch1freq - 1
jmp checkch1freq
updatech1freq:
sta $d401
.if([usefreqhisweeptable1] || [constfreqhisweep1 != $00])
{
sta dofreqhisweep1 + 1
}
inc checkch1freq - 1
.if([usefreqlosweeptable1] || [constfreqlosweep1 != $00])
{
lda #$00
sta dofreqlosweep1 + 1
}
}
}
|
| |
Slammer
Registered: Feb 2004 Posts: 416 |
It would have to be a macro (or pseudo command). Commands that produces bytes to the resulting .prg file (like mnemonics and .byte/.word etc) can't be in functions.
Edit: Otherwise you could make some really tricky stuff like:lda #myByteProducingFunc(27) |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
I've tried to define that portion of code both as macro and function. Macro resulted in error due to non-assembly instructions. Function compiled without error but most probably as regular assembly that's not really a subroutine. Ok, I see that it has to be totally reorganized ;) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
If you are reporting error please post complete examples. When you post cutout pieces of code I have no chance of verifying if its an error or not.
I dont think I understand what you are writing. Are you sure its not when you put it in a function you get an error for using asm directives? ( = directives that produce bytes to the output) |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Sorry about that :) Macro seems to work fine - it was just enclosed within .if directive that I didn't catch somehow. No error report whatsoever and thank you for the tip ;) |
| |
Hoogo
Registered: Jun 2002 Posts: 102 |
I guess there are situations where automatic long branches are difficult:
---> Dest 1
| ...
| -<Branch 2
| | ...
--+<Branch 1
| ...
-->Dest 2 Branch2 cannot be decided until Branch 1 was decided, and the other way around the same.
But such a situation can already be created with an .if (futureLabelFormual)FillSomeBytesFormula. How do you treat that? Forbid .if with unknown labels? Or some check if passes get out of sync? |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
You guessed it , using if's on yet unknown values gives an error since the memlocation of labels have to be resolved in first pass. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
I saw I asked this thing like 4 years ago and surely found some work-around back then but that is several HD crashes ago and perhaps there are updates I didn't catch.
Strings:
I am making a string for a cartridge header but it contains some RVRS ON characters and stuff. The question is how do I avoid doing this hack:
.const CartridgeName = "C64GS C" // Maximum 32 bytes.
.text CartridgeName
.byte $61,$72,$74,$72,$69,$64,$67,$65
Basically what I would like to do is to append the constant with the bytes as added data to the string. This again to allow me to fill in the surplus available characters without having to cheat:
.fill 32-CartridgeName.size()-8,0
So what I would like to do is:
.const CartridgeName = "C64GS C"+hexBytes($61,$72,$74,$72,$69,$64,$67,$65) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Hmm another thing I saw now was that I get an error when compiling my code after updating Kickass (was using old version):
.var ZP = $02
.const FetchDataVector = ZP .eval ZP+=2
Have to move the ".eval ZP+=2" to a new line but it used to assemble just fine. Will make my ZP variable declarations a lot more messy ^^ |
| |
Scan
Registered: Dec 2015 Posts: 110 |
You don't need to move it to a new line, you can also use ; to separate the statements:
.var ZP = $02
.const FetchDataVector = ZP ; .eval ZP+=2
|
| |
Digger
Registered: Mar 2005 Posts: 421 |
Tru dat. But you can do this and it works without eval, since it evaluates post expression.
.var zp = $c0
.const screen = zp++
.const vOffset = zp+=2
.const vScrollText = zp+=2
|
| |
TWW
Registered: Jul 2009 Posts: 541 |
You guys are so clever 8-D
I seriously should drag my ass to a (c0py)party so I can start handing out those beers...
Now only question remains is the string issue above. |
| |
Agemixer
Registered: Dec 2002 Posts: 38 |
TWW, please check my example (dated 2015-03-27 earlier in this thread) for string conversion.
The basic idea for conversing kickass strings to ascii/petscii/whatever, is some macro like this:
.function pet2asc(p) { .eval p = [ p>$40? p+=$80 : p ] .return [ p<$20? p^$40 : p ] } // character conversion from Kickass text to c64 ascii
.macro asctxt(str) { .fill str.size(), pet2asc(str.charAt(i)) }
.macro asctxtCR(str) { :asctxt(str) .byte $0d } // With carriage return
After having these, you can define your text like:
:asctxt("Hello World!")
:asctxtCR("") // just a carriage return (byte $0d)
:asctxt("The quick brown fox ")
:asctxtCR("jumps over the lazy dog") |
| |
Digger
Registered: Mar 2005 Posts: 421 |
Another useful macro (hope @Slammer will add that natively soon) that converts hex string to bytes super useful for color tables.
.macro stringToBytes(string) {
.for (var i = 0; i < string.size(); i++) {
.var char = string.charAt(i).number()
.var value = char >= $30 ? char - $30 : char + 9
.byte value
}
}
Example:
stringToBytes("f582900000000000")
Can be surely written even shorter, but I didn't care. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Math Question:
Say I have a number: -161230 and do the following:
.var number = -161230
.var HighOrder = floor(abs(number/10000)) // Gives 16
.var MediumOrder = floor([abs(number/10000)-floor(abs(number/10000))]*100) // Gives 12
.var LowOrder = (abs(number/100)) // Gives 1612,3
.eval LowOrder = floor(abs(number/100)) // Gives 1612
.eval LowOrder = [(abs(number/100)) - floor(abs(number/100))]*100 // Gives 29,99999999999545
In my head this should give 30,0
Or shouldn't it?
EDIT: I can use round as a workaround(^^). |
| |
soci
Registered: Sep 2003 Posts: 473 |
That's how binary floating point works. This special case would have worked with decimal floating point.
In short floating point numbers need to be handled carefully and yes, that round() will be needed.
Btw. this sort of calculation should have been done with modulo and division using integer arithmetic only. And preferably unsigned to not get "surprising" results for negative numbers (implementation specific). |
| |
xIII
Registered: Nov 2008 Posts: 210 |
just a fast question:
if I use -> .word 100,100
the result in Vice is -> 64,80,64,00
I was expecting -> 64,00,64,00 ?
if I use .word $012c
I get -> 2c 80
expecting: 2c 01 ? |
| |
xIII
Registered: Nov 2008 Posts: 210 |
Quote: just a fast question:
if I use -> .word 100,100
the result in Vice is -> 64,80,64,00
I was expecting -> 64,00,64,00 ?
if I use .word $012c
I get -> 2c 80
expecting: 2c 01 ?
anyone ? |
| |
lA-sTYLe
Registered: Sep 2003 Posts: 63 |
no idea why, nor used to Kickass,
but how about .byte $2c,$01 ? |
| |
xIII
Registered: Nov 2008 Posts: 210 |
Quote: no idea why, nor used to Kickass,
but how about .byte $2c,$01 ?
yes thx, ofcourse it works with .byte but it should work with .word ;) |
| |
soci
Registered: Sep 2003 Posts: 473 |
No one wants to say but you're likely doing something wrong. The examples given work with the last version. |
| |
xIII
Registered: Nov 2008 Posts: 210 |
@soci: indeed I was doing something wrong, I found a ROR in my routine that caused the 1 to become 80 :( |
| |
Mace
Registered: May 2002 Posts: 1799 |
This:
Relaunch64 3.3.7 (Build 20161031)
Mac OS X 10.11.6 (x86_64)
Java-Version 1.8.0_111 (Oracle Corporation)
KickAssembler v4.3
Produces this error:
Exception in thread "main" java.lang.UnsupportedClassVersionError: kickass/KickAssembler : Unsupported major.minor version 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637)
at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Please help :( |
| |
soci
Registered: Sep 2003 Posts: 473 |
You likely have 1.7 installed in parallel to 1.8. Try to change JAVA_HOME to point to 1.8 or uninstall 1.7. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Although Relaunch said I had Java 1.8 installed, the actual JDK was 1.6 with merely the 1.8 runtime (JRE) on top.
I manually removed Java 6 JDK and Java 8 JRE and installed Java 8 JDK last.
Now it works. |
| |
Mace
Registered: May 2002 Posts: 1799 |
<deleted by user> |
| |
Mace
Registered: May 2002 Posts: 1799 |
Okay, can someone explain me why this doesn't work?
While compiling, all I get is "null", it doesn't even do the .print
*=$2000
.var theFile = getPath()+"/"+"test.prg"
.print theFile
.import c64 theFile
If I replace the last line with ".import c64 "(proper path)/test.prg", it works. And I checked for typos 10 times, so I'm sure I'm doing it right. |
| |
ruk
Registered: Jan 2012 Posts: 43 |
Change the .print to .printnow and you will see that it prints out the expected value in the first pass, before the odd "null" output.
I would say that this is bug since the value clearly is available in the first pass. The "null" is probably due to something going south while processing the .import directive |
| |
Mace
Registered: May 2002 Posts: 1799 |
Ok, this is weird:
.print theFile does nothing
.printnow theFile produces the correct filepath.
.import c64 theFile produces null
.import c64 "[correct path to file]" imports the file. |
| |
Mace
Registered: May 2002 Posts: 1799 |
Ok, this is a confirmed bug that will be resolved in the next update. |
| |
Norrland
Registered: Aug 2011 Posts: 14 |
Hellu...
Tried to code some stuff and ran into some problems, searched the manual but haven't found what I'm looking for.
Is it possible to modify names of variables when declaring or adressing them?
Maybe following snippet of non-working-code explains my question (in this example I would like to create 50 lists with the names list_1, list_2, list_3..):
.for (var i=0 ; i<50 ; i++)
.var list_+i=List() |
| |
Knut Clausen
Registered: Apr 2013 Posts: 18 |
Kickassembler won't let you create dynamic variable names like that.
.var myLists = List(50)
.for(var i = 0;i<myList.size();i++){
.eval myLists.add(List())
}
or
.var ht = Hashtable()
.for(var i = 0;i<50;i++){
.eval ht.put("list_" + i, List())
}
will give you what you need |
| |
Norrland
Registered: Aug 2011 Posts: 14 |
Thx Knut, will try that! |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
I may have spotted parser error. PseudoPC readressing doesn't modify BNE/BEQ branches. I had tough time to spot why my piece of code, relocated to zeropage, jams and Vice monitor ensured me that's the reason. Haven't checked other branches, yet.
edit: I'm probably wrong here. Branch value is unchanged in original piece of code (contained within PseudoPC block) but is correct after relocation. It's relative addressing after all, silly me. Jam trouble is, unfortunately, unsolved so far. |
| |
Cruzer
Registered: Dec 2001 Posts: 1048 |
Jammer: You might have discovered a special feature that detects the coder's handle and changes the output accordingly. :D |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
LOL xD Usual foolstart of mine. Vice monitor shows branches with absolute value afterwards hence I got confused for a 'while'. BTW, crash solved. I just forgot to remove .zp markers which left after previous version of code - earlier I moved entire interrupt to zp, later only key routines ;) |
| |
chatGPZ
Registered: Dec 2001 Posts: 11113 |
this is not normal method |
| |
Jammer
Registered: Nov 2002 Posts: 1289 |
Normal is boring? ;) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Hello
I get the following error:
.if (CopyStop-CopyStart >= 256) {
^
Error: The condition must be able to evaluate in first parse
at line 57, column 5 in Asset Manager.asm
I am using the pseudopc directive. I have found a (messy) workaround but wondered if there is a way to allow two parses?
Also, any future plans to allow pseudopc nesting in the future (useful for cartridge images where you need the assembled code pseudopc to $8000, then pseudopc code to $0800 (example) which is to be copied to RAM while it all in fact is located at $2040 in the .crt image. Again, I have a workaround but wondered if this is planned or if there might be some more delicate way to handle this?
EDIT:
Simplified question:
test1:
test2:
.if ([test1 - test2] == 0) .print "This Works!"
.if ([test3 - test4] == 0) .print "This Does Not Work!"
test3:
test4:
Is there a way to get the 2nd .if statement to work without getting the "Error: The condition must be able to evaluate in first parse" issue? |
| |
Joodas
Registered: Oct 2011 Posts: 8 |
Hi lads
I'am trying to configure (https://goatpower.org/2013/09/11/c64-development-with-kick-asse..) KickAss, Notepad++ and VICE (GTK3VICE-3.7-win64) and compile example code. Unfortunatelly Notepad++ returns error:
java -jar "C:\C64\Tools\KickAssembler\KickAss.jar" -log C:\C64\c64error.txt "C:\C64\GoatPowerExample.asm" -libdir C:\noice\C64\ -o "C:\C64\GoatPowerExample.prg" -vicesymbols -showmem -execute "x64.exe -moncommands C:\C64\GoatPowerExample.vs +confirmexit"
; about to start a child process: "java -jar "C:\C64\Tools\KickAssembler\KickAss.jar" -log C:\C64\c64error.txt "C:\C64\GoatPowerExample.asm" -libdir C:\noice\C64\ -o "C:\C64\GoatPowerExample.prg" -vicesymbols -showmem -execute "x64.exe -moncommands C:\C64\GoatPowerExample.vs +confirmexit""
CreateProcess() failed with error code 2:
Do you know how to change command line:
::KickAss & run
java -jar "C:\C64\Tools\KickAssembler\KickAss.jar" -log $(CURRENT_DIRECTORY)\c64error.txt "$(FULL_CURRENT_PATH)" -libdir C:\noice\C64\ -o "$(CURRENT_DIRECTORY)\$(NAME_PART).prg" -vicesymbols -showmem -execute "x64.exe -moncommands $(CURRENT_DIRECTORY)\$(NAME_PART).vs +confirmexit"
to adopt it to the new VICE (GTK3VICE-3.7-win64)?
Thank you in advance |
| |
Endurion
Registered: Mar 2007 Posts: 72 |
Error Code 2 is file/path not found.
Make sure the paths are correct, and there's no quoting issue. Also not sure if java can cope with backslashes. Try replacing all backslashes with slashes. Windows has no problems with them. |
| |
Frostbyte
Registered: Aug 2003 Posts: 166 |
Hopefully not too late to the game, but as far as I know x64 doesn't exist anymore on official VICE distributions. If that is the case on yours, change x64.exe to x64sc.exe in the command.
x64 is (was) the less resource-demanding but less accurate C64 emu, whereas x64sc is the more resource-demanding but more accurate one. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Think I found a bug (and a workaround):
When processing (ZP,X) (Indirect Zero Page,X) inside a pseudocommand, the "AT_IZEROPAGEX" isn't recognized properly.
For example (source = Some (zp,x) type/value):
.if (source.getType() == AT_IZEROPAGEX) - Does not work
.if (source.getType() == -5) - does work.
(-5 seems to be the value connected to AT_IZEROPAGEX which was found by doing a .print source.getType() when passing a (ZP,X) value. |
| |
Frodo
Registered: May 2020 Posts: 2 |
Quote: Hello
I get the following error:
.if (CopyStop-CopyStart >= 256) {
^
Error: The condition must be able to evaluate in first parse
at line 57, column 5 in Asset Manager.asm
I am using the pseudopc directive. I have found a (messy) workaround but wondered if there is a way to allow two parses?
Also, any future plans to allow pseudopc nesting in the future (useful for cartridge images where you need the assembled code pseudopc to $8000, then pseudopc code to $0800 (example) which is to be copied to RAM while it all in fact is located at $2040 in the .crt image. Again, I have a workaround but wondered if this is planned or if there might be some more delicate way to handle this?
EDIT:
Simplified question:
test1:
test2:
.if ([test1 - test2] == 0) .print "This Works!"
.if ([test3 - test4] == 0) .print "This Does Not Work!"
test3:
test4:
Is there a way to get the 2nd .if statement to work without getting the "Error: The condition must be able to evaluate in first parse" issue?
Thanks for posting this!
Were you able to get this resolved by any chance?
I have the same issue with Kick Assembler v5.25.
My workaround isn't great either, e.g. bne_perf(*+2)
Thank you, |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Quote: Thanks for posting this!
Were you able to get this resolved by any chance?
I have the same issue with Kick Assembler v5.25.
My workaround isn't great either, e.g. bne_perf(*+2)
Thank you,
Yes, you can do it like that since *+2 is known when you call the pseudo. Another workaraound is to use .label to pre-define memory locations in advance, but for branches and such this isn't a very good solution. Maybee there is a way with segments (as they seem flexible of sorts) but perhaps combersome when dealing with pseudo/macros.
An example is to get a branch-pseudo to determine if a branch should be long or short (bne label or beq *+4 + jmp label) to a label further down your code. Not trivial...
It has been explained that it's a chicken/egg issue as the unresolved label may change depending on the conditional checks (.if(sometthing) - change something) made inside the pseudocommand or macro. What perhaps could solve it is to allow additional passes to try and resolve "resolvable" labels and then tap out if it not able to do it in n times.
Either way, not sure if this is the right forum to discuss this anymore. There is a facebook group which exists (I am not on FB!) which perhaps could yield a response :)
Another feature request: Make assertions which passes silent (or an option to do so). |
| |
Avalanche
Registered: Aug 2002 Posts: 6 |
I am working with Kick-Ass now for a while. Though Slammer is giving his best, I'd love to see Kick-Ass going "open-source". Some things are buggy, some features missing, and sometimes old socks need to be cut off for better understanding of how to do things.
The FB group is a place to post, and others can like it or write comments on it. But thats all about it. Its not really a good way of taking care and responsibility upon a product-like tool. Plus: you cut off anybody else that is willing to help or would take the responsibility to add improvements/features by himself.
When it comes down to Kick-Ass' future its all depending upon Slammer, in good aswell as in bad terms. |
| |
Style
Registered: Jun 2004 Posts: 498 |
Apologies if this has been covered, I havent been following the thread, but two things Id love in kickass:
1) Overloading macros and functions
2) naming parameters in calls, cos it's clearer and will support 1
Thoughts? |
| |
Style
Registered: Jun 2004 Posts: 498 |
Oh, I forgot
3) Passing nothing to a macro parameter results in null. Or allow defaults for parameters, making the parameter optional. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Quote: Oh, I forgot
3) Passing nothing to a macro parameter results in null. Or allow defaults for parameters, making the parameter optional.
You can do this with pseudocommands (allows "null" parameters).
I.e. add16 $1000 : #100 : (optional destination)
Depending on what it is you want to do, you can #define 'something' which alters the behavior of a macro (example):
#define WhateverCondition
:MyMacro(a, b)
#undefine WhateverCondition
#if WhateverCondition {
.MyMacro(a, b) {}
}
#else{
.MyMacro(a) {}
}
Or simply make 2 macros, one normal and one stable. But yes agree it would be a nice addition. |
| |
Stone
Registered: Oct 2006 Posts: 168 |
At one point I will ask myself:
"Am I not a man of many resources? Do I have but one tool in my toolchest? Must I be eternally bound by forces beyond my reckoning?"
And I shall hope to answer:
"Nay! I am a programmer! I refuse to be a slave to the limitations of my assembler! Henceforth I shall take destiny into my own hands! I shall make use of Python, C++ and their ilk to produce code and data as I see fit! I shall use Makefiles so that my time and powers of conversion are not unduly wasted! Then I shall be the master of my domain and I shall be at peace." |
| |
Bitbreaker
Registered: Oct 2002 Posts: 500 |
Quoting Stone
And I shall hope to answer:
"Nay! I am a programmer! I refuse to be a slave to the limitations of my assembler! Henceforth I shall take destiny into my own hands! I shall make use of Python, C++ and their ilk to produce code and data as I see fit! I shall use Makefiles so that my time and powers of conversion are not unduly wasted! Then I shall be the master of my domain and I shall be at peace."
Such true words, let the assembler stay what it is, the tool that helps you a bit to not enter your code as hex, not less, not more, it is there for the dirty work. In my view there's no need for it to handle high-level language programming like javascript or lua. There's compilers and interpreters for those languages on their own, each of them also brings their own syntax highlighting, if you favour that. I know, we wish it to be comfortable as much as possible, but in the end it is an assembler, and not acompiler and thus subjected to certain restrictions that we need to accept. We love restrictions, right? :-) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Wasn't there like a 'bitching topic' or something people could ramble in???
If a thread sets off your (insert whatever 3-4 letter diagnosis which suits your condition) to the point where you (IN A DEDICATED THREAD TO A SPECIFIC TOOL) are compelled to call other people idiots for using said tool, here a simple solution: Don't comment or better yeat don't even read it, instead make another thread called ‘idiots who uses other tools than I’ or whatever and cut the trolling shit... |
| |
Stone
Registered: Oct 2006 Posts: 168 |
I tried to humorously point out that all tools have their limitations, even something as flexible as Kick Asm. I use at least 4 assemblers regularly and one of them is Kick Asm but when I get into a situation where I need interlinked code/table generation or some kind of data conversion I usually use an offline tool or script, not because the problem can't be solved in my assembler but because it is easier to debug my own program and it does exactly what I want it to do, no more and no less. Of course, trying to solve a problem within the limitations of your chosen tool can be a fun and rewarding challenge in itself even though it may not be the most productive way.
What I think is specific to this thread (and the Facebook group) is that users seem to ask for increasingly obscure features to be added to the assembler to solve their edge cases instead of taking a step back and look at how we work. |
| |
Bitbreaker
Registered: Oct 2002 Posts: 500 |
Quote: Wasn't there like a 'bitching topic' or something people could ramble in???
If a thread sets off your (insert whatever 3-4 letter diagnosis which suits your condition) to the point where you (IN A DEDICATED THREAD TO A SPECIFIC TOOL) are compelled to call other people idiots for using said tool, here a simple solution: Don't comment or better yeat don't even read it, instead make another thread called ‘idiots who uses other tools than I’ or whatever and cut the trolling shit...
Okay, i understand, that you are not interested in valid criticism, new perspectives and growth and prefer to silence those voices by being plain rude and insulting, to stay on the comfortable side. Accepted. Have a nice day. |
| |
ChristopherJam
Registered: Aug 2004 Posts: 1378 |
TWW, nobody called anyone an idiot. If you're reading that between the lines, that's between you and the people you made up in your head.
And really, there's nothing wrong with reminding people that there are other tools that could augment their use of this one or any other. I can quite easily see a case for combinining KA's scripting with external generators for things that KA doesn't (yet) support :) |
| |
Krill
Registered: Apr 2002 Posts: 2839 |
But does KA support canonical 6502 ASM syntax (like "symbol = $1234" without .var or .const) now? =) |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Some clarification is needed, so here goes:
@Stone: Your first post used sarcasm to ‘humorously’ make it’s point. Sarcasm implies expression of contempt or ridicule and there is no need for that and it pissed me off. I see though my answer was perhaps a tad ‘direct’ and it would probably have been better to shut the fuck up and ignore it, but done is done.
@ Bitbreaker: Your response backed up the first one – hence it was de-facto guilty of the same sarcasm. Again, I should off course have shut the fuck up, but sometimes things just piss you off and the planets align and all that. However now you have gotten to be rude back (incapable of growth etc… (which surely probably isn’t a wrong assumption, but still it’s rude to point it out)) so 2 – 1 to you I guess and agreed, have a nice day to you too.
@ CJ: The response was issued due to the aforementioned sarcasm, and perhaps it was a mistake to assume people saw the same. Hope it’s clarified now. And for sure nothing wrong with a friendly remainder, but this matter has been debated and argued over and over, again and again and honestly there is no need for further reminders. I have just previously chosen to stay out of those discussions as in my opinion, people must enjoy their hobby any way they see fit without the snide comments.
@ Krill: No it doesen't (which you surely know) but I really didn’t want to get into any this assembler vs. that assembler and exactly what I was trying to avoid in this thread. I am not thrilled about the syntax of some other assemblers however I try to keep it to myself.
Now I would for sake of good order want to clarify: All of you guys are much more capable coders than I. And for sure your production methods are no doubt in a different league. In short, I respect your skills and the way you obviously handle your productions and I am in no way criticising your way of doing things. And be sure if I ever have questions about moving on to other tools, I would highly appreciate your input (there are even internal ‘forces’ pushing in this direction and probably where things will end up).
Meanwhile, as a complete hobbyist doing this for my own enjoyment, I reserve the right to report bugs, post questions and propose features to this tool I enjoy working with without becoming the next victim of the ‘makefile’ hyena pack… Oppps.. Weeelll fuck it, Bitbreaker, guess it’s 2-2….. |
| |
Krill
Registered: Apr 2002 Posts: 2839 |
Quoting TWW@ Krill: No it doesen't (which you surely know) but I really didn’t want to get into any this assembler vs. that assembler and exactly what I was trying to avoid in this thread. I am not thrilled about the syntax of some other assemblers however I try to keep it to myself. I'd keep my mouth shut if it was only about choosing the quirks of one assembler over the quirks of the other. :)
Alas, it isn't - if you cannot avoid other assemblers being involved.
Consider a 3rd party library - let's say, a loader. =)
The most basic and portable way to include it is via some sort of .incbin to statically link its binary.
The problem is that the symbols definition file with the relevant call and zeropage variable addresses and some other constants (included via some sort of .include) needs to be understood by your assembler - if you want to have clean code, at least.
It doesn't get simpler than "install = $1000" and "load = $2000" etc. (which is understood by pretty much each and every other 6502 assembler) then "jsr install" etc., and yet... need to "convert" that stuff in the include file to work with KA. Bit annoying. |
| |
TWW
Registered: Jul 2009 Posts: 541 |
Quote: Quoting TWW@ Krill: No it doesen't (which you surely know) but I really didn’t want to get into any this assembler vs. that assembler and exactly what I was trying to avoid in this thread. I am not thrilled about the syntax of some other assemblers however I try to keep it to myself. I'd keep my mouth shut if it was only about choosing the quirks of one assembler over the quirks of the other. :)
Alas, it isn't - if you cannot avoid other assemblers being involved.
Consider a 3rd party library - let's say, a loader. =)
The most basic and portable way to include it is via some sort of .incbin to statically link its binary.
The problem is that the symbols definition file with the relevant call and zeropage variable addresses and some other constants (included via some sort of .include) needs to be understood by your assembler - if you want to have clean code, at least.
It doesn't get simpler than "install = $1000" and "load = $2000" etc. (which is understood by pretty much each and every other 6502 assembler) then "jsr install" etc., and yet... need to "convert" that stuff in the include file to work with KA. Bit annoying.
Agreed, definately a pain, but doable (and regarding say, a loader, already done - check your pm) :D |
| |
Krill
Registered: Apr 2002 Posts: 2839 |
Quoting TWWAgreed, definately a pain, but doable (and regarding say, a loader, already done - check your pm) :D Not quite the solution i was hoping for, tbh. :) |
| |
Stone
Registered: Oct 2006 Posts: 168 |
@TWW: I was pompous, sure, but not sarcastic. There was no malice. |
| |
PAL
Registered: Mar 2009 Posts: 269 |
Strange how fast things just turn and get twisted or weird.
In our scene all people are on different skill levels and production methods (Novice. Advanced Beginner. Competent. Proficient. Expert.) Some are great at everything, while some others can not figure out things that seem simple or "stupid" yet create super great effects and parts... I think one should reflect a tad about the fact that we are all on different levels and also social skills... I think I have learned a lesson in the last one ;-)
@TWW - Looking forward to me and you get together after the summer and try to create something nice like we spoke of at X and in chats - We will have lots of fun with that! PAL |
| |
Martin Piper
Registered: Nov 2007 Posts: 634 |
Since I modified Acme to add python scripting support and exhaustive forward label resolution (it retries passes until all labels are defined consistent values) I prefer that assembler. :) |
| |
Frantic
Registered: Mar 2003 Posts: 1627 |
Quote: Since I modified Acme to add python scripting support and exhaustive forward label resolution (it retries passes until all labels are defined consistent values) I prefer that assembler. :)
Where is that version of ACME available, if anywhere? |
| |
Martin Piper
Registered: Nov 2007 Posts: 634 |
Quote: Where is that version of ACME available, if anywhere?
Win binaries: https://github.com/martinpiper/ACME/tree/master/Release
Tests:
https://github.com/martinpiper/ACME/blob/master/features/CheckF..
https://github.com/martinpiper/ACME/blob/master/features/CheckP..
https://github.com/martinpiper/ACME/blob/master/TestPython.a#L17
Source in same repo. |
| |
Frostbyte
Registered: Aug 2003 Posts: 166 |
I have a small problem, and I don't know if Kick Assembler has a way to provide the solution.
What I think I'd need is dynamic labels - that is, labels that are created and named dynamically at compile time.
In my macro, i'm generating code based on some input data, and I'd need labels within that code (in positions and numbers I don't know of yet at the time of generating the code). Then I'm generating another code block that would refer to those generated labels.
E.g. first bit of macro creates code with label1, label2, label3 etc.
Second bit of macro creates code that updates the values at the aforementioned labels.
As far as I can see this is not possible, at least with the usual labels that seem to be always hard-coded? Any other ideas how to do something like this? |
| |
trident
Registered: May 2002 Posts: 74 |
Quote: I have a small problem, and I don't know if Kick Assembler has a way to provide the solution.
What I think I'd need is dynamic labels - that is, labels that are created and named dynamically at compile time.
In my macro, i'm generating code based on some input data, and I'd need labels within that code (in positions and numbers I don't know of yet at the time of generating the code). Then I'm generating another code block that would refer to those generated labels.
E.g. first bit of macro creates code with label1, label2, label3 etc.
Second bit of macro creates code that updates the values at the aforementioned labels.
As far as I can see this is not possible, at least with the usual labels that seem to be always hard-coded? Any other ideas how to do something like this?
Instead of using a bunch of labels, you can create a list to keep track of the addresses, and then use that list to reach them. Like this:
.var ldas = List()
.macro the_macro_that_creates_the_code() {
.eval ldas.add(* + 1)
lda #0
sta $d020
}
Then, further down in the code:
.macro the_macro_that_refers_to_the_created_code() {
.for (var i = 0; i < ldas.size(); i++) {
lda colors + i,x
sta ldas.get(i)
}
} |
| |
Frostbyte
Registered: Aug 2003 Posts: 166 |
Quote: Instead of using a bunch of labels, you can create a list to keep track of the addresses, and then use that list to reach them. Like this:
.var ldas = List()
.macro the_macro_that_creates_the_code() {
.eval ldas.add(* + 1)
lda #0
sta $d020
}
Then, further down in the code:
.macro the_macro_that_refers_to_the_created_code() {
.for (var i = 0; i < ldas.size(); i++) {
lda colors + i,x
sta ldas.get(i)
}
}
Ahhh of course, brilliant! Thank you! I haven't tried it yet, but I can already see it solves my problem. :) |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
This is probably one of the most asked questions. There are different ways to handle these kind of cases one of them is shown by Trident. Let me point you to another feature that solves it quite nicely.
Normally, when you want label1, label2, etc. the labels are inside a loop, like:
spriteLoop: .for (var i=0; i<8; i++) {
lda data: #0 // <- Fancy inbetween label declaration so you dont need +1
sta $07f8+i
}
You can now use the 'spriteLoop' label to access the 'data' labels of the different iterations of the loop like this:
lda #0
sta spriteLoop[0].data // Sprite 0
sta spriteLoop[1].data // Sprite 1
sta spriteLoop[2].data // Sprite 2
...
// Or simply .for (var i=0; i<8; i++) sta spriteLoop[i].data
If you want to do a table with the addresses, simply:
addrTable: .fill 8, <spriteLoop[i].data
You can access the labels of an executed macros by putting a label in front of the execution, just like we did with the .for loop. |
| |
Slammer
Registered: Feb 2004 Posts: 416 |
With regards to the dicussion earlier in the thread. Several years ago I moved the main feedback/support channel of Kick Assembler to the following facebook group:
https://www.facebook.com/groups/RetroAssembler
This was to ensure a forum were the discussion where not interupted by other things. You are welcome to join regardless of which assembler you are using.
(Please notice that I do not visit this CSDb thread often). |
| |
Frostbyte
Registered: Aug 2003 Posts: 166 |
Quote: With regards to the dicussion earlier in the thread. Several years ago I moved the main feedback/support channel of Kick Assembler to the following facebook group:
https://www.facebook.com/groups/RetroAssembler
This was to ensure a forum were the discussion where not interupted by other things. You are welcome to join regardless of which assembler you are using.
(Please notice that I do not visit this CSDb thread often).
Yesterday I sent a request to join that group, but it's still pending. :) |
| |
Frostbyte
Registered: Aug 2003 Posts: 166 |
Quote: This is probably one of the most asked questions. There are different ways to handle these kind of cases one of them is shown by Trident. Let me point you to another feature that solves it quite nicely.
Normally, when you want label1, label2, etc. the labels are inside a loop, like:
spriteLoop: .for (var i=0; i<8; i++) {
lda data: #0 // <- Fancy inbetween label declaration so you dont need +1
sta $07f8+i
}
You can now use the 'spriteLoop' label to access the 'data' labels of the different iterations of the loop like this:
lda #0
sta spriteLoop[0].data // Sprite 0
sta spriteLoop[1].data // Sprite 1
sta spriteLoop[2].data // Sprite 2
...
// Or simply .for (var i=0; i<8; i++) sta spriteLoop[i].data
If you want to do a table with the addresses, simply:
addrTable: .fill 8, <spriteLoop[i].data
You can access the labels of an executed macros by putting a label in front of the execution, just like we did with the .for loop.
Nice! As in my scenario I don't know how many labels I'll end up with, I suppose in the second loop I could also iterate while i < spriteLoop.size()? (in other words, compiler considers spriteLoop as an array or list?) |