Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Kick Assembler Thread 2
2009-07-21 17:20
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..
2009-07-21 17:55
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.
2009-07-21 18:25
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 :-)
2009-07-21 18:44
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?
2009-07-21 18:47
Oswald

Registered: Apr 2002
Posts: 5017
sounds like a cookie/browser issue. that setting applies to all threads afaik.
2009-07-21 20:27
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.

2009-07-21 20:36
yago

Registered: May 2002
Posts: 332
Slammer: It was probably the LCP aftermath, whole CSDb was sloppy.
2009-07-21 21:10
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

2009-07-21 21:38
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!
2009-08-21 21:16
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?
2009-08-21 22:59
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.
2009-08-22 00:26
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.
2009-08-22 06:48
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.
2009-08-22 12:29
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 :(
2009-08-22 13:00
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.
2009-08-22 13:08
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 :-)
2009-08-22 17:24
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
2009-08-22 20:40
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...
2009-08-23 14:56
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)...
2009-08-23 18:31
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.

2009-08-23 18:35
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 :)
2009-08-23 18:51
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 ^^
2009-08-24 01:57
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?
2009-08-24 13:51
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
2009-08-24 21:06
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!
2009-09-01 22:19
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
2009-09-02 19:52
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.
2009-09-03 12:47
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
2009-09-04 07:13
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 ;-)
2009-09-04 09:50
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
2009-09-04 10:08
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
2009-09-04 10:22
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 :-)
2009-09-04 10:49
Slammer

Registered: Feb 2004
Posts: 416
Conjuror: Im interested. Why don't you upload it to codebase?
2009-09-04 11:42
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!
2009-09-04 11:53
MagerValp

Registered: Dec 2001
Posts: 1055
TextMate bundle added to codebase.
2009-09-04 17:24
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
2009-09-08 12:58
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?
2009-09-08 13:30
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  
2009-09-08 13:54
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.
2009-09-08 19:33
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?
2009-09-08 23:53
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.

2009-09-09 05:00
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*
2009-09-09 06:25
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	
}
2009-09-15 08:38
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

2009-09-15 19:26
Slammer

Registered: Feb 2004
Posts: 416
Hi Andy

First of all, I don’t know the acme syntax, but I’m 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)
2009-09-15 20:25
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 ?)
2009-10-05 20:48
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. :)
2009-10-06 19:46
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.
2009-10-08 21:34
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)
2009-10-10 20:31
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.
2009-10-10 22:07
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.
2009-10-13 11:26
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.

2009-10-28 17:22
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
2009-10-28 21:22
Slammer

Registered: Feb 2004
Posts: 416
Algarbi: Minor error. It is fixed in the new version 3.11 which is now on the website.
2009-10-28 21:32
Iapetus/Algarbi/Wood

Registered: Dec 2004
Posts: 71
Thanx
2009-12-08 20:54
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
2009-12-08 21:47
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.
2009-12-09 08:47
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.
2009-12-09 10:04
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.
2009-12-09 11:12
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 =)
2009-12-10 21:47
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
2009-12-11 21:40
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
}

2009-12-12 16:48
Slammer

Registered: Feb 2004
Posts: 416
tlr: Right now you can't, but i'll put it on the todo list.
2009-12-12 20:42
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)
2010-03-12 08:00
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 ;-) )
2010-03-12 10:35
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.
2010-03-12 10:50
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).
2010-03-13 10:42
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.
2010-03-13 10:46
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!
2010-03-13 16:49
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.
2010-03-14 10:10
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.
2010-03-14 12:18
Mace

Registered: May 2002
Posts: 1799
Haha, and then ppl say JAVA is slow!
2010-03-14 12:18
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)
2010-03-17 19:50
Mace

Registered: May 2002
Posts: 1799
Copied from "What assembler/compiler are you using?"
Quoting Slammer
Whats 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.
2010-03-17 20:52
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.
2010-03-17 21:29
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.
2010-03-19 11:03
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!
2010-03-19 11:56
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.
2010-03-24 19:39
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

2010-03-24 19:48
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.
2010-03-24 20:37
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
2010-04-13 12:22
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.
2010-04-13 12:48
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
2010-04-13 13:11
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).
2010-04-13 14:09
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?

2010-04-13 14:22
Pantaloon

Registered: Aug 2003
Posts: 124
the hashtable entries contains a List that contains structs that are defined like this: .struct Pixel {addr,mask}
2010-04-13 14:28
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.
2010-04-13 15:12
Pantaloon

