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..
 
... 590 posts hidden. Click here to view all posts....
 
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: 11115
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.
Previous - 1 | ... | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | ... | 61 - Next
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
Andy/AEG
Acidchild/Padua
Aomeba/Artline Desig..
jmin
Didi/Laxity
Sentinel/Excess/TREX
serato/Finnish Gold
pcollins/Quantum
iceout/Avatar/HF
Krill/Plush
Guests online: 129
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 Memento Mori  (9.6)
10 Bromance  (9.5)
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 Wafer Demo  (9.5)
8 Dawnfall V1.1  (9.5)
9 Quadrants  (9.5)
10 Daah, Those Acid Pil..  (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 Logo Graphicians
1 Sander  (10)
2 Facet  (9.7)
3 Mermaid  (9.4)
4 Pal  (9.4)
5 Shine  (9.3)

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