new stuff to test so here again some quick b&w cartoons
ps: no voting possible only likes
I found a Tomb Raider fountain pen in the attic (no idea where I got it) and some ink cartridges, so I wanted to try it out. The ink in the cartridges is water soluble unfortunately, so the colouring and lines all become one big smudge, but I like that. I’m never going to make very neat cartoons so I’d better make that messiness a trademark.
Almost completely (except for the lettering) hand drawn. Trying some brush pens with ecoline and other water based ink. Lines done with ballpoint.
For a change of pace I decided to use a few of my trainers (and my new map feature) to try and finish this game for once (never reached the end before!).
At first I implemented the ‘never lose your sword’, ‘giant invulnerability’ and ‘endless lives’ trainer options.
Regrettably I played without making any screenshots until the last, so there wont be many pictures.
OK, I knew the game was hard, but I didn’t exactly know just how hard. With just 5 lives, you have to navigate a maze, make no mistakes in the use of swords, don’t make too many mistakes with wrong turns (where you get a insta-kill), make not too many mistakes with the giants and do some pixel perfect movement to kill the samurai.
I think there are some points where there are samurai you can’t realistically kill. And even with all these trainers it takes a lot of time to come to the place where the princess is.
The game manual tells you that after you have saved the princess you have to get her back to the escape boat while being chased by Li Chi, the angry father.
And boy is he angry! Even with a walking cane he’s very fast. Every screen after finding the princess you have about a second before the father enters the scene and starts chasing you. And you’d better not make a mistake turning a corner because, he’ll be on you right away.
And making a mistake turning a corner isn’t as unlikely as it sounds, because the collision with the environment is not based on visual information, but based on location on an invisible tile system. On the picture you see a tree on the bottom right of the player, that looks to have some free space in its upper left corner. But that’s not passable, because it is part of the tree’s tile.
And so you may have been perfect in the game up to meeting the princess but then you have to navigate the maze and evade the father with just 5 lives. And going into a dead end means another life gone.
In practice for me it would be impossible.
I ended up finding and implementing another trainer option, where the father can’t kill you (quite similar to the trainer option of invulnerability to samurai which I already found, so not hard to do).
In total I think I spent about 15-20 minutes including making the extra trainer option to get to this point:
You can see the father in red below and me and the princess in yellow next to the boat (the sprites overlap so they’re hard to distinguish).
Also you can see I have a score of 103%. I think that’s because I killed three samurai the makers didn’t think I would be able to kill.
Playing this way gave me three ideas I would like to add to the game:
- Trainer option to be invulnerable to the father
- The map should update changes, like removing picked up swords and killed samurai
- Having an indicator which way is the right exit to the boat after reaching the princess.
The first one is done, but the other two need some work. But first get the map done properly.
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.
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).
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.
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).
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.
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!
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:
& 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:
Does it work?
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.
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!).
(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.