Registered: Aug 2003
Posts: 124
thx :)
2010-05-21 00:49
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?
2010-05-21 04:08
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
2010-05-21 07:14
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)
2010-05-21 09:31
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 ?
2010-05-21 13:01
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.

2010-05-22 01:08
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?
2010-05-22 10:55
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).
2010-05-22 13:00
TWW

Registered: Jul 2009
Posts: 541
Alright I see now.

Thanx.

-TWW
2010-06-17 19:34
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
2010-06-18 16:52
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.
2010-06-18 19:19
Pantaloon

Registered: Aug 2003
Posts: 124
nice!, hope you get a new computer soon :)
2010-06-29 17:52
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
2010-06-29 21:59
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


2010-06-30 06:37
TWW

Registered: Jul 2009
Posts: 541
Awesome.

Seriously, Thanx for such a cool tool!

TWW/Creators
2010-06-30 13:33
Mace

Registered: May 2002
Posts: 1799
Hmm, 'nested' macros... interesting and simple, yet I never thought of it :-)
2010-08-18 09:36
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
2010-08-20 05:07
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.
2010-09-02 09:11
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.

2010-09-02 10:15
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
2010-09-02 11:10
Pantaloon

Registered: Aug 2003
Posts: 124
i found a better way,

shuffle() that can be done on lists :)
2010-09-02 18:55
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!
2010-09-02 21:19
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*)
2010-09-04 12:56
Slammer

Registered: Feb 2004
Posts: 416
I posted some examples of pseudo commands on codebase64.


2010-09-30 19:20
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.
2010-11-06 16:40
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!
2010-11-06 19:42
Oswald

Registered: Apr 2002
Posts: 5017
RTFM
2010-11-06 19:45
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)
2010-11-06 22:22
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.

2010-11-07 07:03
Oswald

Registered: Apr 2002
Posts: 5017
then "read 2 posts above your own one" :P :)
2010-11-07 11:02
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
2010-11-07 11:55
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

2010-11-07 14:16
Mace

Registered: May 2002
Posts: 1799
Quoting Slammer
There 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.
2010-11-07 14:32
Slammer

Registered: Feb 2004
Posts: 416
OK, I will look into it tonight

When did you download?
2010-11-07 19:35
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?!
2010-11-07 22:28
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..
2010-11-07 23:05
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.
2010-11-10 15:01
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))
  }
}


2010-11-10 15:12
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... :)
2010-11-10 15:43
Cruzer

Registered: Dec 2001
Posts: 1048
JackAsser's solution almost works, except the 0 has to be prefixed:
.var asciivalue = 0 + s.charAt(i)
2010-11-10 15:46
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.
2010-11-10 17:44
Pantaloon

Registered: Aug 2003
Posts: 124
GREAT!
2010-11-16 21:13
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?
2010-11-16 23:41
Cruzer

Registered: Dec 2001
Posts: 1048
Something like this?

.fill theData.size(), theData.get(mod(i,8)*$40 + floor(i/8))
2010-11-17 07:25
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...
2010-11-24 13:14
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.

2010-11-24 13:28
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.
2010-11-24 13:32
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.
2010-11-24 15:40
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.


2010-11-24 17:15
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.
2010-11-24 17:21
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.
2010-11-24 21:05
Slammer

Registered: Feb 2004
Posts: 416
Frantic: With Warpmode your approach might be the fastest way.
2011-01-15 09:51
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!
2011-01-15 13:06
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"
2011-01-15 13:09
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\"
2011-01-15 21:23
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.
2011-01-16 06:38
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!
2011-03-18 18:49
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
2011-03-19 10:35
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)			
}
2011-03-19 13:27
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-)
2011-03-20 08:37
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.
2011-03-21 02:49
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?
2011-03-21 23:09
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.


2011-03-21 23:58
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
2011-03-23 17:51
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)..
2011-05-06 07:56
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.
2011-05-06 09:17
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
2011-05-06 09:26
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.
2011-05-09 19:01
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?
2011-05-09 19:40
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?
2011-05-09 19:50
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.
2011-05-10 00:23
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
2011-05-10 09:43
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.
2011-05-10 10:47
Conjuror

Registered: Aug 2004
Posts: 168
Thanks Mace, thats just embarrassing. I was very tired today.
2011-05-10 18:24
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.
2011-05-10 18:37
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 :-)
2011-07-22 04:59
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...

2011-07-22 08:15
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.

2011-07-22 09:32
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.
2011-07-22 10:16
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)
2011-07-22 12:09
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.
2011-07-22 13:16
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!
2011-07-22 13:29
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..
2011-07-22 21:13
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
	}


