regs/README.md
2018-08-19 17:24:54 -07:00

175 lines
8.5 KiB
Markdown
Executable File

# What is this?
This is a set of command-line tools designed specifically to reverse engineer Apple IIgs software. It is comprised of 3 separate tools; `2mg`, `omf`, and `regs`.
## 2mg
`2mg` extracts .2mg and .po prodos disk images. You can also just list the contents of the disk image with the `-l` or `--list` command line argument. Otherwise, it will create a folder with the name of the disk and extract all the files into that folder.
## omf
`omf` is a rather complicated tool which is designed to extract relocatable segments from OMF files. Apple IIgs executables (.sys16 files) and system tools (ex. SYSTEM/TOOLS/TOOL025) are in OMF format.
You first run this tool and pass it an OMF file and it will generate a .map file. This map file is a simple text file that you may edit. Each line is in the format:
`segment:memory location`
The `segment`is the segment number from the OMF file, and `memory location` is where in memory to relocate that segment.
`omf` does its best to automatically pack all the relocatable segments into the smallest memory possible, starting at `$2/0000`. You can change the starting memory address with the `-o` or `--org` argument. If you wish to manually specify where each segment should go in memory, feel free to edit the .map file however you wish.
The next step is to run `omf` again, this time specifying the map file with `-m` or `--map`. This will apply the .map to the OMF and output each segment along with a corresponding .map file. `omf` will throw an error if the segments cannot be mapped as the .map file dictates (for example, you modified the map file so that the segments accidentally overlap).
`omf` will modify each segment, applying the proper relocations before outputting the segment. If you wish to change where a segment is in memory, you should modify the original .map file and re-run `omf`. The resulting output files will be hardcoded for those specific memory locations.
The segment outputs will be named `segX` and `segX.map`, where `X` is the segment number, in hex. If you wish to change the prefix from `seg` use the `-p` or `--prefix` argument.
At this point, you can use the resulting segment files and map files as input to the `regs` tool.
## regs
`regs`is my 65816 tracing disassembler. It can be used in conjunction with the .map files created by `omf` or on its own. Since it is a tracing disassembler, it will start disassembly at a given location, and keep disassembling, following all possible paths. Everything not disassembled will be assumed to be data and shown in a hex view.
#### regs by itself
You can call `regs` and simply pass it a binary file and it will attempt to disassemble it. You can specify where in memory it should load the file before disassembly with the `-o` or `--org` argument. You can also control whether or not the disassembler is in emulation mode or 16-bit mode with various command-line arguments. Emulation mode is also useful for disassembling 8-bit Apple II software. Use `-e` to start in emulation mode (default native mode), `-m` to start with an 8-bit accumulator (default 16-bit), and `-x` to start with 8-bit index registers (default 16-bit).
#### regs with .map files
`regs` with .map files is where the disassembler really shines. You can call `regs` and pass it a .map file generated by `omf` and have real control over the disassembly. The .map file is designed to be edited by hand. The format is as follows:
```
gMAP "seg1"
sORG $30000
$30000:
$30053:mx
$31066:e
```
The first line specifies the segment file that this map applies to. The filename in the quotes should be relative to the current directory.
The next line specifies where the segment belongs in memory. **Do not edit this** if the segment was created by `omf`, since it has also been hardcoded in the binary.
The next lines are a list of entry points to begin disassembly at. If, when analyzing the disassembly you find a switch case encoded as an indirect jump, you can take that list of jumps and add them to the map file and re-run `regs` to disassemble the previously un-disassembled data. As you work through a disassembly, you may end up with a map file with hundreds of entry points, that's normal.
The flags after the colon are optional, and specify whether emulation mode should be enabled, or 16-bit or 8-bit accumulator and index registers should be used. It defaults to native mode with 16-bit registers.
You can also use bank-separators if you wish. `$3/1066` is the same as `$31066`.
## Pascal folder
You'll notice a pascal folder in this repository. These are the original GS/OS pascal header files. This is to make it easier for you to look up the arguments and structures of various tool calls you'll come across when disassembling.
# Examples
The flexibility of these tools makes their use a little complicated. So here are some examples of how to go about disassembling various things.
### Disassembling an S16
I'll be using the S16 from Dream Zone as an example.
Generate a basic map of your S16:
`$ omf dream.s16`
This will create a file called `dream.s16.map`, which we could edit if we choose. We'll leave it as it is. Extract the segments of the OMF with:
`$ omf --map=dream.s16.map dream.s16 --prefix=dream`
This will create files `dream1`to `dream5` as well as `dream1.map` to `dream5.map`.
The program's entry point is always the beginning of the first segment, so we'll start there.
`$ regs dream1.map > dream1.s`
This will disassemble the entry point. We can then modify the map to further refine the disassembly if we wish.
### Disassembling a Tool
This works the same as disassembling an S16, but with an important difference.
We'll start the same, generating a map and extracting it.
```
$ omf TOOL025
$ omf --map=TOOL025.map TOOL025
```
Now, we'll remove all disassembly instructions from the map. You'll see why in a second. So we edit the map file to look like the following:
```
gMAP "seg1"
sORG $20000
```
That's it.. no disassembly instructions. Now we run the disassembler:
`$ regs seg1.map > seg1.s`
This will just give us a hex dump of the segment. That's actually what we want. All tools start with a tool table. The first dword specifies the number of tools in this toolset. The next dwords all contain addresses (minus 1) of the various tool entry points.
Let's say I want to disassemble NoteOn. We check the pascal folder and discover that it's tool $0b inside the $19 toolset. Which is the TOOL025 file we're working on (the tool numbers in the filenames are in decimal). So we calculate the offset to that entry point.
`$0b * 4 + $20000 = $2:002c`
If we look at the hex dump at that location we'll discover the entry point of NoteOn: `$2:02dd`. Well that's minus one, so we add the real entry point to the .map file:
```
gMAP "seg1"
sORG $20000
$2/02de:
```
And rerun the disassembler.
`$ regs seg1.map > seg1.s`
We have just disassembled the NoteOn function.
### Disassembling a Specific Tool Call in ROM
Let's say I want to disassemble WriteRamBlock. We discover it's in the sound toolset $08. If you search, you'll discover that there isn't a TOOL008 anywhere, so we'll have to pull it from ROM. I'll be using an older 128k ROM just because it's convenient.
First thing I do, is actually hand make a `rom.map` file for the ROM.
```
gMAP "APPLE2GS.ROM"
sORG $fe0000
$fe/0000:
```
and disassemble it.
`$ regs rom.map > rom.s`
This is actually the bootstrap that initializes the `$e1/0000` tool call entrypoint. I notice it copies over a block of memory from `$fe/0051` into `$e1/0000`. So we add `$fe/0051` to the disassembly list of the map file, and disassemble it again.
Following along with the disassembly, we discover that there's a toolset list starting at `$fe/012f`. It starts with a dword with the number of toolsets in the ROM, followed by a list of offsets to the various toolsets. We want toolset 8 for the sound toolset.
`$8 * 4 + $fe012f = $fe014f`
Look up the dword in that location and I find that the toolset is located at `$ff/3e00`. If you then jump to that location, you'll find this is in the exact same format as a tool on disk. It starts with a tool table. WriteRamBlock is tool 9.
`$9 * 4 + $ff3e00 = $ff3e24`
At that location, we discover the offset to the tool entry point is `$ff/41a4` so we'll add `$ff/41a5`to the map file and rerun the disassembly.
Boom, we have just disassembled a specific tool call from ram.