Trap issue with BTII on c64

Any developer realated stuff
User avatar
Saxon1974
Posts: 87
Joined: Thu Mar 27, 2008 3:52 am

Post by Saxon1974 »

My vague memories of playing this game back when it was new was that traps did not work, but then again that was like 1986 and I was 12 years old or so, so I could be wrong.

If anyone can get into the code and if its an easy fix that would be fantastic.

Kind of tarnishes this version for me oh well.
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

I have made a zip with decoated D64 images, i.e. with the files visible. They are still (supposed) xor'ed by $EA. But files could be de-xored and then the TRAP event be found (should be very similar to the one from BT1 where it is within file NM1D). In there should be a call to the damage routine, if you dissassemble that routine, you likely find the bug.
Can mail you that zip.
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

Ok, I have decompiled both TRAP events for BT 1 and for BT 2. They look almost identically. Only the trap texts differ and there is a very tiny passage in BT 2 that slightly differs, however I *think* the basic functionality is the same. If the damage subroutine itself were buggy, then no damage at all would work.
Anyway I will check, if the damage routines are similar and post results here.

E D I T
Both damage routines work alike. Then my only explanation for this is, that probably the routine for the saving roll might always return a "saved" for traps. No time to check that either, sorry.
User avatar
Saxon1974
Posts: 87
Joined: Thu Mar 27, 2008 3:52 am

Post by Saxon1974 »

Ok well thank you for trying ZeroZero, much appreciated.

Maybe someone else with knowledge of C64 game and file structures will take it up and check out the "Save" routine.

I have done some programming in my life, but none with C64 so pretty clueless about it.

EDIT: One additional thought. The TRAP routine when fired from opening a treasure chest works normally so I wonder if comparing that with the regular trap routine you hit when walking would be something to look at? I would think they should be very similar.
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

Hi Saxon,

TRAPS in BT 1 and BT 2 are in an event file and defined as a special on that map cell. TRAPS on chests are different, I am talking about TRAPS in map cells. So WHAT traps do fail in BT2? I was investigating the map cell traps, i.e. the traps while walking...

Another note: while in BT 1 all game files are visible and also unencoded, it is easy to locate and disassemble the events. In BT 2 the files are hidden and encoded, so it is somewhat harder to do that. However I decoated the BT 2 disks, so that the files are still visible. Those disks continue to be playable unless you also decode them. To disassemble the files, they must be decoded (simple XOR with value $EA (a -ha!), ty to Twoflower for pointing this out). I did that for the TRAPS event, that is the event in the BT1 file NM1D on the dungeon disk. A similar file is on the BT 2 dungeon disks (both, idntical) of size of 609 bytes.

There also is a CHEST event (including traps), which in BT 1 is located in file NM1C. There likely is a similar file in BT 2.

So, did I lookup the wrong event, did you mean chest traps rather than map traps?

Anyway, the regular traps work in a way, that obviously a safe roll is tested, and if the result is FAIL, some damage will be put into memory cell $45 and a subroutine called to apply that damage to the character that is pointed to in memory cell $44. This is same in BT 1 and BT 2. So the only explanation I have left is, that in BT 2 for some reason this safe roll always returns SAFE instead of FAIL, so that NEVER any damage is applied...

It is to be checked, if this safe roll routine is used elsewhere, if yes, then this would mean, that the safe roll always is SAFE. If the damage routine itself failed, NO DAMAGE at all would ever be effected on any character, so that is NOT the reason.
User avatar
Twoflower
Posts: 128
Joined: Thu Mar 19, 2009 12:40 am
Location: Haarlem, NL
Contact:

Post by Twoflower »

ZeroZero wrote:It is to be checked, if this safe roll routine is used elsewhere, if yes, then this would mean, that the safe roll always is SAFE. If the damage routine itself failed, NO DAMAGE at all would ever be effected on any character, so that is NOT the reason.
Doh. Ofcourse it is like you describe it above - as usual I didn't think that far while posting. I still believe that either the call for the "safe roll" is performed incorrectly, or that the variable which determines the safe roll is set to a safe value by thoughtless coding. The variable might be stored in a dedicated adress / zeropage or it might simply be a temporal value stored in either of the A, X or Y accumulators.