2011-07-23 07:20
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.
2011-07-23 14:06
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.
2011-07-23 16:06
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

2011-08-01 15:00
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... ;)
2011-08-01 15:44
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.
2011-08-01 18:41
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?
2011-08-02 10:12
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).
2011-08-02 10:36
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?
2011-08-02 10:40
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
2011-08-02 11:21
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)
2011-08-07 18:25
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...
2011-08-08 17:39
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.
2011-08-09 07:18
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.
2011-08-17 18:55
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?
2011-08-17 19:23
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?
2011-08-17 19:37
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.
2011-08-17 19:41
Slammer

Registered: Feb 2004
Posts: 416
Also remember to switch off the rom and use $fffe/$ffff for irq.
2011-08-18 19:51
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.
2011-08-25 11:19
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
2011-08-25 16:37
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.
2011-08-25 17:01
tlr

Registered: Sep 2003
Posts: 1714
Quoting Slammer
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.

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.
2011-08-25 19:03
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.
2011-08-26 12:56
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!
2011-08-31 19:15
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


2011-08-31 20:02
Slammer

Registered: Feb 2004
Posts: 416
Thanks. It's corrected in the next release.
2011-09-07 19:01
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
or
inc.z label
lda.a $0000
Btw. the 'chars inheriting from number' issue was implemented in v3.19
2011-09-07 19:29
tlr

Registered: Sep 2003
Posts: 1714
Great!
2011-09-24 09:35
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
or
inc.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

2011-09-24 17:08
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.
2011-09-24 22:36
tlr

Registered: Sep 2003
Posts: 1714
Quoting Slammer
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.

Dasm does have that approach but I consider it very confusing.

I've even changed that in my own version of dasm.
2011-09-27 14:39
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!
2011-09-27 14:52
Cruzer

Registered: Dec 2001
Posts: 1048
Something like this?...

.var length = end - start
start:
    nop
end:
.print "length:" + length

2011-09-27 17:32
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!
2011-10-01 08:58
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.
2011-10-01 16:01
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
2011-10-01 16:10
tlr

Registered: Sep 2003
Posts: 1714
Quoting Slammer
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? ...


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?
2011-10-01 17:46
Pantaloon

Registered: Aug 2003
Posts: 124
ohh, i didnt know of the importonce, lovely!!!
2011-10-02 09:34
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 :-)

2011-10-02 14:32
tlr

Registered: Sep 2003
Posts: 1714
Quoting Slammer
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.

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.
2011-10-05 03:37
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!
2011-10-05 15:42
Cruzer

Registered: Dec 2001
Posts: 1048
TWW: Why not use a parameter for that?
2011-10-05 17:04
TWW

Registered: Jul 2009
Posts: 541
That's what I'm currently doing so yes, this is a luxory feature request 8-D
2011-10-05 17:09
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.
2011-10-05 17:37
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.
2011-10-05 18:20
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. 
*/

}
2011-10-05 18:30
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.
2011-10-05 19:11
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.
2011-10-05 19:55
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?
2011-10-06 21:51
Slammer

Registered: Feb 2004
Posts: 416
No .ifdefined yet. What are you going to use it for?
2011-10-06 22:38
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^^
2011-10-08 09:38
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 */
	}	

}
2011-10-12 16:40
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.
2011-10-19 11:46
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

					}
				}

			}
		}

2011-11-01 15:21
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'

2011-11-02 07:11
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.
2011-11-02 08:10
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
2011-11-02 13:07
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.


2011-11-02 19:42
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.
2011-11-03 07:29
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.

2011-11-03 08:55
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.
2011-11-03 10:20
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)

2011-11-03 15:21
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.
2011-11-03 15:37
Dr.j

Registered: Feb 2003
Posts: 276
Ok Guyz..10x for the help
2011-11-03 17:38
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
2011-11-03 19:47
Slammer

Registered: Feb 2004
Posts: 416
I'll check it in the weekend.

(I guess the missing .s in the sourcecode is a typo)
2011-11-03 19:51
Pantaloon

Registered: Aug 2003
Posts: 124
yes that is a typo :)
2011-11-05 15:17
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

2011-11-05 22:55
Pantaloon

Registered: Aug 2003
Posts: 124
thanks alot slammer!!! :)
2011-12-01 11:48
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?
2011-12-02 09:23
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 :)
2011-12-04 13:57
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?
2011-12-04 14:08
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).




