11

Examples of Amiga Kickstart files (ROMs) can be 256k (1.2/1.3) or 512k (3.0/3.1) binary files, located at $FC0000-$1000000 or $F80000-$1000000

Several programs are able to "soft-kick" Amigas, i.e. install another ROM than the original one, without changing the chips physically, either to upgrade to a newer ROM to run more recent programs, or on the contrary to boot older programs that aren't compatible with new ROMs.

Since the ROM is by definition not writable, those soft-kick programs have to load the replacement Kickstart somewhere else in memory.

Problem is: the ROM files isn't position-independent code. It contains a lot of hardcoded addresses between $F80000/$FC0000 and $1000000

That's where the relocation table files (aka .RTB) come into play. A table exists for almost every official ROM file (see here).

My question is: how exactly are created those relocation table files ?

I tried to re-create those myself and failed. Actually I was able to find most of the reloc offsets, but still miss some. For instance, this one is obvious, LAB_0186 must be relocated (it also could have been made originally PC-relative but that's another story:

LAB_0181:
    LEA LAB_0186,A0     ;0fc208c: 41f900fc20c0
    CLR.W   D1          ;0fc2092: 4241
    ...
    RTS             ;0fc20be: 4e75
LAB_0186:

now that one is more subtle:

MOVE.L  #$00fc1d28,312(A6)  ;0fc034a: 2d7c00fc1d280138

One recognizes an address inside the ROM, but it could be a value too. Introducing heuristics to try to find the hidden ones can find some, but also find fake ones.

And there are tables, that are difficult to figure out for the same reason (plus disassembling data confuses the disassembler which thinks that some data are instructions):

    DC.W    $00fc           ;0fc32c8
    DC.W    $25ae           ;0fc32ca   ; $FC25AE is probably an address
    DC.W    $00fc           ;0fc32cc
LAB_029C:
    MOVE.W  (A6),(A1)+      ;0fc32ce: 32d6  ; $FC32D6 too
    MOVE.W  D0,D7           ;0fc32d0: 3e00   ; now there's this stray word
    DC.W    $00fc           ;0fc32d2   
    MOVE.L  (A6)+,252(A2)       ;0fc32d4: 255e  ; and another probable address again... argh!!! 00fc
    MOVE.W  -(A0),(A1)+     ;0fc32d8: 32e0
    MOVE.W  D0,D6           ;0fc32da: 3c00
    DC.W    $00fc           ;0fc32dc

I doubt that those tables have been created by the actual Amiga developers who took time to assemble ROMs at different addresses to compute the relocation offsets (the simplest way to do that when you have the full source code) so someone did the hard job for all those Kickstarts

The author of skick probably created them himself and he confirms that it's non-trivial and is bragging about the fact that he's not going to disclose how it's done:

.RTB file consists of two parts. The first part contains all the relocation offsets ... It is created with a special program called RTG (relocation table generator) from specially pre-processed Kickstart image. How to get this image, it is my magic and I'll never tell anybody about it. One note only: generation of 39.046 .RTB took 1 1/2 hours. (Manual work, + about 10 mins my 7MHz '010 CPU time).

I'm impressed that the first part can be generated, on a 68010...

Second part contains BCPL relocation table and it is required for 1.3 ROM only. It was created manually, analysing dos.library, which is written in BCPL in 1.3.

That's more classical way to do it: fully reverse-engineer the program. I suppose it's easier because dos library is smaller, and doesn't change much between 1.x kickstarts. Not much mystery here.

.RTB file is not easy to create. I don't recommend anybody to try it without very good knowledge of assembly language and machine code (not the same). N.B. Auxiliary tools to do such work took 1 month to develop.

Yeah, I don't recommend it either...