But perhaps we should locate the problem-file to start with? :-)
/Twoflower
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

@ Twoflower

Contact me on ICQ, I send you both assembler files, for BT 1 and BT 2 trap event. With a freezer module you then could easily get into the routines to debug. I also can explain to you, what I think is the routines in question.
User avatar
Saxon1974
Posts: 87
Joined: Thu Mar 27, 2008 3:52 am

Post by Saxon1974 »

ZeroZero wrote:Hi Saxon,

TRAPS in BT 1 and BT 2 are in an event file and defined as a special on that map cell. TRAPS on chests are different, I am talking about TRAPS in map cells. So WHAT traps do fail in BT2? I was investigating the map cell traps, i.e. the traps while walking...

Another note: while in BT 1 all game files are visible and also unencoded, it is easy to locate and disassemble the events. In BT 2 the files are hidden and encoded, so it is somewhat harder to do that. However I decoated the BT 2 disks, so that the files are still visible. Those disks continue to be playable unless you also decode them. To disassemble the files, they must be decoded (simple XOR with value $EA (a -ha!), ty to Twoflower for pointing this out). I did that for the TRAPS event, that is the event in the BT1 file NM1D on the dungeon disk. A similar file is on the BT 2 dungeon disks (both, idntical) of size of 609 bytes.

There also is a CHEST event (including traps), which in BT 1 is located in file NM1C. There likely is a similar file in BT 2.

So, did I lookup the wrong event, did you mean chest traps rather than map traps?

Anyway, the regular traps work in a way, that obviously a safe roll is tested, and if the result is FAIL, some damage will be put into memory cell $45 and a subroutine called to apply that damage to the character that is pointed to in memory cell $44. This is same in BT 1 and BT 2. So the only explanation I have left is, that in BT 2 for some reason this safe roll always returns SAFE instead of FAIL, so that NEVER any damage is applied...

It is to be checked, if this safe roll routine is used elsewhere, if yes, then this would mean, that the safe roll always is SAFE. If the damage routine itself failed, NO DAMAGE at all would ever be effected on any character, so that is NOT the reason.
No your checking the correct thing (The trap event on the map cell you hit when walking). The chest trap events work and apply damage\effects as they should, it's just the walking cell maps that don't work at all.

I was merely guessing that the same routine to apply damage might be called when triggering a trap from a chest as opposed to walking? I could be wrong but once you trigger a trap from opening a chest the resulting type of trap and damage looks like the same routine that occurs when you hit a walking trap, so I was guessing it works the same and maybe comparing the two would help discover what's wrong with the walking map cell traps.

Sounds like your saying the code called on a trap triggered from a chest is different from when its hit walking around the map.
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

@ Saxon

No, in contrary:
I doubted that the reason for the problem is the damage routine itself, because the same damage routine is called for any kind of damage. Instead I am suspecting the routine, that does a "safe roll" to avoid damage from a trap per character. If that one works wrong and always says, that that character succeeded his safe roll, then never any damage would be applied. And that I haven't checked yet.

And yes, the code for chests and map traps is different, that are two different special events encoded for BT 1 in files NM1C and NM1D. Similar files exist for BT 2, but they are cloaked and encoded. I only decloaked and decoded the file or the map traps (a file of 609 bytes size).

BT 2 traps event:

Code: Select all

                       *        =   $a200 ;  C64 