2011-12-04 15:58
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
2011-12-04 22:56
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.
2011-12-08 20:37
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.
2011-12-11 02:18
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
2011-12-11 17:37
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.)
2011-12-12 00:05
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!
2011-12-12 22:00
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.
2011-12-12 23:03
Pantaloon

Registered: Aug 2003
Posts: 124
coding is always fun :)
2011-12-13 12:15
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.
2011-12-29 09:14
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
2011-12-29 21:27
Slammer

Registered: Feb 2004
Posts: 416
Hi Style

Normal macros have to have the right number of arguments.

Pseudocommands can have empty parameters
2011-12-30 03:18
Style

Registered: Jun 2004
Posts: 498
any chance you can overload macros? :)

2011-12-30 17:02
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.
2011-12-31 04:40
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.
2011-12-31 11:04
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)
2012-02-04 13:45
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

2012-02-05 02:36
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.

2012-02-08 12:56
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! :)
2012-02-08 15:55
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
}
2012-02-08 16:29
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)

2012-02-08 22:35
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.



2012-02-08 22:43
McKrackeN

Registered: Feb 2011
Posts: 20
Yes!! That's it!! Thanks for your help and for this amazing compiler!!
2012-02-10 22:38
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?
2012-02-19 12:39
Slammer

Registered: Feb 2004
Posts: 416
Suppose by invert you mean exclusive or you can:
.fill 256,data.get(i)^$ff
2012-02-19 13:27
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)
2012-02-19 16:13
TWW

Registered: Jul 2009
Posts: 541
Yepp, that's exactly what I ment. Thanx Slammer!
2012-02-19 16:24
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 
   }
2012-02-19 17:47
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 :/
2012-02-20 20:36
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
2012-03-12 11:28
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?
2012-03-13 15:46
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(*)
2012-03-13 20:44
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.

2012-03-13 23:51
Norrland

Registered: Aug 2011
Posts: 14
Thanks for the answers, I'll try them.
2012-04-17 21:20
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
2012-04-17 22:00
Killsquad
Account closed

Registered: Jun 2005
Posts: 17
To get the numeric value of the params use max.getValue(), min.getValue() and freq.getValue().
2012-04-17 22:15
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!
2012-04-18 11:11
Cruzer

Registered: Dec 2001
Posts: 1048
Mace: Seems more like a job for a macro. Then you don't have to use getValue()
2012-04-18 18:27
Mace

Registered: May 2002
Posts: 1799
Thanks Killsquad.
@Cruzer: yeah, probably... was just foolin' around 'n stuff ;-)
2012-04-18 18:39
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.
2012-04-30 08:12
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)


2012-04-30 10:09
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

2012-04-30 13:37
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.
2012-04-30 18:25
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.
2012-04-30 20:27
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.
2012-05-03 13:29
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.
2012-05-03 18:44
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.

2012-05-06 03:06
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)
2012-05-06 12:14
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.
2012-05-06 12:17
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"

2012-05-06 12:20
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.
2012-05-07 05:18
JackAsser

Registered: Jun 2002
Posts: 1989
@Ruk, @Groepaz: Well... cpp is free, easy to use and easy to integrate into your makefiles so... :)
2012-05-07 05:22
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)
2012-05-07 06:45
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?
2012-05-07 20:47
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!)
2012-05-08 06:28
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)
2012-05-09 10:45
Frantic

Registered: Mar 2003
Posts: 1627
In fact, there are sources available for RGBDS:
http://www.otakunozoku.com/rednex-gameboy-development-system/
2012-05-09 11:52
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)
2012-06-07 10:48
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.
2012-06-07 21:40
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.
2012-06-09 15:34
Conrad

Registered: Nov 2006
Posts: 833
Is there a commandline to output files bigger than 64K? ... for the case of writing .crt files?
2012-06-09 23:58
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.
2012-06-10 08:20
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.
2012-06-11 09:27
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.
2012-06-15 18:53
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.
2012-06-16 09:44
Pantaloon

Registered: Aug 2003
Posts: 124
slammer, NICE!
2012-06-16 20:19
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. :)
2012-06-17 17:40
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

2012-06-18 07:46
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.
2012-06-18 09:25
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.
2012-06-19 09:29
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.
2012-06-19 12:52
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!
2012-06-20 14:47
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.



2012-06-20 19:30
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.
2012-07-05 20:33
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.
2012-07-06 15:14
tlr

Registered: Sep 2003
Posts: 1714
@slammer: Very cool feature!
2012-07-19 20:07
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)
2012-07-20 07:08
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'?
2012-07-20 07:18
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 :)
2012-07-20 08:32
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?
2012-07-20 08:50
MagerValp

