English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 27 December 2020, 13:48   #1
moohorse
Registered User
 
moohorse's Avatar
 
Join Date: Oct 2020
Location: United Kingdom
Posts: 17
Help disassembling Wicked

Hello! I'm hoping someone will be kind enough to help nudge me along with disassembling Wicked (Electric Dreams, 1989). I'd like to be able to add a trainer for a level skip/infinite time, as the game is still too hard even with infinite lives. You just can't get past some of the later levels.

I have the original disk, the dual-format Zero #11 disk (in the Zone) and the QTX disk. Wicked used the Rob Northen Copylock protection system, so I don't think I'm able to use the hunk files from the original disk - and I think it was encrypted with incbin, or the Zero disk (as that was also compressed with Rob Northen) for disassembly.
I'm trying to disassemble a WinUAE savestate in IDA, but I have no idea where to start analysing from. This is my first time trying to disassemble something with copy protection.

Or can I disassemble from @Abaddon's WHDLoad v1.1 as that seems to have patched some things, so I'm sure he must have been able to disassemble it. I've no idea where to begin with that, though.

I'd just like to have the asm to look at. I'm so curious about this game, I'd love to understand how it works!

I should be grateful for any pointers, tips, (or if some kind person could send a .s file)

Many thanks!
Attached Thumbnails
Click image for larger version

Name:	wickeddisk.jpg
Views:	178
Size:	109.7 KB
ID:	70076  
moohorse is offline  
Old 27 December 2020, 14:12   #2
dlfrsilver
CaptainM68K-SPS France
 
dlfrsilver's Avatar
 
Join Date: Dec 2004
Location: Melun nearby Paris/France
Age: 46
Posts: 10,481
Send a message via MSN to dlfrsilver
First check if the game has real files, or if those are hidden on the disk.

Next, if the main code is encrypted, you will have to decrypt it before doing any disassembly of the game.
dlfrsilver is offline  
Old 27 December 2020, 14:22   #3
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,307
hooking just before the patch in whdload is the method I use to analyze the code for trainer, second buttons.. etc...

you want a trainer for whdload version? I can do it if you want (and provide the details on how I did it)
jotd is offline  
Old 27 December 2020, 14:37   #4
moohorse
Registered User
 
moohorse's Avatar
 
Join Date: Oct 2020
Location: United Kingdom
Posts: 17
@jotd That would be awesome! I'd love to know how to do that.

I think it starts at $280AA in the snapshot I've loaded in to IDA. Certainly g [280aa] in the debugger takes me back to the title start.

Code:
ROM:000280AA sub_280AA:                              ; CODE XREF: sub_29B9C?j
ROM:000280AA
ROM:000280AA ; FUNCTION CHUNK AT ROM:00028C86 SIZE 00000592 BYTES
ROM:000280AA
ROM:000280AA                 move    #$2700,sr
ROM:000280AE                 move.w  #$8200,($DFF096).l
ROM:000280B6                 movea.l #$800,sp
ROM:000280BC                 move.w  #1,(word_5E4).l
ROM:000280C4                 bsr.w   sub_29B5C
ROM:000280C8                 bsr.w   sub_29B86
ROM:000280CC                 bsr.w   sub_29976
ROM:000280D0                 moveq   #0,d0
ROM:000280D2                 bsr.w   sub_2DCF0
ROM:000280D6                 lea     (word_5B2).l,a0
ROM:000280DC
ROM:000280DC loc_280DC:                              ; CODE XREF: sub_280AA+3C?j
ROM:000280DC                 move.b  #0,(a0)+
ROM:000280E0                 cmpa.l  #$5E4,a0
ROM:000280E6                 bne.s   loc_280DC
ROM:000280E8                 jsr     sub_29994
ROM:000280EE
ROM:000280EE loc_280EE:                              ; CODE XREF: sub_280AA+9FA?j
ROM:000280EE                 bsr.w   sub_29A5E
ROM:000280F2                 movea.l #unk_343EA,a0
ROM:000280F8                 move.w  #$17,d0
ROM:000280FC                 move.w  #0,d1
ROM:00028100                 jsr     sub_2989C
ROM:00028106                 clr.w   (word_34812).l
ROM:0002810C                 clr.w   (word_34838).l
ROM:00028112                 clr.w   (word_34968).l
ROM:00028118                 clr.w   (word_34820).l
ROM:0002811E                 clr.w   (word_34846).l
ROM:00028124                 jsr     sub_2BF6E
ROM:0002812A                 move.w  #4,(word_476).l
ROM:00028132                 move.w  (word_5B2).l,d0
ROM:00028138                 addq.w  #2,d0
ROM:0002813A                 move.w  d0,(word_586).l
ROM:00028140                 move.l  #unk_60EE6,d1
ROM:00028146                 move.l  #unk_5E546,d2
ROM:0002814C                 cmpi.w  #1,(word_5C0).l
ROM:00028154                 bhi.w   loc_28162
ROM:00028158                 move.w  #1,(word_4BA).l
ROM:00028160                 exg     d1,d2
moohorse is offline  
Old 27 December 2020, 15:02   #5
moohorse
Registered User
 
