Reducing Ati Roms

Reducing ATI ROMs

This page contains instructions for removing the NDRV code from a 128k ATI ROM. They were originally written by joevt, and have been modified and expanded by 0850-1337. Removing the NDRV reduces the size of the rom to < 64KB, making it fit onto the smaller ROM chips found on many PC cards. This procedure has seen mixed success; while many reduced ROMs, such as the 9800 Pro v130 ROM, are great, other ROMs such as the reduced 9700 v124 Pro ROM, have been shown to be not-so-great. Fear not, however, as in that particular case, problems with the 9700 Pro reduced ROM have been fixed by modifying the 9800 Pro v130 ROM to run on 9700s.
A newer and a bit easier method is now available to reduce ATI ROMs. It's been tested by gotoh on X800XT retail ROM, Radeon 9800 Pro Retail V130 ROM, Radeon 9600XT OEM and Radeon 7000 PCI ROM (this last one is not perfect). It also worked partly on X850XT OEM ROM. Unfortunately, reducing ATI ROMs seems to give good results only on Retail ATI cards' ROMs supported by ATI ROM Extender, included in ATI ROM updater (last one is August 2005 version from AMD/ATITECH). So OEM ATI cards might work, fully, partly or not properly with reduced ATI PowerPC ROMs, because some features may only work with NDRV present in ROM. ATI ROM Extender also provides these settings (like correct monitor detection or fan control) but unfortunately, this extension only supports Retail ATI cards (or flashed PC cards using Retail/reduced Retail ATI ROM).

What I'm trying to say is that here, as always, your mileage may vary.

Reducing ATI ROMs

Hex numbers are indicated by the "h" suffix. All other numbers are in decimal, and written math expressions obey conventional order of operations. One pair of hex digits is one byte.

1) Delete everything between the first occurrence of 12 FC 4A 6F 79 21 h and the last occurrence of 01 15 01 12 h inclusive plus the next 8 bytes (pairs of hex digits) after that.
Note : if the next 8 bytes begin with C3 08 … they should not be removed or reduced ROM won't work—this has been tested on both the Radeon 9600XT and 8500 ROMs, and is also present in 9800XT ROM but untested so far.

2) Delete any occurances of 12 19 64 72 69 76 65 72 2C 41 41 50 4C 2C 4D 61 63 4F 53 2C 50 6F 77 65 72 50 43 01 10 h and the 4 bytes before each occurence.
Note: 7000 226 reduced ROM omits the 10 bytes before that string - don't know why. If anyone can test this on a 7000, that would be good.

The NDRV is now removed. The next steps fix up the PCI Header:

3) Find the first occurrence of F1 08 h. The offset of that is the start of the Open Firmware FCode. Change the content of the 4-byte group beginning with the third byte after F1 08 h to: the offset of the last non-zero byte, plus two, minus the offset of the F1 08 h.

Example (from 9800 Pro 130 ROM):

0x00000030: FB 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00
0x00000040: F1 08 D1 96 00 01 F4 35 12 36 00 00 00 00 00 00
0x00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0x000050A0: 61 70 01 10 12 04 31 2E 39 34 01 14 12 09 41 54
0x000050B0: 59 2C 46 63 6F 64 65 01 10 00 00 00 00 00 00 00
0x000050C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Your calculation:

* 50B8h + 2h - 40h = 507Ah

I do this using a TI-86, although OS X's Calculator.app can also work in hex. To do this, choose View->Programmer, then click the Hex button on the Calculator.

So, the value of your 4-byte group changes as follows:

0x00000030: FB 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00
0x00000040: F1 08 D1 96 00 00 50 7A 12 36 00 00 00 00 00 00
0x00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

4) Remember the offset of your last non-zero byte - in the example above, it was 50B8h. Find the first occurrence of 000003h in your ROM. Change the next byte after 000003h to the hex equivalent of the integer value (truncate) of the offset of your last non-zero byte, plus 2, plus 511, divided by 512. This step may be trivial, however not enough testing has been done yet to know.

Your calculations:

* 50 B8 h = 20664

* (20664 + 2 + 511) / 512 = 41.3613… truncate to 41

* 41 = 29 h

Alternately, if you work only in hex, you will probably come up with:

* (50 B8 h + 2 h + 1 FF h) / 2 00 h = 29 h