Registered: Dec 2001
Posts: 1055
Quoting Slammer
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'?

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
2012-07-20 08:54
Conjuror

Registered: Aug 2004
Posts: 168
Joomla allows you to download pages as PDF. I'm sure other CMS's allow that too.
2012-07-20 10:51
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..
2012-07-22 18:01
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.
2012-07-22 22:12
Slammer

Registered: Feb 2004
Posts: 416
Thanks for the input. I'll check it out.
2012-07-23 07:05
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. :)
2012-07-23 11:44
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.
2012-07-23 20:10
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?
2012-08-08 03:54
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 ;-)
2012-08-08 07:08
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
2012-08-08 08:01
Cruzer

Registered: Dec 2001
Posts: 1048
@Ruk: That would of course require a 256 chars long table to avoid index out of bound.
2012-08-08 09:44
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 =)
2012-08-08 11:26
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.
2012-08-09 03:52
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.
2012-08-09 12:03
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 :)
2012-09-30 07:05
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.
2012-09-30 13:43
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.


2012-10-01 00:55
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.
2012-10-01 07:54
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.
2012-10-01 10:12
Slammer

Registered: Feb 2004
Posts: 416
Try this one, http://www.theweb.dk/KickAssConrad.jar
2012-10-01 17:03
Conrad

Registered: Nov 2006
Posts: 833
Quote: Try this one, http://www.theweb.dk/KickAssConrad.jar

Thanks Slammer, that one works perfect! :)
2012-10-04 07:50
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?
2012-10-04 13:49
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.
2012-10-04 15:19
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 :-).
2012-10-04 16:54
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. ;)
2012-10-06 20:06
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?

2012-10-07 07:32
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.
2012-10-15 15:10
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.
2012-10-15 20:58
Digger

Registered: Mar 2005
Posts: 421
Love you Slammer! Just-in-time before the X! :)
2012-11-11 01:51
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"
2012-11-11 08:38
Mace

Registered: May 2002
Posts: 1799
I suggest you read chapter 10 of the manual, Modifiers.
2012-11-11 15:58
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

2012-11-11 16:27
TWW

Registered: Jul 2009
Posts: 541
ok mace/slammer, thanx. That's what I thought. Time to brush up on java :-)
2012-11-27 17:32
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...
2012-11-27 17:35
chatGPZ

Registered: Dec 2001
Posts: 11113
simply use labels :)
yourlabel:
lda table,x
...
inc yourlabel+1
...
table:

2012-11-27 17:39
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... :(
2012-11-27 17:44
The Gothicman
Account closed

Registered: Aug 2011
Posts: 40
Allright...
I DIDN'T use labels...
I used vars... :(

Haha... I'm so... ... ... ;)

Thanx...
2012-12-04 00:21
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 :)
2012-12-04 11:09
Cruzer

Registered: Dec 2001
Posts: 1048
Raven: If you use vars you can:
.var value = 0
.if (something) {
	.eval value = 1
}

2012-12-04 11:15
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.
2012-12-04 11:17
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?


2012-12-04 11:20
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
2012-12-04 12:29
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.
2012-12-04 18:29
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.
2012-12-04 23:05
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.
2012-12-05 08:07
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;".
2012-12-05 18:54
Slammer

Registered: Feb 2004
Posts: 416
Frantic, That is a possibility. The notation is a bit cryptic but i will do the job.
2012-12-05 22:12
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.
2012-12-06 06:13
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.
2012-12-06 12:42
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 =)
2012-12-06 16:49
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.




2012-12-07 11:31
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
2012-12-07 11:43
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
2013-01-27 12:32
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!! :)
2013-01-27 12:57
Cruzer

Registered: Dec 2001
Posts: 1048
FATFrost: Did you remember -jar? E.g. java -jar KickAss.jar
2013-01-27 15:58
FATFrost
Account closed

Registered: Sep 2003
Posts: 211
er...let me have look// :)

2013-01-27 16:01
FATFrost
Account closed

Registered: Sep 2003
Posts: 211
Yeahz!! got it working nice!! Thanks Cruzer!!
2013-02-12 16:39
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?
2013-02-12 19:27
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.
2013-02-17 08:52
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?
2013-02-17 10:19
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

2013-02-17 16:02
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?
2013-02-17 17:55
Slammer

Registered: Feb 2004
Posts: 416
Never thought of that. If there is a need then I'll put it in the todo list.
2013-02-17 19:23
Cruzer

