Monday, September 24, 2007

Tweaking

Too little time for anything major (yet!) but scoring and subgame have seen some little changes.


  • Bonus score if you do well in subgame. 20% bonus for each remaining pulser if you win 11-1, 40% if you win 12-0

  • 2000 point bonus if you're wimp and use only transfer to overtake the ship. Not enough to compensate for score lost by not shooting droids, as I don't want to encourage that kind of cowardism ;)

  • Shoot droids to pieces before transferring to them - their pulser count reduces by one for every 16 points of damage. Don't forget that you have to cope with whatever energy they have left, though!



In addition to adding small things I've also discarded some ideas

  • Grenades/mines. What to do when droid explodes a mine but there are no free sprites?

  • Two player mode through link cable. That cuts down sprites available for enemy droids and fire, lowering the difficulty considerably. With fever sprites it's also harder to hide the fact that the game teleports droids away if it runs out sprites.


I have doubts about transport pads as well. These would transfer player within a deck, but that would require resetting droid positions to avoid several visibility problems. And that would mean teleporting all droids, meaning you could face the same robot you were running away just a second or two ago half a deck away. You may say that there isn't much realism in the game, but that makes it even more important to preserve what's left of it!

Wednesday, September 5, 2007

Wasting time

How can one waste gazillions of cycles to mirror one sprite? Quite easily, just forget speed and concentrate on compact code.



MirrorSprite
 
ldy #0
sty src
sty .5+1
 
; src = A<<6 | $4000
 
sec
ror
ror src
lsr
ror src
sta src+1
 
; ptr = X<<6 | $4000
 
txa
sec
ror
ror .5+1
lsr
ror .5+1
sta .5+2
 
; get sprite multicolor flag
 
ldy #$3F
lda (src),y
sta tmp2 ; b7=1 if multicolor
 
lda #60
 
.1 tax ; x=60,61,62, 57,58,59, ... 3,4,5, 0,1,2
 
lda #3
sta bytesLeft
 
.2 dey ; y=62,61,60, 59,58,57, ... 5,4,3, 2,1,0
lda (src),y
sta tmp1
lda #$01
.3 lsr tmp1 ; 5
bit tmp2 ; 8
bpl .4 ;10 hires, 8 loops 1 bit each
 
php ;13 else multicolor, 4 loops 2 bits each
lsr tmp1 ;18
rol ;20
plp ;24
.4 rol ;26
bcc .3 ;29 8*16=128 / 4*29=116
.5 sta $8000,x ; 63*128=8064
 
inx
dec bytesLeft
bne .2
 
txa
; sec ; asserted with "bcc .3"
sbc #6
bpl .1
 
rts
 


Hey, I just realized I can make it at least one byte sorter! ;)

Update: cycle counts were way off...

Tuesday, September 4, 2007

Byte Liberation Front

I keep surprising myself with all the memory I can squeeze out when I start trying. When reordering the multicolor charset from the Metal Edition Paradroid I finally took a good peek at the alpha charset. Eliminating duplicate chars and blanks freed another 31*8 bytes and couple more in graphics font. There are several 8-byte data areas I can scatter anywhere in the memory, but to keep it neater I should do some rearranging. Finding the correct data block in binary file whenever I want to change something doesn't sound fun to me.

In case you're wondering about those five blank chars below "8" - "c" and why they aren't used... Chars $28-$2c (top halves of those 1*2 characters) are at offset $0140 and need 40 bytes. (Not so) interestingly that's the same offset and size as 10th character line on screen, which is the first line used for the deck display. To change all sprite pointers and displayed charset with single $d018 write I simply switch from blank screen + blank font to actual game screen and graphics at the correct line. However, VIC-II has already read the character pointers at that time (from blank screen) which means that I have to copy the top line from game screen into the blank screen. That in turn makes chars $28-$2c visible if used because the blank screen is actually the first half of the blank font... So, those chars are unusable as graphic data both in alpha font and in in-game graphics font. That however doesn't mean that they can't be used for anything else ;)



From graphics to sound effects... I found out that I can move the main SFX table partially into the RAM under I/O at a cost of ten cycles every time an effect is started. This filled up the hard-to-use $D000 RAM completely, and freed 160+ bytes elsewhere.



Back to graphics with something which is only an idea so far. Compressing droid parts separately would gain ~600 bytes, but I can do even better. If sprites are decompressed into one continuous block, I can use the previous sprite data as codebook which would give better compression at no extra cost. Extra time used for decompression isn't anything to worry about, no one has complained about the sprite mirroring delay yet and that one takes about 15,000 cycles per sprite, 60,000 cycles in total - even if mirrored sprites aren't used at all!



