Re-hacking the 80’s- part 4

<read previous part

Unbugging the past

In this part I’m going to describe how I removed a ‘feature’ of the game that I consider to be a bug.

Backup material

But first: Maybe you imaginary readers would like to have the disassembled source I use, so I uploaded the currenty version. I still add comments to it when I find out stuff, so there will be newer versions later (1).

Code

Bug or not?

In the game there is a finite number of swords. Some are just lying around, and some can be retrieved after being thrown by enemies. But once a thrown sword is picked up, that enemy will never throw another sword.

sword1
The samurai has thrown his sword (the grey thing on the right).

And a sword thrown at an enemy will be spent as well.
So you’d better make good use of that sword. That is part of the challenge of the game: you really have to think about when you use your sword on what.

But you could be carrying a sword and then die by walking to another screen you’ve never been to and be immediately killed by an enemy.
You will not only loose a life but also that sword, probably making the game impossible to finish (I erroneously stated that you would lose a sword when killed by a bridge giant, but that’s not true).

sword2
Picked up the sword, all’s well.
sword3
Oh, no! Killed by the samurai, the sword is gone now!

 

 

 

 

 

 

I think that’s unfair so I will try to fix that. Furthermore I think I will not add it to the game as an optional trainer option but always incorporate that in the game.

Side note

I wondered how much code this game has. I stripped all data and comments from my disassemled document and ended up with less than 2000 lines of code.
Considering how little one line of assembly code can do (for instance, ‘add 1 to x register’) that’s not much!

More detectoring

The Arcade Joystick

Now I have to find the piece of code responsible for handling the acquiring and losing of a sword.
You get a sword by walking over one. That happens when the sprites of the player and the sprite of a sword collide.
The Commodore 64 has a memory location that detects sprite collisions: $D01E (to be more accurate: the video chip detects sprite collisions and updates $D01E accordingly). In the first episode I’ve shown a small part where that memory is read to detect a collision of the player with a giant’s arm. But that part only codes for collision with the giants’ arms. So where else is collision detected? Sadly that is the only part where $D01E is read, so collision detection works differently for picking up swords.
So what now? By now I have a pretty good understanding of the code, so I know where collision detection takes place in the code, but there is is a different way to solve the puzzle: if you press the joystick button AND you have a sword then a sword is thrown.


Finding the code for that is not that hard. The joystick states can be read from memory $DC00 and $DC01 (joystick port 2 resp. 1). I know which port is used so I can search with VICE for the byte sequence 8D 00 DC (LDA $DC00, it could also be LDX or LDY, but that’s less likely)(2).

You get a few hits but one looks promising. Here is the exerpt of the code (you can see some auto-commented code but also some code I added when figuring out how it works).

Two earlier discoveries help me here (3):

  • the 8 sprites of the C64 all have its own role in this program, you can turn sprites on and off and see this pattern emerging:
sprite# 0 1 2 3 4 5 6 7
player bridge-left samurai &
left giant
middle giant bridge-right
& right giant
not used enemy sword sword & key& treasure
  • $0DA0 is the address of a subroutine that turns sprites on (the X register is the number of the sprite to turn on, numbered from 1-8).
    $0DAA does the same, except that it turns that sprite off
L9C00 LDY  $49      ; 
      BNE L9C57     ; 
      LDA  $8E      ; bit 7 set in $8E: has sword
      BPL L9C56     ; 
      LDA  LDC00    ; Data Port A (Keyboard, Joystick, Paddles,  Light-Pen)   7-0 Write Keyboard Column Values for Keyboard  Scan 7-6-2006 Read Paddles on Port A / B (01 = Port A,  10 = Port B) 4 Joystick A Fire Button: 1 = Fire 3-2-2006 Paddle Fire Buttons 3-0 Joystick A Direction (0-15)    MOS 6526 Complex Interface Adapter (CIA) #2
      AND  #$10      ; FIRE button bit. Is zero if pressed!
      BEQ L9C15     ; 