Registered: Dec 2001
Posts: 1048
Good idea, TWW! I vote for putting it on the TODO list.
2013-02-17 23:13
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).
2013-03-18 08:57
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?
2013-03-18 09:16
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
2013-03-18 09:45
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



2013-03-18 10:11
Cruzer

Registered: Dec 2001
Posts: 1048
Change the macro to this, to avoid immediate addressing mode:
.macro setBackground(color) {
	lda color
	sta $d021
}
2013-03-18 10:34
Carlos
Account closed

Registered: Mar 2009
Posts: 15
Great! didn't notice that.. thks Cruzer.
2013-03-18 18:19
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..
2013-03-22 12:00
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)
2013-03-22 17:02
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..
2013-03-22 17:04
chatGPZ

Registered: Dec 2001
Posts: 11113
mmmmh. whats the difference between a struct and a namespace then? *shrug*
2013-03-22 20:32
Pantaloon

Registered: Aug 2003
Posts: 124
groepaz, you dont know the difference between namespace & structs ? i hope you are trolling :)
2013-03-22 21:10
Cruzer

Registered: Dec 2001
Posts: 1048
Groepaz doesn't even know the difference between .align and .fill :P
2013-03-22 21:45
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..
2013-03-22 22:53
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.
2013-03-25 02:55
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.
2013-04-16 07:37
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.

2013-04-16 08:20
Pantaloon

Registered: Aug 2003
Posts: 124
You can't. You can see kickasm as a preprocessor only.
2013-04-16 10:06
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.
2013-04-16 12:11
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.
2013-04-16 12:57
Pantaloon

Registered: Aug 2003
Posts: 124
the manual is quite clear what can be done and not with macros.
2013-04-16 16:58
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.
2013-05-11 17:04
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.
2013-05-12 09:51
JackAsser

Registered: Jun 2002
Posts: 1989
@slammer: interesting read on a good example! Cudos!
2013-05-12 19:27
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.
2013-05-12 21:17
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 =)
2013-05-12 21:46
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.
2013-05-12 21:50
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.
2013-05-12 21:53
chatGPZ

Registered: Dec 2001
Posts: 11113
slammer: convince peacemaker to use another assembler, and i won't touch kickass ever again - promised =P
2013-05-13 06:22
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. ;-)
2013-05-13 07:04
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
2013-05-13 07:30
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
2013-05-13 08:40
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.
2013-05-13 10:46
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.
2013-05-13 12:09
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.
2013-05-13 13:49
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)
2013-05-13 16:21
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.
2013-05-13 21:44
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.
2013-05-15 18:37
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).
2013-05-17 18:07
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
2014-12-17 10:40
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 ?
2014-12-18 18:26
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 :-)
2014-12-18 22:52
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 ;)
2014-12-19 06:45
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.
2014-12-19 10:13
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 ;)
2014-12-19 17:30
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.
2014-12-20 12:50
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...
2015-01-04 15:20
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.
2015-01-04 20:34
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
2015-01-13 11:04
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?
2015-01-13 16:46
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.
2015-03-23 13:43
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...
2015-03-23 16:18
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
2015-03-24 11:01
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.
2015-03-24 16:39
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.
2015-03-24 16:49
Pantaloon

Registered: Aug 2003
Posts: 124
i was waiting for that comment from Groepaz :)
2015-03-24 17:32
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.
2015-03-24 18:24
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.
2015-03-24 18:39
soci

Registered: Sep 2003
Posts: 473
Works as designed, it seems.
2015-03-24 18:56
chatGPZ

Registered: Dec 2001
Posts: 11113
i am not doubting that at all :)
2015-03-24 18:56
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.
2015-03-24 19:02
soci

Registered: Sep 2003
Posts: 473
Oswald, that was a good example why using *+ and *- is really error prone:
bcc *+3
inc $03
2015-03-24 19:05
chatGPZ

Registered: Dec 2001
Posts: 11113
hey, that way debugging never becomes a bore! =)
2015-03-24 19:11
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.
2015-03-24 20:11
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 ;)
2015-03-24 20:54
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 *+. :)
2015-03-24 21:26
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.
2015-03-24 21:58
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
2015-03-25 08:04
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. :)
2015-03-25 08:36
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..?!)
2015-03-25 09:00
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.
2015-03-25 09:31
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! ;)
2015-03-25 09:51
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 :)
2015-03-25 12:20
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.
2015-03-25 14:41
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\
2015-03-25 15:48
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?
2015-03-26 21:23
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.
2015-03-27 00:07
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
2015-03-27 00:45
Agemixer