a200:0002:1   20 e1 08          jsr $08e1
a203:0005:1   20 90 08          jsr $0890
a206:0008:1   a5 5b             lda $5b
a208:000a:1   29 07             and #$07
a20a:000c:1   85 f7             sta $f7
a20c:000e:1   a0 a3             ldy #$a3
a20e:0010:1   a2 52             ldx #$52
a210:0012:1   20 06 08          jsr $0806
a213:0015:1   a5 f7             lda $f7
a215:0017:1   0a                asl a
a216:0018:1   aa                tax 
a217:0019:1   bc 67 a3          ldy $a367,x
a21a:001c:1   bd 66 a3          lda $a366,x
a21d:001f:1   aa                tax 
a21e:0020:1   20 06 08          jsr $0806
a221:0023:1   e6 1d             inc $1d
a223:0025:1   a9 08             lda #$08
a225:0027:1   20 1a 09          jsr $091a
a228:002a:1   a9 28             lda #$28
a22a:002c:1   85 1f             sta $1f
a22c:002e:1   a9 03             lda #$03
a22e:0030:1   85 20             sta $20
a230:0032:1   20 96 08          jsr $0896
a233:0035:1   a6 f7             ldx $f7
a235:0037:1   a4 42             ldy $42
a237:0039:1   a9 00             lda #$00
a239:003b:1   18                clc 
a23a:003c:1   7d 4a a3          adc $a34a,x
a23d:003f:1   88                dey 
a23e:0040:1   10 f9             bpl $a239
a240:0042:1   aa                tax 
a241:0043:1   a9 00             lda #$00
a243:0045:1   85 69             sta $69
a245:0047:1   85 6a             sta $6a
a247:0049:1   e0 00             cpx #$00
a249:004b:1   f0 16             beq $a261
a24b:004d:1   20 90 08          jsr $0890
a24e:0050:1   a5 5a             lda $5a
a250:0052:1   29 03             and #$03
a252:0054:1   18                clc 
a253:0055:1   69 01             adc #$01
a255:0057:1   18                clc 
a256:0058:1   65 69             adc $69
a258:005a:1   85 69             sta $69
a25a:005c:1   90 02             bcc $a25e
a25c:005e:1   e6 6a             inc $6a
a25e:0060:1   ca                dex 
a25f:0061:1   d0 ea             bne $a24b
a261:0063:1   a9 00             lda #$00
a263:0065:1   85 44             sta $44
a265:0067:1   a6 f7             ldx $f7
a267:0069:1   bd 42 a3          lda $a342,x
a26a:006c:1   d0 05             bne $a271
a26c:006e:1   20 cc a2          jsr $a2cc
a26f:0071:1   85 44             sta $44
a271:0073:1   a6 f7             ldx $f7               <= start of applying damage to 1 char
a273:0075:1   bd 3a a3          lda $a33a,x
a276:0078:1   85 c8             sta $c8
a278:007a:1   a9 80             lda #$80
a27a:007c:1   85 d0             sta $d0
a27c:007e:1   a5 69             lda $69
a27e:0080:1   85 45             sta $45              <= cell to store damage
a280:0082:1   a5 6a             lda $6a
a282:0084:1   85 46             sta $46
a284:0086:1   a5 42             lda $42
a286:0088:1   0a                asl a
a287:0089:1   0a                asl a
a288:008a:1   0a                asl a
a289:008b:1   0a                asl a
a28a:008c:1   18                clc 
a28b:008d:1   69 07             adc #$07
a28d:008f:1   48                pha 
a28e:0090:1   ad 55 a4          lda $a455
a291:0093:1   85 67             sta $67
a293:0095:1   ad 56 a4          lda $a456
a296:0098:1   85 68             sta $68
a298:009a:1   a0 1d             ldy #$1d
a29a:009c:1   68                pla 
a29b:009d:1   91 67             sta ($67),y
a29d:009f:1   20 d5 08          jsr $08d5
a2a0:00a2:1   b0 13             bcs $a2b5
a2a2:00a4:1   c9 00             cmp #$00
a2a4:00a6:1   f0 07             beq $a2ad
a2a6:00a8:1   46 46             lsr $46
a2a8:00aa:1   66 45             ror $45
a2aa:00ac:1   4c b5 a2          jmp $a2b5
a2ad:00af:1   a9 00             lda #$00
a2af:00b1:1   85 45             sta $45
a2b1:00b3:1   85 46             sta $46
a2b3:00b5:1   85 c8             sta $c8
a2b5:00b7:1   a5 44             lda $44
a2b7:00b9:1   20 03 90          jsr $9003     <= apply damage subroutine
a2ba:00bc:1   a6 f7             ldx $f7
a2bc:00be:1   bd 42 a3          lda $a342,x
a2bf:00c1:1   f0 08             beq $a2c9
a2c1:00c3:1   e6 44             inc $44
a2c3:00c5:1   a5 44             lda $44
a2c5:00c7:1   c9 07             cmp #$07        <= for all 6 party members (why not 7 in BT 2?)
a2c7:00c9:1   90 a8             bcc $a271
a2c9:00cb:1   4c 48 08          jmp $0848
a2cc:00ce:1   a9 07             lda #$07
a2ce:00d0:1   85 3b             sta $3b
a2d0:00d2:1   20 90 08          jsr $0890
a2d3:00d5:1   a5 5a             lda $5a
a2d5:00d7:1   29 03             and #$03
a2d7:00d9:1   aa                tax 
a2d8:00da:1   e0 07             cpx #$07
a2da:00dc:1   f0 3c             beq $a318
a2dc:00de:1   8a                txa 
a2dd:00df:1   0a                asl a
a2de:00e0:1   a8                tay 
a2df:00e1:1   b9 2c a3          lda $a32c,y
a2e2:00e4:1   85 50             sta $50
a2e4:00e6:1   b9 2d a3          lda $a32d,y
a2e7:00e9:1   85 51             sta $51
a2e9:00eb:1   a0 00             ldy #$00
a2eb:00ed:1   b1 50             lda ($50),y
a2ed:00ef:1   f0 29             beq $a318
a2ef:00f1:1   a0 38             ldy #$38
a2f1:00f3:1   b1 50             lda ($50),y
a2f3:00f5:1   c9 0b             cmp #$0b
a2f5:00f7:1   90 0e             bcc $a305
a2f7:00f9:1   a0 4e             ldy #$4e
a2f9:00fb:1   b1 50             lda ($50),y
a2fb:00fd:1   d0 1b             bne $a318
a2fd:00ff:1   a0 38             ldy #$38
a2ff:0101:1   b1 50             lda ($50),y
a301:0103:1   c9 0c             cmp #$0c
a303:0105:1   f0 13             beq $a318
a305:0107:1   a0 3e             ldy #$3e
a307:0109:1   b1 50             lda ($50),y
a309:010b:1   c9 03             cmp #$03
a30b:010d:1   90 04             bcc $a311
a30d:010f:1   c9 05             cmp #$05
a30f:0111:1   90 07             bcc $a318
a311:0113:1   a9 03             lda #$03
a313:0115:1   8d d6 a2          sta $a2d6
a316:0118:1   8a                txa 
a317:0119:1   60                rts 
a318:011a:1   e8                inx 
a319:011b:1   c6 3b             dec $3b
a31b:011d:1   f0 0c             beq $a329
a31d:011f:1   e0 04             cpx #$04
a31f:0121:1   f0 04             beq $a325
a321:0123:1   e0 07             cpx #$07
a323:0125:1   90 b7             bcc $a2dc
a325:0127:1   a2 00             ldx #$00
a327:0129:1   f0 b3             beq $a2dc
a329:012b:1   a9 01             lda #$01
a32b:012d:1   60                rts 