moohorse's Avatar
 
Join Date: Oct 2020
Location: United Kingdom
Posts: 17
Oh, there are two versions of the game.

IPF-1263 - The Intro/Loader is encrypted, but the game is not
IPF-0295 - Both the Loader/Intro and the game are encrypted
moohorse is offline  
Old 27 December 2020, 19:32   #6
Galahad/FLT
Going nowhere
 
Galahad/FLT's Avatar
 
Join Date: Oct 2001
Location: United Kingdom
Age: 50
Posts: 9,014
Quote:
Originally Posted by moohorse View Post
Hello! I'm hoping someone will be kind enough to help nudge me along with disassembling Wicked (Electric Dreams, 1989). I'd like to be able to add a trainer for a level skip/infinite time, as the game is still too hard even with infinite lives. You just can't get past some of the later levels.

I have the original disk, the dual-format Zero #11 disk (in the Zone) and the QTX disk. Wicked used the Rob Northen Copylock protection system, so I don't think I'm able to use the hunk files from the original disk - and I think it was encrypted with incbin, or the Zero disk (as that was also compressed with Rob Northen) for disassembly.
I'm trying to disassemble a WinUAE savestate in IDA, but I have no idea where to start analysing from. This is my first time trying to disassemble something with copy protection.

Or can I disassemble from @Abaddon's WHDLoad v1.1 as that seems to have patched some things, so I'm sure he must have been able to disassemble it. I've no idea where to begin with that, though.

I'd just like to have the asm to look at. I'm so curious about this game, I'd love to understand how it works!

I should be grateful for any pointers, tips, (or if some kind person could send a .s file)

Many thanks!
You'd be better off using the Quartex crack, i'm going by memory here but isn't it just a crunched single file?

You can depack that file and all of the nasty encryption will have been removed by Rob/Quartex so you don't even have to deal with that.

Or..... tell people here exactly what you would like with regards to trainer options, and i'm sure someone here can oblige, plenty of talented people that can do trainers in their sleep.
Galahad/FLT is offline  
Old 27 December 2020, 19:43   #7
mcgeezer
Registered User
 
Join Date: Oct 2017
Location: Sunderland, England
Posts: 2,702
I’m almost certain zeus daz already asked for this and i think stingray might have done it already.
mcgeezer is offline  
Old 27 December 2020, 20:04   #8
gurth
Registered User
 
gurth's Avatar
 
Join Date: Dec 2013
Location: Halifax
Posts: 225
Quote:
Originally Posted by moohorse View Post
Hello! I'm hoping someone will be kind enough to help nudge me along with disassembling Wicked (Electric Dreams, 1989). I'd like to be able to add a trainer for a level skip/infinite time, as the game is still too hard even with infinite lives. You just can't get past some of the later levels.

