Oldschool Gaming - reviewing new games on classic computers
The Hex Files :: Part 5 :: written by Jason Kelk :: added 28 Jan 2004

Righto, time for some more codewriting entertainment! Now, where were we? Ah yes, the challenge from the previous installment; your mission, if you decided to accept it was to change the text colour to light blue and the sprite colour to dark blue. The text colour is altered by changing the LDA #$0F on line 25 of the source to LDA #$0E or indeed any colour you want. To change the sprites look at line 62. It reads LDA #$0C and to make them purple use LDA #$04. All sorted now? Good, lets get back to dissecting the remaining code, starting from line 71;

main		lda #$fc
rashold		cmp $d012
		bne rashold

Now our friend the raster has been introduced to us a couple of installments back, and the principle remains the same; the C64 projects the screen to the TV a line at a time and this loop waits for line $FC, which is just off the bottom of the standard screen. From here onwards the term "frame" will denote one complete scan of the screen by the raster, so one frame is a 50th of a second.

		ldx scrlcount
		inx
		stx scrlcount
		cpx #$08
		bne dontmove

Right, we've already discussed using labels as places to keep numbers. scrlcount is our smooth scroll counter, it's counting how many frames have passed up to a maximum of eight to delay our scroller since moving it every frame would be far too fast to read. It's also used to work out what value should be in $D016 later on, but I'll explain that when we get there.

		ldx #$00
scrlmove	lda $05e1,x
		sta $05e0,x
		inx
		cpx #$27
		bne scrlmove
		ldx messcount
		lda scrolltext,x
		sta $0607
		inx
		stx messcount

Well, this section has covered before too and it's basically the same scroll shifting routine we had moving so quickly previously. This time, however, we are reading from our own message in the computers memory at wherever the label scrolltext is. That gets defined later, don't worry.

		ldx #$00
		stx scrlcount

Because we've just finished a "move" of the scroller we now have to reset our counter so that the machine will wait another eight frames before doing it again. Okay, now earlier we branched to dontmove if we were not going to move the scroll, so lets see where that leads us.

dontmove	txa
		eor #$07
		sta $d016

Okay, this is just a little bit of trickery to set the smooth scrolling up for our message. TXA we have already covered, but EOR is new. EOR (or Exclusive OR) is what is known as a logic gate. There are three regularly used gates, ORA (known as just an OR gate, but called ORA because all 6510 commands are three letters long, so we add an A for accumulator), EOR and AND. ORA works like this:

	LDA #$64		or in binary %01100100
	ORA #$C7		or in binary %11000111

	Leaves A as #$E7	or in binary %11100111

Why? Well, look at the first column of binary numbers. The first two are a 0 in the top row and a 1 in the second and the "rule" is that if either the first OR the second number (or indeed both) is a 1 the answer, in the third number in the column will also be 1. If both numbers are a 0 the answer will be a 0, just like the fourth and fifth columns. AND works on a similar principle, except that the first number AND the second number must be a 1 for the outcome to be a 1, otherwise the answer is 0. If only one of the numbers is a 1 then the answer is a 0, meaning that if the ORA above is replaced with an AND the binary answer will be %01000100.

Now for our little friend EOR. The result of our above example after using EOR instead of ORA would be %10100011 because EOR works by a different means. Again, it compares the columns separately, but if the second number is a 1 it takes the first number and toggles it, changes it from a 0 to a 1 or vice versa. If the content of the second number is a 0 nothing changes, and the content of the first passes straight through. So the result of EOR #$07 on our counter, which runs from $00 to $07 is to basically invert it so that it goes from $07 to $00 and we can then put this into $D016 for the smooth scrolling.

Okay, so now we've sorted out the scrolling and the smooth scroll, it's time for the sprite positions.

		ldx #$00
		ldy sineposx
setsprx		lda sine_curve,y
		sta $d000,x
		tya
		clc
		adc #$20
		tay
		inx
		inx
		cpx #$10
		bne setsprx

Right, this is a fairly normal copy loop (as we've done before) but with an unusual twist. Before I explain how it works, I'll just quickly explain sine and cosine curves a bit more, which are used when demo programmers want to make things swing back and forth. At $0E00 and $0F00 are two tables of data, each 256 ($100) bytes long. If you were to examine the data you'd find that it contains the co-ordinates for a sprite, starting from the right hand side of the area it covers, accelerating towards the middle and decelerating at the left hand side of the area, then moving back in the same way.

The above loop reads the curve at $0E00 using the Y (which contains another counter) and puts it into $D000. It then adds a value of $20 to the Y, increments X twice (so that it only writes to the sprite X values, $D000, $D002 and so on) and then, if it hasn't reached $10 and therefore done all eight sprites goes back. Why do we add $20? Well, it's to make all six sprites read from different points on the curve to produce that swirling effect. Try changing that value to $00 and they all appear with the same X position.

		ldx #$00
		ldy sineposy
setspry		lda sine_curve_2,y
		sta $d001,x
		tya
		clc
		adc #$1c
		tay
		inx
		inx
		cpx #$10
		bne setspry

This is basically the same loop as we've just looked at, except that we are using sineposy, reading from $0F00 (the vertical sine table, slightly different to the horizontal one) and writing the values to $D001, $D003 and so forth for the vertical sprite positions. The ADC #$1C is different to the previous loop merely to make the curves a bit more interesting. It can quite happily be $20 or indeed any other value, so why not try playing with it and its fellow to see what you can do?

		lda sineposx
		sec
		sbc #$03
		sta sineposx

		lda sineposy
		sec
		sbc #$02
		sta sineposy

Okay, this just moves the counters around for the sprite movement. Again, the $03 and $02 can be altered to change how fast the sprites swing around, a value of $00 will cause them to stop dead and a value of $FF will make them go backwards on one axis slowly.

		jsr $1003
		jmp main

As explained last issue we are using an external music routine. Every frame we have to call the routine to keep the music playing and here's the JSR call for the tune we're using. And the JMP completes our loop, as we go back to main and wait for raster position $FC on the next frame.

		* = $2000
message		.scrl "welcome to the scrolling message!    "
		.scrl "this little demo-ette was coded for   "
		...

And to finish off this block of code, here's the previously mentioned label message and another new assembler directive to go with it. The .scrl command simply writes the text in quotes to the memory (at $2000, as specified by the * command above) in a format our routine can use, the letter A is represented as $01, B is $02 and so on. The text included in the source (of which only a part is reproduced here) is exactly 256 bytes long because the scroll routine can't handle any more or indeed less.

Right, all done and this time I don't have a challenge for you, just some "play" suggestions. The values in the two sprite setup loops ($20 and $1C) and the mover ($03 and $02) can be altered. Why not try putting different values in and seeing what happens to the sprites. Some interesting ones to try are replacing $20 with $82, which causes each sprite in turn to read its position from opposite ends of the curve, or replacing $03 and $02 with $04 and $05. Go on, have a play with the numbers and I'll see you next time with something new to look at! As always, contact me if you have any queries, comments or suggestions.

The source code for the routines above (they're the same as Hex Files 4) can be downloaded here for easier reference.

Content copyright © 2004-2014 Oldschool Gaming     Designed and hosted by Enisoc Design