'Ere mister, wanna learn machine code? Well you've come to the right place ain't ya? Yup, welcome to another installment of the Hex Files and, as is becoming fairly common ground now, I'll start off by having a look at the solution to the "challenge" (since some people have said they are too easy) set in the previous installment. If you remember, we had a simple scroll routine and I asked you to move it down a line and change where the data was coming from to $e460. Here's the modified routine:
* = $0900
main ldx #$00
raster cmp $d012
move_loop lda $0429,x
sta $0428,x ; read/write moved from $0400/1
lda $e460,y ; reads the new "text" from $e460
sta $044f ; and this used to be $0427
Right, at this point you're all saying something along the lines of "that's all very well, but what good is it?" On it's own not an awful lot, but if you start adding other things to it you get a little demo and that's just what we are going to do. Now I expect you are all wondering how I expect you to be able to understand the code for a demo, right? Well, it's not going to be a complex demo, just something simple with sprites, a piece of music and a slightly more complex scrolling message than the one above. And you don't even have to type the code in, it's all available to download as we go if you feel lazy! So first, download this installment's example data, extract everything to the same directory and drop demo_1.asm into a passing text editor so we can have a prod around.
First off, since this is such a large piece of source I'll cover it in chunks and any commands we haven't covered already will be explained on the way past. The first part of the source is responsible for initialization, the setting up of the computer.
scrlcount = $0340
messcount = $0341
sineposx = $0342
sineposy = $0343
sine_curve = $0e00
sine_curve_2 = $0f00
The above assigns the names scrlcount, messcount, sineposx and sineposy to various locations in memory and specify where to look for the two sine curves that are about to be loaded in. Apart from the curves, these are our counters for various pieces of the code and the memory they have been given is part of the cassette buffer so will cause no problems.
These three are "INClude BINary" file commands; they're not 6510 machine code instructions but assembler directives, in other words they tell C64Asm to load those binary files and include them in the final PRG it makes. In this case, they're the sprite definitions (at $0c00 to $0dff), the sine curves we'll use to make the sprites move (at $0e00 to $0fff) and finally a piece of music by Sean of Cosine (at $1000 to $1xxxx).
As usual the * command tells the assembler where we want our code put, in this case at $0900. And next we have a new 6510 command, SEI means SEt Interrupt disable status and basically it turns off the C64's interrupts which would otherwise interfere with the running of our code. You may have noticed the occasional jump in the old scroller as the system interrupts occurred at the same point on the screen as the routine and we don't want that. The actual use of SEI (for setting up interrupts) will be covered later on.
clrpage lda #$20
Okay, this is one of those loop thingies isn't it? Yes, just like the loops we have seen before it's just putting a repeated character onto the screen. It's a bit different in that it does the whole screen and the colour memory at $D800 as well. You may be wondering about the last location being $06E8, well this is a little trick; the screen memory is 1,000 bytes long and runs from $0400 to $07E7 and the maximum value a register can hold is $FF so $06E8 + $ff is $07E7. It saves having to do a shorter loop for the last bit of the screen. The value $20 is the space character so the whole screen is cleared and the value $0f is going to the colour memory to set all the characters light grey.
This next piece of code puts 0 into the screen and border colours, making them black and also zeroes off our counters - at least, all except sineposy which we want to be different for the sine effect to work so it has a value of $40 instead.
Right, I've assumed that you all have some knowledge of sprites from the C64's manual but we'll clarify a little to be sure; the above four lines will, in order, turn on all eight sprites ($d015), make them multicolour ($d01c) and also alter their priority to put them under any characters on the screen like our scroller ($d01d). The eight bits in each of these locations represent one sprite, so the first sprite is the lowest bit and the last is the highest; since a value of #$ff has all of it's bits set that means all eight sprites are being turned on and then all have their multicolour enabled and are set to "low" priority.
setsdp sta $07f8,x
Next we set the sprite data pointers (S.D.P.'s for short) using another loop. But this time there are two commands we haven't covered again. These are CLC (CLear Carry flag) and ADC (Add Decimal Accumulator). The former's job is to empty the carry flag, which is one of a series of flags the C64 uses to remember things (in this case, it's an "overflow" for various calculations). The reason for it's use here will not be immediately apparent until I explain the ADC command that follows it.
ADC #$01 will add one to whatever value is in the accumulator, so if it's presently $30 as at the start of the loop the ADC command will make it $31. It's like the INX command except that by changing the value you can alter how much the A changes by and, if the carry flag is set from any previous job, then it will be added in too! Since we don't want this to happen here because the carry will only have been set by something we don't want to affect this particular job, we use the CLC first.
But what does this loop actually do? Well, it puts a value of $30 into $07F8, a value of $31 into $07F9 and so on until it puts $37 into $07Ff, all of which point the VIC to $0C00, $0C40 and so on to $0dC0 for the sprite data. If you look at those sprites in memory they spell H E X F I L E S (we have put in two E definitions to make this a bit easier for now).
spritec sta $d027,x
Now we have to set the sprite colours. $D027 onwards govern the sprite colours and the value of $0e will produce the same light blue as the border colour when the C64 is turned on. The multicolours are set to dark grey and light grey so the sprites can have a nice shading effect.
The final part of the setup we will cover this issue is another new command. JSR means Jump to Sub Routine and it's the machine code equivalent of the BASIC command GOSUB. Up until now we have used the RTS command to drop back to BASIC after our code has finished, but if we were to JSR to a piece of code an RTS would return us back to the next command along so it allows us to pop off temporarily and do something else, then come back and continue where we left off. In this case it calls the part of the music routine (it was included earlier with the INCBIN command, remember?) that sets the music up for playing and turns the volume on. The LDA #$00 is to tell the music routine that we want tune 0, the first one it has and later on there's a JSR $1003 that actually plays the music.
Right, that's yer lot for another time, I hope you're all following okay. If you want to, you can try to carry on alone and examining the rest of the program, although there are some new commands I will cover in the next installment. And your mission, should you decide to accept it, is to try and change the sprite colours to $04 (for purple) and the message colour to $01 (for white). Good luck and, as usual, you can contact me if you have any questions on this installment. This web site will self destruct in ten seconds.
The source code for the routines above can be downloaded here for easier reference.