[code that checks keyboard is left out here, the game can be controlled by keyboard and joystick]
L9C15 LDX  L01      ; copy player pos to sword pos
L9C17 LDA  LD000,X  ; Sprite 0 X Pos  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
      STA  LD00A,X  ; Sprite 5 X Pos  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
      DEX           ; 
      BPL L9C17     ; 
      LDY  L4343    ; 4343 = player direction?
      STY  L9C8C    ; 
      LDA  L40A8,Y  ; 
      STA  spr6point    ; set sprite pointer depending on player direction
      LDX  L40A4,Y  ; 
      STX  $4B      ; sword direction?
      LDA  L40A0,Y  ; some more table reading
      CLC           ; and adding that to the sprite position based on that table
      ADC  LD00A,X  ; Sprite 5 X Pos  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
      STA  LD00A,X  ; Sprite 5 X Pos  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
      LDA  #$0F      ; set color of the sprite
      STA  LD02C    ; Sprite 5 Color  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
      LDA  #$60      ; not sure what this does, yet
      STA  $49      ; 
      LDX  #$05      ; position sprite 5
      JSR  L0DA0    ; 
      LDA  #$00      ; set 0 in three memory locations
      STA  $8E      ; set to not carrying sword
      STA  L4371    ; 
      STA  L436F    ; 
[....]

On a side note: I think there is a bug at ‘adc ld00a,x’. That part places the sword sprite in an offset from the sprite position. But X is always 1 at that point of the code, so indexed addressing is useless here. It could be replaced by ‘adc ld00b’. Now only D00B (Y position of sprite) is changedI think it was meant to be in the loop so the X position would also be changed.

The end of the code here is interesting: 3 memory locations are set to zero. Maybe one of them means ‘not carrying  sword’?
I can see $8E is also read in the beginning of the subroutine. It determines if the joystick button is read at all.
So it probably it determines if the player has a sword or not.

We can test it by changing that value live with VICE. It would mean the player could throw a sword again:
2017-03-06 (3)

Does it work?

2017-03-06 (5)
Visually no change: no sword in hand
2017-03-06 (6)
but clicking the button does throw a sword!

So I know what to change. I also found out that address $4371 is as a sword-indicator but only for the visual part. Putting value #$10 in it, makes sure the player walks holding a sword.

If you start to look for parts where both are reset (which typically happens when you die or start a new game), you find a few regions, but the region starting at $9443 seems to be the right part.

	   ; handle death?
L9443 LDA  #$12      ; only sprites 1 and 5 are multicolour, the brige parts
      STA  LD01C    ; Sprites 0-7 Multi-Color Mode Select:  1 = M.C.M.  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
      LDA  #$00      ; 
      STA  LD017    ; Sprites 0-7 Expand 2x Vertical (Y)  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
>>      STA  L4371    ; 0 = sprite carrying no sword (only visual)
      LDA  #$38      ; start position
      STA  $L5F      ; screen number
      LDX  #$01      ; 
      STX  $D015    ; Sprite display Enable: 1 = Enable  MOS 6566 VIDEO INTERFACE CONTROLLER (VIC)
L9476 LDA  #$00      ; 
      STA  $60      ; 
      STA  $61      ; 
      STA  $49      ; 
>> L947E STA  $8E      ; $8E, value #$80 means, carrying sword
      LDY  #$63      ; 
      STY  spr0point    ; 
      LDA  #$02      ; 
      STA  $3F      ; 
      JMP  L9936    ; goto Main Loop

So I have the way to ‘bugfix’ the game. It will be incorporated in the trained version.

Finally

I’d like to end with an animation of a feature I’m working on: the map. I succeeded in generating a map of the game and the objects when the game starts. You can toggle the map. It’s not finished yet, but almost there (I’ll change the colors I promise!).

willow

(1): I made my disassembler program before I used version control software. The newest file I used turned out to have several bugs, that don’t bother me, but make it less readable: you can’t tell the difference between zero page addressing ($xx) and numbers (#$xx).

(2): The A register can be used to for arithmetic (adding subtracting) and bit manipulation which is useful if want to know stuff about the joystick. Bit 5 for instance is the fire button, so AND #$10 sets the zero bit in the status register if bit 5 is not set in the A register.

(3): knowledge of the C64 is necessary  to understand what’s happening. Here: knowing $D015 turns sprites on where each bit codes for a sprite.

1 Comment

  1. Re-hacking the 80’s-part 5: training run | Goerp

    […] Re-hacking the 80’s- part 4<< […]

Leave A Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.