Hi
matt. Sorry for late reply on your PM, I didn't notice it and knew about it only checking my abandoned e-mail
Unfortunatelly, there are no any really powerful debugging tools for MD, so we have to use what we have.
If you want NLZ of Flicky, here it is, I made it 5 years ago... eh, good old times....
http://shedevr.org.ru/ghost/Flicky.gen.analyzed.rar
Just disassemble file. All data marked as 0xFF.
Let me describe my vision of this situation of reverse engineering and my actions in it. Some new versions of Gens and other emulators provide some new functions, but I'm too lazy to learn something so my actions may seem primitive and "old-school"
Sorry for ugly English
The main idea is: imagine two cases:
1. Cat leaves a diamond
2. Cat doesn't leave it
In second case game uses additional logic from branch "show a diamond" and data for it. Using code/data logger we can track code and data used specially for a diamond. We need logger which doesn't log every instruction but saves MAP and logs only unique instructions. And it also must save map between logging sessions. Exodus does so, and, AFAIR, old Gens Tracer does too. So what we do?
First, we need to make save state for case 2: before cat dies and leaves diamond.
Enable logging from start (hard reset the game), start the game, walk here and there, get chickens, perform as many actions as we can to fill logger map and... kill cat without diamond. Stop the logging and save this point. On Gens Tracer you should do nothing, on Exodus you should Analyze and export log to file. Then start the logging again and load savestate where cat leaves diamond. Stop logging and save this new point. Comparing two results we will see new code/data.
Exodus was my first try, I didn't use saves and made all actions as one large try. After 2nd logger "checkpoint" it showed only 7 bytes more. Comparing results gave me address $165AC and near it. Ok, look for it in NLZed disassembly:
Code: Select all
_000164EA: AB64 Invalid
_000164EC: 08D0 0007 BSET #$7,(A0)
...
_00016502: 217C 000165AC 0008 MOVE.L #$000165AC,$0008(A0)
Look for 000164EC and get:
Code: Select all
...
_0001129E: 3F00 MOVE.W D0,-(A7)
_000112A0: 3010 MOVE.W (A0),D0
_000112A2: 6708 BEQ ROM:$000112AC(pc)
_000112A4: 0240 7FFC ANDI.W #$7FFC,D0
_000112A8: 4EBB 0006 JSR $000112B0(pc,D0.W)
_000112AC: 301F MOVE.W (A7)+,D0
_000112AE: 4E75 RTS
_000112B0: 6000 FFEA BRA ROM:$0001129C(pc)
...
_000112D8: 6000 5212 BRA ROM:$000164EC(pc)
So, we need value 0028 in d0 to get to 000164EC.
Now I could cheat and tell you "look for "0028,(A0"" or "look even for "0028,("", but it won't be truth, I didn't do so, and yes, you cannot find first substring with A0, but you can find second substring with left brace only in disassembly. But found instruction will look like
Wait a minute, we fill d0 from (A0), not (A1)! Though this instruction is that we are searching for, it's pretty unobvious a0 is equal to a1 at that moment. And there is no direct call of 0001129E
Of course, I didn't know the right instruction, so I did next steps. Unfortunatelly, 0001129E is called very often with various values for A0 and simple breakpoint to 1129E won't help. Breakpoint to 000164EC won't help too - when it's done, we will be ALREADY at 000164EC, but we need preceding code. So we need to localize frame where this breakpoint is done, stop 100-1000 instructions BEFORE it and trace in debugger to track the right conditions we are searching for. In new versions of Gens good choice is to use Slow Mode or Frame Advance.
For example, we have savestate with 10 frames before diamond appearance. We create breakpoint to 000164EC (I prefer patch-code
000164EC:60FE in embedded Cheat Engine, it will hang 68k only). Then we make 10 frame steps. Go to debugger and see we are already at 000164EC. Ok. We load savestate, make 9 frame steps, go to debugger, see some random instruction, SAVE to another slot, press P button in Gens debugger and ...voila! We've got to 000164EC. Next actions are straightforward. We trace instructions, look at RAM and localize conditions which lead us to 000164EC.
I found this subroutine:
Code: Select all
_000153A4: 08E8 0007 003C BSET #$7,$003C(A0)
...
_000153D8: 1038 D88A MOVE.B RAM:$D88A,D0
_000153DC: 0200 00F0 ANDI.B #$F0,D0
_000153E0: 6622 BNE ROM:$00015404(pc)
_000153E2: 43F8 C740 LEA RAM:$C740,A1
...
_00015400: 32BC 0028 MOVE.W #$0028,(A1)
_00015404: 6100 BD12 BSR ROM:$00011118(pc)
_00015408: 4E75 RTS
Value 0028 and condition above are what we were searching for. So what is RAM:$D88A? Open RAM window in Exodus, for example, resume the game and realize that $D888 are in-level seconds and $D88A are in-level frames (60 per second) in decimal notation. So the condition for diamond appearance is: cat should die at 0-9th frame of any in-level time second.
Phewww. ^_^
Interestingly, there is another similar subroutine, but it wasn't used:
Code: Select all
...
_0001620E: 32BC 0028 MOVE.W #$0028,(A1)
...
Similar result we should get with Gens Tracer. I've got next log after loading state with diamonded cat.
Code: Select all
TRACE STOPPED
01:53E2 43 F8 LEA ($C740),A1
01:53E6 4A 28 TST.B $0016(A0)
01:53EA 67 04 BEQ #$04 [01:53F0]
01:53F0 3E 28 MOVE.w $0030(A0),D7
01:53F4 3C 28 MOVE.w $0024(A0),D6
01:53F8 33 47 MOVE.w D7,$0030(A1)
01:53FC 33 46 MOVE.w D6,$0024(A1)
01:5400 32 BC MOVE.w #$0028,(A1)
01:12D8 60 00 BRA #$5212 [01:64EC]
01:64EC 08 D0 BSET #7,(A0)
01:64F0 66 28 BNE #$28 [01:651A]
01:64F2 42 28 CLR.B $0005(A0)
01:64F6 42 A8 CLR.L $0034(A0)
01:64FA 42 A8 CLR.L $002C(A0)
01:64FE 5E 68 ADDQ.W #7,$0024(A0)
01:6502 21 7C MOVE.l #$000165AC,$0008(A0)
01:650A 42 68 CLR.W $0006(A0)
01:650E 31 7C MOVE.w #$012C,$0038(A0)
01:6514 08 A8 BCLR #7,$0002(A0)
01:651A 61 00 BSR #$FFFFAB40 [01:105C]
01:651E 61 00 BSR #$FFFFAC06 [01:1126]
01:6522 43 F8 LEA ($C440),A1
01:6526 61 00 BSR #$FFFFB298 [01:17C0]
01:652A 4A 00 TST.B D0
01:652C 67 4E BEQ #$4E [01:657C]
01:657C 53 68 SUBQ.W #1,$0038(A0)
01:6580 66 04 BNE #$04 [01:6586]
01:6586 4E 75 RTS
TRACE STOPPED
You may see there "new" instructions from 0153E2 to 015400. And we can realize the first "new" instruction goes right after condition we are searching for.
One tricky thing.
Although this game is very small and old, internally it's pretty tricky. It copies bunch of code and data to RAM and jumps there. Here is code:
Code: Select all
_000003C8: 41F9 00010000 LEA ROM:$00010000,A0
_000003CE: 43F9 00FF0000 LEA RAM:$00FF0000,A1
_000003D4: 303C 2FFF MOVE.W #$2FFF,D0
_000003D8: 22D8 MOVE.L (A0)+,(A1)+
_000003DA: 51C8 FFFC DBRA D0,ROM:$000003D8(pc)
_000003DE: 4EF9 00FF0000 JMP RAM:$00FF0000
You should change last instruction to JMP RAM:$00010000. We will call it "hacked ROM".
Also there are many jumps to other parts of RAM.
I don't remember exactly, it seems I used original, not hacked version of ROM with Exodus, that's why it didn't show "new" code in second log (code was in RAM and I didn't log that area), only several bytes of data. And then I hacked the ROM, and later, writing this message, I tried GensTracer - on already hacked ROM.
Yeah, I've just verified, tested hacked ROM on Exodus and it gave me the same result as Gens Tracer. Quick and simple

But it needed prework - hacking the ROM.