Anyone has information on the RTG program or how it could work ? (the author didn't even have access to memory protection to execute and find ill-relocated locations...)

2
  • 1
    So you are asking how to, theoretically, automate creating a relocation table for 68k object code when you have no source code, right? – Brian H Mar 6 '20 at 22:15
  • yes, exactly. with source code, you can make the difference between data and labels, and the problem is trivial – Jean-François Fabre Mar 7 '20 at 7:23
8

The job is non-trivial, but I don't think it would be hard for someone 'experienced in the art'. 256k or even 512k is not a lot of code, and the ROMs are highly structured with a well-defined interface. I suspect it would be easier than cracking some of the more sophisticated copy-protection schemes used in Amiga games.

In some respects ROM code is easier to analyze than code compiled for RAM. No relocation quirks to worry about. No self-modifying code. Any PC-relative reference must be to code or static data (no variables mixed in with instructions!) etc. Most of the code was generated by C compilers which didn't optimize to the extent that modern compilers do, so it is clean and easy to follow.

One recognizes an address inside the ROM, but it could be a value too. Introducing heuristics to try to find the hidden ones can find some, but also find fake ones.

Any 32 bit number starting with $00fC is far more likely to be an address inside the ROM than a 'value'. Examining the code that uses the 'value' should tell you if it is an address or not.

And there are tables, that are difficult to figure out for the same reason (plus disassembling data confuses the disassembler which thinks that some data are instructions):

Tables are generally accessed with 'boiler plate' code that is easily recognizable. Tables of 16 bit words (commonly used for switch/case statements) don't need to be relocated.

A good disassembler should be able to correctly disassemble the code 99% of the time. Reviewing it and fixing misidentified sections might take a few hours. If the job is done properly it should reassemble to identical code, but this test probably isn't necessary. All you have to do is find those absolute references to memory locations in the ROM, and the rest is trivial.

Anyone has information on the RTG program or how it could work ?

I don't have any information on it, but I imagine it is just as the author described - a 'simple algorithm' that compresses the relocation offsets. You could probably figure it out by analyzing the program that extracts them.

(the author didn't even have access to memory protection to execute and find ill-relocated locations...)

No memory protection - the horror!

I doubt that those tables have been created by the actual Amiga developers who took time to assemble ROMs at different addresses to compute the relocation offsets (the simplest way to do that when you have the full source code)

They didn't do it, their compiler/linker did. Having the 'full' source code would actually be a very hard way to do it - perhaps even impossible. You would have to duplicate the exact development system that they used back then, including the same compiler versions, same make files etc. Disassembling the ROM to produce asm source which reassembles to identical code would be much easier.

8
  • " a 'simple algorithm' that compresses the relocation offsets": that part isn't a problem. I know how to read a RTB table. I should edit that part out of my question. The format of the table isn't mysterious at all. It's the way the offsets are extracted that is mysterious to me – Jean-François Fabre Mar 7 '20 at 13:44
  • you're right about the fact that any number between $F80000 (resp $FC0000) and $1000000 should be analyzed manually. The "art' of the technique is probably to save a lot of time with this analysis. – Jean-François Fabre Mar 7 '20 at 13:45
  • "The format of the table isn't mysterious at all. It's the way the offsets are extracted that is mysterious to me" - well the author says "it is my magic and I'll never tell anybody about it." so we may never know exactly how he did it. But neither finding the relocation addresses nor compressing them is 'mysterious'. The numbers don't all need to be analyzed manually. Most of them are obvious, and only a few might need manual review. A good disassembler would flag those for you. – Bruce Abbott Mar 7 '20 at 18:06
  • I mean: I'm able (and I've done that several times in cd32load, JST and some python script) to read a .RTB file and apply relocations. This is a kind of compression by providing offset as byte, word, or long relative to the previous value. – Jean-François Fabre Mar 7 '20 at 18:13
  • I have developed a disassembler which achieves up to 100% accuracy without manual intervention on load modules of 1MB and larger (it is based on 'dis' an open-source disassembler found on Fish disk 160). It generates about 60,000 lines per minute on a stock A500. In the past I would simply tweak the code to deal with individual programs. Making it produce relocation tables for ROM code would not be hard (would probably take me a day or two to implement, but I love asm coding on the Amiga so the longer the better!). – Bruce Abbott Mar 7 '20 at 18:24
3

The simple answer is don’t build your relocation tables by disassembling the code, use the relocation tables already built in tools like Remus and Capitoline.

The more complex answer and the process I use to create the tables is by breaking down the Kickstart ROM into individual modules using the ROMHEADER and LIBHEADER structures, the program kickinfo does this, however, the exact boundaries aren’t clearly labelled (ROMSKIP is unreliable for this purpose). Once you know the boundaries of the individual libraries, you can be more confident that relative addresses you find in that range that reference an address in the range is valid, i.e. libraries don’t make absolute address references outside their boundaries (not entirely true), to call another library use use that libraries call table. Once you have a list of candidate RELOC addresses you can then perform two checks, verify with disassembly, and if you’re really lucky you’ll have another ROM with the same library in a different address, repeating the process should yield identical RELOCS, if not, only the ones in common are valid. If you byte for byte compare the same library in two different Kickstarts the only differences will be absolute addresses.

To read a Kickstart and pull out the libraries, you mainly only need to understand how each library is stored, this means reading the ROMTAG structure; ROMTAG Structure but be warned, RT_ENDSKIP is the minimum end, it could end after this, also the library might start before the ROMTAG.

Doobrey's Remus tool allows you to extract individual libraries from Kickstarts (that it knows about), you can also use my tool Capitoline (this may not be it's permanent home, but you will always find the most up to date info and link to the code on Facebook.

Once you have the extracted libraries, you can read these files as they are in Amiga HUNK format, the hunks you'll be most interested in are HUNK_RELOC* and HUNK_DREL* these allow the libraries to be placed anywhere in memory (although building a Kickstart is like loading a library, the absolute addresses are decided when you build it, which is why the relocs are "lost" when you build a Kickstart)

After you have all the RELOC data for the libraries in the Kickstart, the only things remaining are the things in the ROMHEADER, this exists at the start of the ROM (EXECBASE) and in the middle of the ROM (aka KickitySplit) or the start of an expansion ROM, all three are the same thing and make sure that the hardware knows where to start (ROMBASE).

The final note is to watch out for things that aren't in library RELOC data, things it doesn't expect to move, the most important one is the library scan table in exec.library, this is a list of addresses that exec scans for libraries, so it's absolutely crucial, for example, the KS 3.1 scantable looks lke this;

0x00F800000100000000F0000000F80000FFFFFFFF

which breaks down as scan F80000-100000 then F00000-F80000 (expansion roms), note the CD32 exec also has E00000, which is why it can use an extended Kickstart), so you need to treat that first F80000 as a reloc location too (obviously a disassembler will treat this as data)