I have the original disk, the dual-format Zero #11 disk (in the Zone) and the QTX disk. Wicked used the Rob Northen Copylock protection system, so I don't think I'm able to use the hunk files from the original disk - and I think it was encrypted with incbin, or the Zero disk (as that was also compressed with Rob Northen) for disassembly.
I'm trying to disassemble a WinUAE savestate in IDA, but I have no idea where to start analysing from. This is my first time trying to disassemble something with copy protection.

Or can I disassemble from @Abaddon's WHDLoad v1.1 as that seems to have patched some things, so I'm sure he must have been able to disassemble it. I've no idea where to begin with that, though.

I'd just like to have the asm to look at. I'm so curious about this game, I'd love to understand how it works!

I should be grateful for any pointers, tips, (or if some kind person could send a .s file)

Many thanks!
What a fantastic idea and approach. This is something I hope to do myself in 2021. Bravo.
gurth is offline  
Old 28 December 2020, 14:57   #9
moohorse
Registered User
 
moohorse's Avatar
 
Join Date: Oct 2020
Location: United Kingdom
Posts: 17
That's interesting.
I think I managed to disassemble an ST memory dump and a lot of the code is similar to the Amiga memory dump. I feel I might have something to study!
Attached Thumbnails
Click image for larger version

Name:	WickedCompare.PNG
Views:	155
Size:	441.4 KB
ID:	70088  
moohorse is offline  
Old 28 December 2020, 15:51   #10
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,307
okay, here's a small "tutorial" on how to hack a game that is already running on whdload, on WinUAE.

0. installs:

- download the whdload package (dev) and wicked.lha on whdload site. Make sure that you have the source code in the package... Or check my github for my slaves.
- install vasm on windows
- install ira on windows
- install notepad++ with a proper asm 68k outline

1. assemble the .slave file. I'm using and vasm cross assembler with the following options:

Code:
vasmm68k_mot -DDATETIME -Ipath_to_OS_includes -Ipath_to_whdload_includes -devpac -nosym -Fhunkexe Wicked.slave WickedHD.s
(set the proper values for OS/whdload includes, those dirs should contain os include dirs like exec, dos... and also whdload.i and other whdmacros.i of the whdload dev package)

I've renamed the file Keith provided as Wicked.asm to WickedHD.s because I'm a maniac and I have a process to update my slaves/manage them with git.

2. annoying part: figure out which parts of the source aren't relocatable

barfly optimizes calls like move.l resload,a2 to move.l resload(pc),a2, vasm does not. So it's better to add PC-relative directive where it's missing. WHDload is going to yell at startup without it. Use "hunkfunc" to figure out the number of relocs, or use find_slave_relocs.py from my github tools repo.

3. run the slave (WinUAE) and check that it's working

4. now just before the main "patch" call (where the code is loaded but not patched yet by whdload), put a "blitz" macro instruction. For this game it's going to be here:

Code:
_PatchMain
		;waitbutton
		
		cmp.l		#$41fa0022,($25000)
		beq		.notencrypted
		bsr		_Decode295Main
		bsr		_Relocate
.notencrypted
    blitz   ; <----------------- add the instruction here
		lea		_PL_MAIN(pc),a0
		bsr		_Patch
5. Run the game again. Now you're going to see color blitz waiting for mouse button. Break with Shift+F12 to get winuae console.

6. Now with the slave source we know that the game starts at $25000. We don't know where it ends. Well, we could but what the hell... We know that it can't be above $80000 for this 512k chip game. We could monitor what the game loads too, and it's even easier when the game uses files as we can guess the size (unless it's packed, where we can guess too )

Slave has set WHDLF_ClearMem so we should find a lot of zeroes at one point and guess that the executable ended ($CCCCCCCCC if the flag is not set)

Once we have the end (or what we think is the end) just save the binary data using S command

Here it appears in _Decode295Main routine that the executable part has $15ED6 longwords