(followed by data cells and BT encoded text)
User avatar
Saxon1974
Posts: 87
Joined: Thu Mar 27, 2008 3:52 am

Post by Saxon1974 »

ZeroZero wrote:@ Saxon

No, in contrary:
I doubted that the reason for the problem is the damage routine itself, because the same damage routine is called for any kind of damage. Instead I am suspecting the routine, that does a "safe roll" to avoid damage from a trap per character. If that one works wrong and always says, that that character succeeded his safe roll, then never any damage would be applied. And that I haven't checked yet.

And yes, the code for chests and map traps is different, that are two different special events encoded for BT 1 in files NM1C and NM1D. Similar files exist for BT 2, but they are cloaked and encoded. I only decloaked and decoded the file or the map traps (a file of 609 bytes size).
ZeroZero,

Oh I gotcha.

I may not be helping here since I have not done any dev work on any C64 stuff but was just trying to throw out some ideas :)

Let me know if your going to do anything that I might be able help test if you would like.

Cheers
User avatar
Twoflower
Posts: 128
Joined: Thu Mar 19, 2009 12:40 am
Location: Haarlem, NL
Contact:

Post by Twoflower »

I bet one of these are the culprits:

Code: Select all

a29d:009f:1   20 d5 08          jsr $08d5
a2a0:00a2:1   b0 13             bcs $a2b5
a2a2:00a4:1   c9 00             cmp #$00
a2a4:00a6:1   f0 07             beq $a2ad
This subroutine at $08D5 probably nullifies damage or modifies the saving-roll. Can't be sure without testing it in the engine, but this should be a good start where to look.
/Twoflower
User avatar
Saxon1974
Posts: 87
Joined: Thu Mar 27, 2008 3:52 am