Registered: Dec 2002
Posts: 38
Thanks Slammer
2015-04-30 09:40
Murphy

Registered: Jul 2006
Posts: 10
Slammer: Thanks for this awesome assembler!

Support of |= (and &=) operators are planned?
2015-04-30 12:37
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.
2015-05-01 07:30
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.
2015-05-01 10:46
Murphy

Registered: Jul 2006
Posts: 10
Thanks Slammer! The source was sent in PM.
2015-05-01 12:48
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
}
2015-05-03 16:31
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.
2015-05-03 16:43
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.
2015-05-03 16:59
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
2015-05-03 21:28
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. :)
2015-05-23 15:24
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.
2015-05-23 16:30
Slammer

Registered: Feb 2004
Posts: 416
BMPPattern contains a value for which the << operator is not defined. Could it be null?
2015-05-24 13:50
TWW

Registered: Jul 2009
Posts: 541
Yepp. That was precisely it.
2015-07-09 21:19
Killsquad
Account closed

Registered: Jun 2005
Posts: 17
Any update on .ifdef/.ifndef directives? Would be very handy.
2015-07-10 07:07
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.
2015-07-10 07:33
Murphy

Registered: Jul 2006
Posts: 10
Slammer: Really great improvements!

I can't wait! :)
2015-07-10 12:25
Killsquad
Account closed

Registered: Jun 2005
Posts: 17
That is great news, Slammer. Looking forward to it.
2015-10-24 10:32
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?
2015-10-24 14:54
Pantaloon

Registered: Aug 2003
Posts: 124
great news, will 4.x version be released before christmas ?
2015-10-25 23:27
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.
2015-10-25 23:30
Slammer

Registered: Feb 2004
Posts: 416
subjik: I haven't updated yet. Hoping to hear from others who have.
2015-10-27 07:33
Jammer

Registered: Nov 2002
Posts: 1289
Are there plans to introduce more handy arrays with x dimensions instead of workaround with list and hashtags? ;)
2015-11-01 12:06
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.
2015-11-01 17:34
Dr.Science

Registered: Oct 2011
Posts: 39
Having the same issue as Subjik on OSX!
2015-11-01 18:00
Slammer

Registered: Feb 2004
Posts: 416
Ok, Could I get you to post the exact commandline you are using to run KickAssembler
2015-11-03 09:30
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 ;)
2015-11-11 22:09
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
2015-11-12 11:54
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
2015-11-12 18:44
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.
2015-11-13 22:06
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
2015-11-14 20:39
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
}
2015-11-15 10:49
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?
2015-11-15 16:55
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
2015-11-22 20:21
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.
2016-01-10 00:02
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' ;)
2016-01-10 00:13
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 :)
2016-01-10 09:11
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.
2016-01-10 17:07
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... :)
2016-01-10 17:09
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.
2016-01-10 17:26
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.
2016-01-11 14:05
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?
2016-01-11 16:56
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.
2016-01-11 17:04
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 :)
2016-01-11 17:14
Jammer

Registered: Nov 2002
Posts: 1289
Quoting Slammer
Jammer: 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
2016-01-11 17:33
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?
2016-01-11 17:38
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? :)
2016-01-11 18:38
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.
2016-01-11 18:59
Jammer

Registered: Nov 2002
Posts: 1289
TWW, Slammer has already pointed me to the right answer. I was asking rather about export thing :)
2016-01-11 20:49
IanC
Account closed

Registered: Sep 2010
Posts: 2
Quoting Groepaz
PS: 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.
2016-01-12 07:35
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'.
2016-01-12 12:18
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)
2016-01-25 21:53
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...
2016-01-26 17:46
The Gothicman
Account closed

Registered: Aug 2011
Posts: 40
Wow! I -was- drunk...

Haha... Fuck the shit... :)
2016-01-26 17:55
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".
2016-01-26 18:35
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. ;)
2016-03-07 20:53
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)?
2016-03-08 06:15
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)
2016-03-08 16:33
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!
2016-03-08 19:22
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?
2016-03-08 19:38
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 :)
2016-03-08 20:12
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.
2016-03-08 20:20
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 :-) )
2016-03-08 20:23
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?
2016-03-09 05:57
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 :)
2016-03-09 06:25
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:
2016-03-13 14:08
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.
2016-03-13 14:16
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
			}
		}
	}
