English Amiga Board

English Amiga Board (https://eab.abime.net/index.php)
-   Coders. General (https://eab.abime.net/forumdisplay.php?f=37)
-   -   Disassembling games to find out the game logic? (https://eab.abime.net/showthread.php?t=66643)

Jonathan Drain 15 November 2012 03:36

Disassembling games to find out the game logic?
 
A lot of real-time strategy games work on rules that aren't explained in the manual or anywhere, but which are very useful for calculating the most effective strategy. Things like weapon damage, a unit's hit points, or hit/miss chances.

I have trouble spotting game logic in disassembly of the game, because it's usually a very small piece of code (e.g. checking a single integer once in the game loop) and I'm not used to assembly.

Are there any tricks to finding game rules in the game code?

copse 15 November 2012 04:51

Quote:

Originally Posted by Jonathan Drain (Post 850783)
A lot of real-time strategy games work on rules that aren't explained in the manual or anywhere, but which are very useful for calculating the most effective strategy. Things like weapon damage, a unit's hit points, or hit/miss chances.

I have trouble spotting game logic in disassembly of the game, because it's usually a very small piece of code (e.g. checking a single integer once in the game loop) and I'm not used to assembly.

Are there any tricks to finding game rules in the game code?

I don't think there's any trick to it. To me it all looks so generic until there's meaningful labels, so I tend to just plug away until it's obvious. It's like peeling away layers on an onion.

Lonewolf10 15 November 2012 22:33

Quote:

Originally Posted by Jonathan Drain (Post 850783)
A lot of real-time strategy games work on rules that aren't explained in the manual or anywhere, but which are very useful for calculating the most effective strategy. Things like weapon damage, a unit's hit points, or hit/miss chances.

I have trouble spotting game logic in disassembly of the game, because it's usually a very small piece of code (e.g. checking a single integer once in the game loop) and I'm not used to assembly.

Are there any tricks to finding game rules in the game code?


Not sure about individual games, but there are alot of tricks in coding that you can only learn from the programmers themselves. I personally hate trying to understand other peoples code (especially disassembled code).

As for the movement AI in RTS games, they basically use the A* pathfinding algorithm or a variation on it. There used to be pages documenting it on www.gamedev.net but I can't find them right now. I have them saved to my laptop, so if you are interested I can .lha the webpages and stick them in the zone.

Edit:

They moved it, it's now here:

http://www.gamedev.net/page/resource...eginners-r2003

AnimaInCorpore 16 November 2012 07:05

Quote:

Originally Posted by Jonathan Drain (Post 850783)
Are there any tricks to finding game rules in the game code?

A good start is to rename the labels of the source code first as far as you can. This helps a lot at least to separate the parts of the source which are not of interest for you.

This was helpful for me porting PacMania and Galaga 88 from the X68000 to the Atari Falcon.

Cheers
Sascha

copse 16 November 2012 07:17

Quote:

Originally Posted by AnimaInCorpore (Post 850981)
A good start is to rename the labels of the source code first as far as you can. This helps a lot at least to separate the parts of the source which are not of interest for you.

This was helpful for me porting PacMania and Galaga 88 from the X68000 to the Atari Falcon.

What disassembler did you use? While X68000 is not a platform I am really interested in, I am curious whether it correctly identified all the OS calls or just dumped them as dc.w $Fxxx?

I'm currently working on a disassembler, and have added support for X68000 executable files, and it would be helpful to know for to allow for future expansion.

AnimaInCorpore 16 November 2012 10:28

Quote:

Originally Posted by copse (Post 850982)
What disassembler did you use? While X68000 is not a platform I am really interested in, I am curious whether it correctly identified all the OS calls or just dumped them as dc.w $Fxxx?

I have written an own M68000 disassembler so that you already get a good readable source to make easy modifications later on. In fact, the main goal wasn't porting X68000 games to the Atari either but this was a good proof of concept of the first step of the idea I have.

Yes, the Line-F calls are indeed only dumped as "dc.w $fxxx" in the source code but detecting its purpose was rather easy since the value is different for each DOS call.

Here's a snippet from Galaga 88:
Code:

...
L_0003200A:
    move.w  %D0,WORD_00041424.l                    | 0x0003200A 33C0 0004 1424          |
    move.w  #0x0,-(%A7)                            | 0x00032010 3F3C 0000                |
    move.l  %A0,-(%A7)                              | 0x00032014 2F08                    |
    dc.w    0xFF3D                                  | 0x00032016 FF3D                    | _OPEN

    addq.l  #0x6,%A7                                | 0x00032018 5C8F                    |
    tst.l  %D0                                    | 0x0003201A 4A80                    |
    bmi.s  LOAD_FILE                              | 0x0003201C 6BC2                    |

    move.w  %D0,FILE_HANDLE.l                    | 0x0003201E 33C0 0004 1422          |

    move.w  WORD_00041424.l,%D0                    | 0x00032024 3039 0004 1424          |
    beq.w  L_00031DB8                              | 0x0003202A 6700 FD8C                |

    subq.w  #0x1,%D0                                | 0x0003202E 5340                    |
    beq.w  L_00031DE6                              | 0x00032030 6700 FDB4                |

    subq.w  #0x1,%D0                                | 0x00032034 5340                    |
    beq.w  L_00031E3A                              | 0x00032036 6700 FE02                |

    bra.w  L_00031E74                              | 0x0003203A 6000 FE38                |

L_0003203E:
    move.w  FILE_HANDLE.l,-(%A7)                  | 0x0003203E 3F39 0004 1422
    dc.w    0xFF3E                                  | 0x00032044 FF3E                    | _CLOSE
...

I think representing Line-A and Line-F with "dc.w $xxxx" is fine since the main purpose is to have your own opcodes for which you would use macros for a better readability.

Cheers
Sascha

copse 16 November 2012 20:49

Quote:

Originally Posted by AnimaInCorpore (Post 851003)
I have written an own M68000 disassembler so that you already get a good readable source to make easy modifications later on. In fact, the main goal wasn't porting X68000 games to the Atari either but this was a good proof of concept of the first step of the idea I have.

Ah, thanks, good to know :)

Is the %A0 register naming an Atari ST style? As far as I recall, we just go vanilla A0 style in Amiga land.

copse 16 November 2012 21:08

Quote:

Originally Posted by Jonathan Drain (Post 850783)
A lot of real-time strategy games work on rules that aren't explained in the manual or anywhere, but which are very useful for calculating the most effective strategy. Things like weapon damage, a unit's hit points, or hit/miss chances.

I have trouble spotting game logic in disassembly of the game, because it's usually a very small piece of code (e.g. checking a single integer once in the game loop) and I'm not used to assembly.

Are there any tricks to finding game rules in the game code?

Coming back to this, I think that you have two options.

The currently most feasible tool, is to debug the program and get familiar with the code that way. Ideally you would have a debugger that let you relabel addresses, and basically acted as Resource+debugger. I think that Ollydbg is a PC debugger that lets you do this for PC programs. And IDA for the PC probably does the same, but I haven't used it much. But on the Amiga, I think you are out of luck. I know there was one debugger/disassembler combination for the Amiga, but it never worked for me when I tried it and I have no idea how you would obtain it anyway. I think it would not be that much work to disassemble an Amiga debugger and extend it with the ability to edit label/symbol names, and to allow saving of those and source. Another option is to use the WinUAE debugger, but I've always found using it somewhat inscrutable.

Another option that is not currently possible is to use a disassembler does some of the legwork for you. I don't know about you, but there's a step when I disassemble a program that was linked against a library where I go through and relabel all the routines that make library calls. Then I go through and relabel all the wrapper routines that call the routines that make library calls. And then I go through and relabel all the wrapper routines that call the wrapper routines.. There's an approach that I think is called library fingerprinting - where IDA Pro or some similar solution has a database of signatures for routines that get linked from the static libraries, and can automatically label them. And similarly, instead of you needing to go find all the "move.l 4.w, A6" and set the symbol for the call into exec or whatever, they also proactively detect these OS calls and automatically put the symbols in place and comments on the arguments passed on the stack.

Links:
Signatures for Library Functions in Executable Files (citeseer paper page).
Unstrip signature detection tool.
IDA Pro FLIRT signature detection.

Of course, another approach might be to do try IRA. Getting reassembleable source code, and debugging it in the assembler might be somewhat helpful.

AnimaInCorpore 16 November 2012 22:00

Quote:

Originally Posted by copse (Post 851078)
Ah, thanks, good to know :)

Is the %A0 register naming an Atari ST style? As far as I recall, we just go vanilla A0 style in Amiga land.

Actually the style is a little awkward but this is accepted by the Human68k and the m68k-atari-mint toolchains as well so I can assemble the same source on both systems. ;)