so:

Code:
> S wicked_25000.bin $25000 $15ED6*4
Wrote 00025000 - 0007CB58 (359256 bytes) to 'wicked_25000.bin'.
the file is usually created somewhere like C:\Users\Public\Documents\Amiga Files\WinUAE

7. now the fun begins. Disassemble the file with IRA like this

Code:
ira -a -offset=$25000 wicked_25000.bin
which creates a 4MB .asm file called "wicked_25000.asm". I've zoned a copy (after applying my cheapres.py tool on it, which in that case will name the custom chip register offsets, not really useful in our trainer case)

the patchlist seems to have a zero-base address (all addresses are absolute). It's okay for a hardware banging/no OS game that uses chipmem for code (the easiest ones).

in main patchlist, now we can see that Keith already fixed stuff (access fault):

Code:
PL_NOP		$25ccc,8		; Fix Access Fault move.b #$8e,($fffa21)
if we look into the source we see the faulty instruction trying to write into $fffa21 which is... in ROM argh:

Code:
LAB_0037:
	MOVE.B	#$8e,EXT_02f7		;25ccc: 13fc008e00fffa21
Since it does nothing useful, Keith NOPed the 8 bytes with PL_NOP

yeah, you're starting to get the gist of it.

8. Trainer: infinite energy

Energy is not that easy to find, because as opposed as lives, you don't have a clear "3" or "2" digit and you can't use standard trainers easily. BUT Winuae offers deep trainer. We note that energy decreases, then increases when a life is lost

So start game, shift+F12 and start with "D" (init trainer pass). Then continue ("c") and lose some energy and use "Dd" (decrease) to tell winuae that the value you're looking for has decreased. Continue, if you lose a life, energy is resplenished. Use "Di" increase in that case.

After 10 or 12 iterations, I find that the value $4B4 (looks good, low address for variables are common in games) contains the energy. To test if it works, just write into $4B4 with $2F

Code:
>W $4B4 $2F.B
Wrote 2F (47) at 000004B4.B
continue the game (c) and you'll notice that the energy bar is now full. Okay but what is the part of the code that decreases the energy? There are 2 methods. First try to check for $4B4 in the source. yeah, found the init part already:

Code:
	MOVE.W	#$2f00,D1		;273c2: 323c2f00
LAB_00EC:
	MOVE.W	D1,EXT_00b0		;273c6: 33c1000004b4
I renamed the EXT variable and searched further

Code:
	MOVE.W	#$5f00,D0		;28eac: 303c5f00
	SUB.W	energy,D0		;28eb0: 9079000004b4
	MOVE.W	D0,energy		;28eb6: 33c0000004b4
this is the only other occurrence. We probably have our winner (energy & lives values aren't generally too sneaky, those aren't protections). Ok now quit the game and add a conditional NOP in the patch list. We had added in the whdload slave config something like:

Code:
		dc.b    "C1:X:Enable Trainer:0;"
which means: if bit 0 of custom 1 value is set, enable trainer. This activates this part of the main patchlist we just created

Code:
        PL_IFC1X    0
        PL_NOP  $28eb6,4    ; infinite energy
        PL_ENDIF
problem: it doesn't work because at some point the code locations change (the code partially moves itself for some reason, so our first disassembly dump isn't that useful)

Ok, I was doing this live, and assuming it was easy enough for a kind of tutorial. The steps above will work for a lot of games, though. To be continued...

Last edited by jotd; 28 December 2020 at 16:45.
jotd is offline  
Old 28 December 2020, 16:48   #11
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,307
ok, now we know that energy is in $4B4 all right. Without further disassembly we can use a memory watchpoint to find where the code is changed. Note that JIT MUST BE DISABLED to be able to use watchpoints.

Code:
w 0 $4B4.W 2 W
c
we'll get back into winuae when $4B4 or $4B5 is changed. Bingo