2016-03-13 15:49
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)
2016-03-13 15:58
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 ;)
2016-03-13 16:36
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)
2016-03-13 17:31
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 ;)
2016-03-13 20:04
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?
2016-03-14 06:31
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.
2016-09-01 21:29
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)
2016-09-01 21:38
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 ^^
2016-09-02 12:20
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
2016-09-02 16:47
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
2016-09-02 17:22
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.
2016-09-03 15:46
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")
2016-09-03 18:32
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.
2016-10-19 04:32
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(^^).
2016-10-19 07:44
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).
2016-10-21 19:37
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 ?
2016-10-22 16:46
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 ?
2016-10-22 18:18
lA-sTYLe

Registered: Sep 2003
Posts: 63
no idea why, nor used to Kickass,

but how about .byte $2c,$01 ?
2016-10-22 18:44
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 ;)
2016-10-22 18:59
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.
2016-10-22 19:50
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 :(
2016-10-30 15:11
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 :(
2016-10-30 15:40
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.
2016-10-31 11:10
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.
2016-11-07 08:31
Mace

Registered: May 2002
Posts: 1799
<deleted by user>
2016-11-11 21:39
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.
2016-11-11 22:09
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
2016-11-12 09:01
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.
2016-11-12 11:27
Mace

Registered: May 2002
Posts: 1799
Ok, this is a confirmed bug that will be resolved in the next update.
2017-02-16 04:14
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()
2017-02-16 13:56
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
2017-02-16 14:44
Norrland

Registered: Aug 2011
Posts: 14
Thx Knut, will try that!
2017-07-04 15:09
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.
2017-07-04 20:54
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
2017-07-04 21:38
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 ;)
2017-07-04 21:52
chatGPZ

Registered: Dec 2001
Posts: 11113
this is not normal method
2017-07-04 22:21
Jammer

Registered: Nov 2002
Posts: 1289
Normal is boring? ;)
2017-08-10 13:25
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?
2023-03-29 21:34
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
2023-03-30 06:41
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.
2023-03-30 20:00
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.
2023-06-13 09:46
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.
2023-06-27 05:40
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,
2023-06-27 17:09
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).
2023-06-27 21:19
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.
2023-07-01 08:58
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?
2023-07-01 09:12
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.
2023-07-03 10:23
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.
2023-07-03 16:01
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."
2023-07-04 07:39
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? :-)
2023-07-04 08:38
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...
2023-07-05 12:54
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.
2023-07-06 10:38
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.
2023-07-06 11:40
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 :)
2023-07-06 17:07
Krill

Registered: Apr 2002
Posts: 2839
But does KA support canonical 6502 ASM syntax (like "symbol = $1234" without .var or .const) now? =)
2023-07-07 14:58
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…..
2023-07-07 16:47
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.
2023-07-07 17:50
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
2023-07-07 18:31
Krill

Registered: Apr 2002
Posts: 2839
Quoting TWW
Agreed, 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. :)
2023-07-07 20:43
Stone

Registered: Oct 2006
Posts: 168
@TWW: I was pompous, sure, but not sarcastic. There was no malice.
2023-07-09 19:20
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
2023-07-11 03:06
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. :)
2023-07-11 17:41
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?
2023-07-12 09:32
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.
2023-08-09 17:56
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?
2023-08-09 18:54
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)
}
}
2023-08-09 21:51
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. :)
2023-08-09 22:35
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.
2023-08-09 22:40
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).
2023-08-10 12:49
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. :)
2023-08-10 12:54
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?)
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Mike
Martin Piper
pcollins/Quantum
digix
rambo/Therapy/ Resou..
Guests online: 148
Top Demos
1 Next Level  (9.8)
2 Mojo  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Comaland 100%  (9.6)
6 No Bounds  (9.6)
7 Uncensored  (9.6)
8 Wonderland XIV  (9.6)
9 Bromance  (9.6)
10 Memento Mori  (9.6)
Top onefile Demos
1 It's More Fun to Com..  (9.7)
2 Party Elk 2  (9.7)
3 Cubic Dream  (9.6)
4 Copper Booze  (9.5)
5 TRSAC, Gabber & Pebe..  (9.5)
6 Rainbow Connection  (9.5)
7 Onscreen 5k  (9.5)
8 Wafer Demo  (9.5)
9 Dawnfall V1.1  (9.5)
10 Quadrants  (9.5)
Top Groups
1 Oxyron  (9.3)
2 Nostalgia  (9.3)
3 Booze Design  (9.3)
4 Censor Design  (9.3)
5 Crest  (9.3)
Top Coders
1 Axis  (9.8)
2 Graham  (9.8)
3 Lft  (9.8)
4 Crossbow  (9.8)
5 HCL  (9.8)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.957 sec.