The disassembler can, however, be configured to produce different styles.

Cheers
Sascha

Jonathan Drain 17 November 2012 05:02

What I've been doing so far is to disassemble with IRA, then when I work out what a label is for, I find-and-replace the label name with a more descriptive one. Amiga system library calls are easy to spot, and from there you can tell which parts of code probably deal with sound, graphics, disk IO, etc. It's like building a jigsaw by finding the edges and working inward.

Finding an individual line of game logic is like looking for a needle in a haystack. If only I had a magnet!

copse 17 November 2012 05:43

Quote:

Originally Posted by Jonathan Drain (Post 851166)
What I've been doing so far is to disassemble with IRA, then when I work out what a label is for, I find-and-replace the label name with a more descriptive one. Amiga system library calls are easy to spot, and from there you can tell which parts of code probably deal with sound, graphics, disk IO, etc. It's like building a jigsaw by finding the edges and working inward.

Finding an individual line of game logic is like looking for a needle in a haystack. If only I had a magnet!

Is there any reason you don't use resource? The ability to jump around the source code, is quite handy and a lot more than doing it by hand ala ira.

Jonathan Drain 18 November 2012 21:10

I'm not sure. I think because I couldn't find a full version of ReSource at the time, so I just tried to see what could be done with IRA and the WinUAE debugger. I'm really an asm noob.

Minuous 19 November 2012 07:23

Quote:

Originally Posted by AnimaInCorpore (Post 851093)
The disassembler can, however, be configured to produce different styles.

What about CALM (Common Assembly Language for Microprocessors) notation?

copse 20 November 2012 00:42

Quote:

Originally Posted by Minuous (Post 851597)
What about CALM (Common Assembly Language for Microprocessors) notation?

Out of curiosity, why would anyone support this?

Minuous 20 November 2012 02:24

Why wouldn't they? It's a bit pointless having to learn completely new syntax for every different CPU when they all carry out much the same operations, it makes it far easier to read code for unfamiliar CPUs, etc. I really can't think of a single advantage to manufacturer-specific notation (except that you can quickly tell in most cases what CPU the assembly code you are looking at is written for, because of the non-standardization. But generally one would know this in advance anyway).

It's not hard to support, eg. the disassembler subsystem of my emulator supports it for both the supported CPUs (2650 and 6802).

Anyway I won't rehash all the arguments in favour of it, I will just give some links which provide justification and reference:

http://calm.baillifard.com
http://www.pf-soft.ch/ascalm.php?L=E&C=W
http://www.didel.com/calm/


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

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.

Page generated in 0.06698 seconds with 11 queries