Code:
Memwatch 0: break at 000004B4.W  W  00001F00 PC=0002A3A8 CPUDW (000)
>d $2A3A2
0002A3A2 33c1 0000 04b4           MOVE.W D1,$000004b4 [1f00]
0002A3A8 e049                     LSR.W #$08,D1
We can locate this code at a different address.

Code:
	MOVE.W	#$2f00,D1		;273c2: 323c2f00
LAB_00EC:
	MOVE.W	D1,energy		;273c6: 33c1000004b4
Damn. So our patch was not effective. I forgot that location. I don't like having to patch going which is moved afterwards... but well...

Actually we probably just patched the position of the energy bar but not the real energy... We could find where the energy is really stored by going "upstream" to see how this position is computed. But nevermind since Keith had put a little "infinite energy" trainer, but it didn't work because...

he overlooked the fact that his address is the in-game address and not the address when he patches the code. But he had the proper code to change so that saves a LOT of time thanks!

The lower addresses patches work, but at some point, code moves to other locations... So using the address $2bf22 in game and what it contains (NEG D6 + a test), we get code that is located in 28f46

Code:
        PL_IFC1X    0
   		PL_NOP		$28f46,2			; Infinite Energy - Neg.w d6
        PL_ENDIF
let's try this (tick "trainer" / custom1=1) aaaand... it works ! We now have infinite energy.

But that's not very easy because every code we'll get from the running game will need to be computed back to the original disassembly... I don't like working like that (plus it means that the code copies code in locations, without flushing caches which can cause issues on some machines)

ok, I get it, first thing the code does is to relocate itself

Code:
	ORG	$25000

SECSTRT_0:
	LEA	LAB_0001+2(PC),A0	;25000: 41fa0022
	ADDA.L	#$00057b2c,A0		;25004: d1fc00057b2c
	LEA	EXT_02c3,A1		;2500a: 43f90007fb2c
	MOVE.L	#$00015ecb,D0		;25010: 203c00015ecb
LAB_0000:
	MOVE.L	-(A0),-(A1)		;25016: 2320
	SUBQ.L	#1,D0			;25018: 5380
	BNE.S	LAB_0000		;2501a: 66fa
	JMP	LAB_0161+4		;2501c: 4ef9000280aa  jmp to $280AA
All patch offsets are just shifted by $2fdc bytes. No biggie. To save time we could compute the addresses, or just "blitz" after the code is copied and dump + disassemble again.

Doing so, the running code addresses match the disassembly addresses. I'm going to do that. As you see there are a lot of minor annoyances in this process. But a lot of games are more straightforward too.

Adding levelskip is slightly more difficult. You have to locate the main game loop and see how it exits. Sometimes I use savestates just before completing a level to figure out where it happens (did that for Deliverance for instance).

I'm going to do that. Pick another game if you want, open another thread and I'll try to create another tutorial.

Last edited by jotd; 28 December 2020 at 17:29.
jotd is offline  
Old 28 December 2020, 16:52   #12
moohorse
Registered User
 
moohorse's Avatar
 
Join Date: Oct 2020
Location: United Kingdom
Posts: 17
Wow, jotd! That is amazing! Thank you so much!
moohorse is offline  
Old 28 December 2020, 17:08   #13
phx
Natteravn
 
phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 2,510
Quote:
Originally Posted by jotd View Post
barfly optimizes calls like move.l resload,a2 to move.l resload(pc),a2, vasm does not.
Of course it does! But you are running Devpac-compatibility mode, and Devpac only does this optimisation with "opt a+".
phx is offline  
Old 28 December 2020, 17:11   #14
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,307
Quote:
Originally Posted by phx View Post
Of course it does! But you are running Devpac-compatibility mode, and Devpac only does this optimisation with "opt a+".

sorry to have been unexact, I don't want to add optimizations, I prefer that the code is okay from the start so it can be assembled without optimizations and work. It's simple enough.