Post by Saxon1974 »

Twoflower wrote:I bet one of these are the culprits:

Code: Select all

a29d:009f:1   20 d5 08          jsr $08d5
a2a0:00a2:1   b0 13             bcs $a2b5
a2a2:00a4:1   c9 00             cmp #$00
a2a4:00a6:1   f0 07             beq $a2ad
This subroutine at $08D5 probably nullifies damage or modifies the saving-roll. Can't be sure without testing it in the engine, but this should be a good start where to look.
Interesting. Does this mean one of you might have a shot at figuring this stuff out? I have no idea how to help other than testing the game.

I return to these games every once in a while and sure hope one day this bug could get fixed in the C64 version of the game.
drifting
Posts: 153
Joined: Wed Dec 07, 2011 10:21 pm

Post by drifting »

Twoflower wrote:I bet one of these are the culprits:

Code: Select all

a29d:009f:1   20 d5 08          jsr $08d5
a2a0:00a2:1   b0 13             bcs $a2b5
a2a2:00a4:1   c9 00             cmp #$00
a2a4:00a6:1   f0 07             beq $a2ad
This subroutine at $08D5 probably nullifies damage or modifies the saving-roll. Can't be sure without testing it in the engine, but this should be a good start where to look.
$08D5 is a jump to $4CE5 which is almost certainly the culprit. Following the logic a bit further:

Code: Select all

a29d:009f:1   20 d5 08          jsr $08d5     ; RNG
a2a0:00a2:1   b0 13             bcs $a2b5     ; if carry bit set goto do_damage

a2a2:00a4:1   c9 00             cmp #$00      ; if A == 0
a2a4:00a6:1   f0 07             beq $a2ad     ;   goto nullify_damage
a2a6:00a8:1   46 46             lsr $46       ; else
a2a8:00aa:1   66 45             ror $45       ;   halve damage
a2aa:00ac:1   4c b5 a2          jmp $a2b5     ;   goto do_damage

nullify_damage:
a2ad:00af:1   a9 00             lda #$00
a2af:00b1:1   85 45             sta $45
a2b1:00b3:1   85 46             sta $46
a2b3:00b5:1   85 c8             sta $c8

do_damage:
a2b5:00b7:1   a5 44             lda $44 
It seems that $4CE5 is flawed in that the carry bit is not set and the accumulator is zero. Out of ~10 tests using AppleWin the carry bit has been cleared and A is 0 every time.
User avatar
ZeroZero
Posts: 286
Joined: Tue Mar 10, 2009 9:10 pm
Location: Germany

Post by ZeroZero »

Interesting....

Has this been tested with low level chars, hi level chars or both?

Hi level chars probably really pass the save roll every time, while
low levels shouldn't.
drifting
Posts: 153
Joined: Wed Dec 07, 2011 10:21 pm

Post by drifting »

They were high level. Darendor in an earlier post did some testing with a new party and saw the same results. I'm going to look at the $4CE5 routine a little closer to see what I can find.

I'm thinking that there is some flaw in the save check code that was discovered post-C64 and Apple II and pre-DOS. The DOS version of the traps doesn't use the save check code for traps. It just does a 50% chance of zeroing damage and, failing that, a 50% chance of halving damage.
Post Reply