Wednesday, 28 April 2021

Running on the smell of an oily rag

Working through the game start up and it's a bit of a grind to be honest. A fair bit of code had to be transcribed before anything interesting happened. But I now have the game starting and the player ship moving around. If you don't die from being hit or colliding with something, you'll run out of fuel.

Coin up, start a game and move around.

No shooting or bombing, but you can play through the 3 lives and it displays "GAME OVER" although I suspect the scroll offsets of the display area haven't been reset as they should be as it appears at a random offset from centre, and in the wrong colour. A quick search didn't reveal where that was but I'll find it.

As I work through the code I mark each routine as being one of UNIMPLEMENTED, WIP, LOOKS_OK, UNTESTED or COMPLETE via a printf that can be selectively enabled or disabled by category. Today added a whole swag of UNTESTED routines.

Unlike my earlier efforts, in this transcode I've started with the original disassembly, with every line denoted a C comment. Makes it much easier to keep functions in the same order as the ASM code, and keep track of addresses etc. Until a few days ago I was writing the new C function under the corresponding ASM function, but more recently I've moved the commented ASM inside the functions with the C code following each block of ASM code.

I've been removing the ASM code from the file whenever I deem a function to be COMPLETE (tested, debugged) but now I'm thinking that in my next transcode, I should actually keep the ASM code in there. It'll blow out the source file size of course, but does that really matter?

An example of what I mean...

// $10BA
void game_init (void)
  //10BA: 21 09 40    ld   hl,$4009              ; load HL with address of TEMP_COUNTER_4009  
  //10BD: 35          dec  (hl)
  //10BE: C0          ret  nz                    ; wait until counter reaches zero
  //10BF: 36 0A       ld   (hl),$0A              ; set TEMP_COUNTER_4009 to 10

  if (--wram.temp_counter_4009 != 0)
  wram.temp_counter_4009 = 10;

  //10C1: 2C          inc  l                     ; bump HL to point to SCRIPT_STAGE
  //10C2: 34          inc  (hl)                  ; advance to next stage of script (PLAY_GAME @ $22F4)
  //10C3: 3E 01       ld   a,$01
  //10C5: 32 19 40    ld   ($4019),a             ; set DRAW_LANDSCAPE_FLAG
  wram.draw_landscape_flag = 1;
  //10C8: 21 01 00    ld   hl,$0001
  //10CB: 22 80 43    ld   ($4380),hl            ; set PLAYERS[0].IsActive and reset PLAYERS[0].IsExploding flags
  //10CE: 22 A0 43    ld   ($43A0),hl            ; set PLAYERS[1].IsActive and reset PLAYERS[1].IsExploding flags
  wram.players[0].is_active = 1;
  wram.players[0].is_exploding = 0;
  wram.players[1].is_active = 1;
  wram.players[1].is_exploding = 0;
  //10D1: AF          xor  a
  //10D2: 32 82 43    ld   ($4382),a             ; reset PLAYERS[0].StageOfLife (see PLAYER_INIT @ $16FE)
  wram.players[0].stage_of_life = 0;
  //; player starting level, update lives remaining 
  //10D5: 21 08 41    ld   hl,$4108              ; load HL with address of CURRENT_PLAYER_LIVES
  //10D8: 35          dec  (hl)                  ; reduce number of lives
  //10D9: 11 03 07    ld   de,$0703              ; Command ID: 7 = HEAD_UP_DISPLAY_COMMAND, Param:3 = DISPLAY_CURRENT_PLAYER_LIVES
  //10DC: FF          rst  $38                   ; call QUEUE_COMMAND
  rst38_queue_command (7, 3);           // HEAD_UP_DISPLAY_COMMAND, CURRENT_PLAYER_LIVES

There is one bug that I haven't even looked for that revealed itself after I got the full demo lifecycle coded; when the player is killed and the next life starts, random strips of the landscape are missing. Given the nature of the bug and the data structures in the game, I suspect it's an area of memory being corrupted... hopefully it won't elude me for too long when I finally go looking for it.

There's probably another day or two (at least) working through the game lifecycle mechanics before I get onto the shooting and bombing.

No comments:

Post a comment