(also sometimes I copy some binary trash as code in ripped code and I don't want it optimized it would break it)
jotd is offline  
Old 28 December 2020, 18:14   #15
Galahad/FLT
Going nowhere
 
Galahad/FLT's Avatar
 
Join Date: Oct 2001
Location: United Kingdom
Age: 50
Posts: 9,014
So, is the OP wanting to skip individual levels, or complete an entire Constellation?
Galahad/FLT is offline  
Old 28 December 2020, 18:48   #16
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,307
I don't know. I don't have a clue how to play this game.

I've located the mainloop

Code:
game_mainloop:
	JSR	LAB_0291		;28892: 4eb90002d90c
	TST.W	EXT_00ce		;28898: 4a7900000502
so far I could just make the game bug or go game over. Didn't find the "level completed" flag.

Dumped a new disassembly in the zone. This time if you compare the "source" addresses with the addresses when running the game, they match.

Last edited by jotd; 28 December 2020 at 18:54.
jotd is offline  
Old 28 December 2020, 18:55   #17
Galahad/FLT
Going nowhere
 
Galahad/FLT's Avatar
 
Join Date: Oct 2001
Location: United Kingdom
Age: 50
Posts: 9,014
Level skip

Setting one flag doesn't seem to do it, quite convoluted code, but I have something working so people can go from there and experiment!

I used the Oracle cracked version for reference

So, once the game is loaded and running do the following:

Put in a NOP in at $29e94
Put in a JSR $c0.s at $2890c followed by 3 NOP's

At $c0 write the following code:

btst #2,$dff016
bne $e0
move.w #1,$516.s
tst.w $5ca.s
beq $da
subq.w #1,$5ca.s
jmp $2893e
tst.w $516.s
bne $e8
rts
jmp $2893e

When playing the game, press RIGHT mouse button and it should skip the current level.
Galahad/FLT is offline  
Old 28 December 2020, 20:59   #18
jotd
This cat is no more
 
jotd's Avatar
 
Join Date: Dec 2004
Location: FRANCE
Age: 52
Posts: 8,307
great. I'm going to add this to the whdload version
jotd is offline  
Old 30 December 2020, 01:20   #19
moohorse
Registered User
 
moohorse's Avatar
 
Join Date: Oct 2020
Location: United Kingdom
Posts: 17
$5c8 is the lives counter.

ROM:00029916 subq.w #1,($5C8).l ; Subtract Quick

SUBQ.W #1,EXT_011e ;29916: 5379000005c8

so EXT_011e is the lives variable

Now to try and find the timer...
moohorse is offline  
Old 30 December 2020, 16:16   #20
WayneK
Registered User
 
Join Date: May 2004
Location: Somewhere secret
Age: 50
Posts: 366
Quote:
Originally Posted by moohorse View Post
Now to try and find the timer...

A good way to find locations for things you don't know (yet), but you do know other locations (lives for example) - put a memory watchpoint on the lives location when you're at the main menu, before you start a game, then start a game and the debugger should pop up...


Now you're looking at the "initialise player" code, where there will almost always be a bunch of code to init all the player values to their starting state, eg:


;lives

moveq.w #5,$1234
;energy

move.w #99,$1236


etc... you might also see it using some kind of structure instead of lots of fixed addresses, eg:


lea $1234,(a0)
move.w #5,(a0)
move.w #99,2(a0)


but you get the general idea! Basically note down all the locations that values are written to during the 'init player' code, then start changing them and see what happens! This is often the fastest way to find less obvious counters such as timers - good luck!
WayneK is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Disassembling a TAC 2 joystick... please help me Marty_McFly support.Hardware 23 01 March 2022 14:18
Disassembling an A600 Revival9001 support.Hardware 2 31 January 2017 07:01
Disassembling resource copse Coders. General 1 02 April 2012 03:36
Disassembling and reassembling absence Coders. General 7 22 September 2009 15:30
Disassembling games for fun crabfists Coders. General 69 29 October 2008 11:20

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 03:53.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10601 seconds with 16 queries