Anyway, here is an example before modification:

0x00000010: 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00
0x00000020: 50 43 49 52 02 10 48 4E 00 00 20 00 00 00 00 03
0x00000030: FB 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00

And this is the result after modification:

0x00000010: 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00
0x00000020: 50 43 49 52 02 10 48 4E 00 00 20 00 00 00 00 03
0x00000030: 29 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00

If the byte following the one you just changed is anything other than 00h, change it to 00h.

Finally,

5) Optional, but not a bad idea: Add zeros to the end of the file until the size is extactly 64KB (up to offset 0x0000FFFF).

Reducing ATI ROMs

New method, tested and working on X800, 9800Pro, 9600XT, 7000 PCI, so testers for other cards are welcome!

Reducing ATI ROMs

Hex numbers are indicated by the "h" suffix. All other numbers are in decimal, and written math expressions obey conventional order of operations. One pair of hex digits is one byte.

1) Delete everything between the first occurrence of 12 FC 4A 6F 79 21 h and the last occurrence of 01 15 01 12 C3 h inclusive.
Radeon 7000 PCI ROM did not have 01 15 01 12 C3 h. The NDRV ended with 01 15 01 12 h so you need to make sure you reach the last 01 15 01 12 h and check if it ends with C3 h or not.

2) Delete any occurances of 12 19 64 72 69 76 65 72 2C 41 41 50 4C 2C 4D 61 63 4F 53 2C 50 6F 77 65 72 50 43 01 10 h

The NDRV is now removed. The next steps fix up the PCI Header (unchanged from first version):

3) Find the first occurrence of F1 08 h. The offset of that is the start of the Open Firmware FCode. Change the content of the 4-byte group beginning with the third byte after F1 08 h to: the offset of the last non-zero byte, plus two, minus the offset of the F1 08 h.

Example (X800XT ROM):

0x00000000: 55 AA 40 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00000010: 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00
0x00000020: 50 43 49 52 02 10 48 4A 00 00 20 00 00 00 00 03
0x00000030: F1 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00
0x00000040: F1 08 51 32 00 01 DF EB 12 36 00 00 00 00 00 00
0x00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0x00005BD0: 65 72 6C 61 70 01 10 12 04 35 2E 30 30 01 14 12
0x00005BE0: 09 41 54 59 2C 46 63 6F 64 65 01 10 00 00 00 00
0x00005BF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Your calculation:

* 5B EB h + 2 h - 40 h = 5B AD h

I do this using OS X's Calculator.app. To do this, choose View->Programmer, then click the Hex button on the Calculator.

So, the value of your 4-byte group changes as follows:

0x00000000: 55 AA 40 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00000010: 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00
0x00000020: 50 43 49 52 02 10 48 4A 00 00 20 00 00 00 00 03
0x00000030: F1 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00
0x00000040: F1 08 51 32 00 00 5B AD 12 36 00 00 00 00 00 00
0x00000050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

4) Remember the offset of your last non-zero byte - in the example above, it was 50B8h. Find the first occurrence of 000003h in your ROM. Change the next byte after 000003h to the hex equivalent of the integer value (truncate) of the offset of your last non-zero byte, plus 2, plus 511, divided by 512. This step may be trivial, however not enough testing has been done yet to know.

Your calculations:

* (5B EB h + 2 h + 1 FF h) / 2 00 h = 2E h

Anyway, here is an example before modification:

0x00000000: 55 AA 40 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00000010: 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00
0x00000020: 50 43 49 52 02 10 48 4A 00 00 20 00 00 00 00 03
0x00000030: 2E 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00

And this is the result after modification:

0x00000000: 55 AA 40 00 00 00 00 00 00 00 00 00 00 00 00 00
0x00000010: 00 00 00 00 00 00 00 00 20 00 00 00 00 00 00 00
0x00000020: 50 43 49 52 02 10 48 4A 00 00 20 00 00 00 00 03
0x00000030: F1 00 00 00 01 80 00 00 00 00 00 00 00 00 00 00

If the byte following the one you just changed is anything other than 00h, change it to 00h.

Finally,

5) Optional, but not a bad idea: Add zeros to the end of the file until the size is extactly 64KB (up to offset 0x0000FFFF).

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.