All these summed up give me more than one kilobyte to play with - but what should I fill it with?

Sunday, August 26, 2007

Lies, damned lies, and statistics

I needed something to use when deciding which tables benefit most from move to zero page, so I counted words and their occurences in all source files. In addition to giving me the info I wanted, it revealed something else.



Paradroid Redux Top 30 ML Instructions


1549 lda 202 adc 119 bmi
1362 sta 175 lsr 108 iny
679 jsr 167 bcc 106 clc
394 ldx 163 stx 100 sbc
380 ldy 151 bpl 85 dec
313 bne 144 asl 84 eor
251 rts 133 bcs 83 ora
245 beq 131 inc 82 bit
219 cmp 130 sty 81 sec
210 and 124 jmp 76 dex



Disclaimer: Above counts include some code which is commented out, and I didn't expand all macros either.

Saturday, August 25, 2007

Zero page roundup

I finally took the time to change all zero page variable declarations from

var = $02
to
var ds.b 1
and removed all variables which aren't used any more. I suspected I would end up with 30 to 40 free zero page locations, but it turned out to be about 70 bytes! I swiftly used half of it for the two most used object variable tables (16 bytes each), which makes accessing them both faster and smaller. I guess those tables really are accessed a lot, code size was reduced by over 100 bytes... I still have room for another two tables there, but I have to find the ones which gain most cycles/bytes.



Complete list of bug fixes since the previous release:


  • Droid teleportation doesn't send them outside the deck any more.

  • Waypoint chars are placed onto deck map every time when exiting lift, meaning no more completely confuzed droid army.

  • Door status is restored when exiting lift, so droids won't get stuck against them any more.

  • The first deck entered after load had waypoint magic chars visible, as they aren't hidden in EnterShip() routine but in EnterDeck(). Instead of wasting three bytes to add one JSR call, I changed the font so magic chars are there after load :)

  • Background stars are now really disabled during the intro sequence, that avoids random colors for lower half of "7" char. I disabled them earlier, but that broke when I added more run-time randomizing.



Important bits here.



Update


Two more bugs fixed, one remains... Intro text scrolled beyond the end of page sometimes, and out-of-sight droids were paralyzed on C128. The remaining bug allows droid go through wall in certain conditions, something which I didn't notice on emulator.

Friday, August 24, 2007

Squish 'em

Two bugs found and fixed, both of them having the same root cause. Whenever you change deck in lift, it's built immediately, even if you don't actually enter that deck. This avoids a delay when you exit the lift. However, if you then decide to go back to the deck where you entered lift after, game keeps previous droid/deck status intact but deck map is reset to the default state.

Now, the two bugs:


  1. All waypoints are now marked with magic chars for faster detection, and I didn't restore them when re-entering deck. Mea culpa. Now waypoints are decompressed/marked correctly evrey time. This means that some work is done twice when entering a new deck, but it's fast enough to be unnoticeable.

  2. Doors keep their state on re-entry, but deck map has all doors closed after decompression. If droid had opened a door when you caused level build in the lift, droid got stuck against/in the middle of a door which was visually closed, but logically open. This bug was there from the beginning. I added some code to restore door visual state when entering a deck, and it seems to work. Doing this with minimum amount of new code made door code resemble spaghetti tho.



New beta out during this weekend, with almost all known bugs fixed. Well, make that all known bugs fixed if I have time for it :)

Sunday, August 19, 2007

Another week gone by

And so time passed by with nothing extraordinarily great done...



I found a bug in the latest beta - it teleports droids to the great unknown because I didn't adjust the teleport routine when I changed the waypoint system. Fixing that didn't take long, but with the released beta you need to enter another deck and come back to get droids back. Just visiting a lift doesn't work.



Multicolor is almost working. Almost, but not quite. I really should have done multicolor changes too when I changed the hires font...



I saved 70 bytes in the background star drawing by combining the top and bottom routine, it's not time critical so I could shrink the code without worrying about the speed. Adding random stars and blinking took most of the freed space, but I guess I can accept that.



I've used some of the new droid-specific data in old routines, speeding them up slightly as well as making them smaller. Inserting new droid AI makes every droid take slightly longer time to run, so I need every cycle I can get. I want to make big bad droids get irritated by the smaller ones when alarm is high if possible. I can already see 834 bumping into 329, shooting it out of the way and then rushing into the explosion. :)



One thing to consider is to make two passes through the droids when running them, handling visible ones in the first round and the remaining ones in the second. That way I could exit early if it looks like I'm running out of time. Sorting out-of-view droids by their distance would make it work even better, but sorting takes time...