Final note, Capitoline is mainly a Kickstart editing tool to assemble your own ROMs, but it’s got a bunch of extra utilities built in like a module extractor, disassembler, splitter, merger, patcher, byteswapper etc. it has a Windows GUI, but the CLI (Windows/Mac/Linux) has all commands available, it’s also got an RTB builder built in, but as with all these things it’s not something I’ve spent too much time on and it doesn’t create RTBs exactly the same as the skick ones - in some cases only the trailers are different. Unlike skick and Remus, Capitoline uses INI files for it's reloc data, these aren't as efficient, but they are human readable if you want to compare your relocs with mine.

5
  • 1
    Answers on Stack Exchange sites are expected to stand alone. See How to Answer for details. Can you explain how your program generates these files? – wizzwizz4 Mar 3 at 13:48
  • it’s much easier to use the relocation tables from the library modules that the ROM is built from and generate an RTB from that. I can't agree more, but the exact point is I don't have the relocation tables, say, for instance, for CD32 extended ROM. from relocation tables it's easy to create .RTB files. – Jean-François Fabre Mar 3 at 15:02
  • 1
    As it stands, this doesn't answer the question. – Chenmunka Mar 3 at 18:12
  • @wizzwizz4 thanks for the advice, to answer the question “how exactly are created those relocation table files ?” there’s two parts. The format of the RTB isn’t documented, so it’s a best guess, what I do understand from it is that it uses a trivially compressed data format, I’ll add this. Second part is identifying the reloc tables, these are well know Amiga format libraries, you simply have to extract one, and create the other, I’ll add another answer when I’m at my PC next. – Mikey Mar 3 at 21:16
  • @Mikey Do you have links to the tools you mention (Remus and Capitoline)? You're allowed to link directly to your own stuff, if the answer answers the question (which I think it does now; well done!) and if you make it clear it's your own (which you did anyway); I think it'd improve your answer if you had that instead of “how to search” instructions. – wizzwizz4 Mar 3 at 23:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.