First post, by slivercr
…or, how to turn your cheap Quadro FX 1000 into a GeForce FX 5800 Ultra.
About a week ago, while rummaging through Marktplaats, I spotted a Quadro FX 1000 which had been mislabeled as Geforce 5200. I always wanted either this one or the Quadro FX 2000 since they are based on the NV30 chip, the same one powering the infamous dustbuster. I went ahead and bought it for €7 + shipping—good deal. Upon arrival I inspected it and realized the memory chips used in this card are actually the same ones used in the 5800 Ultra! (I couldn't find the exact datasheet for these markings, but they are the same that can be seen in pictures from reviews of the 5800u.)
So, while heavily underclocked at 300 Core / 300 Mem, the card will for sure reach a memory frequency of 500 MHz... if I can overclock the core to 500 MHz I'll have something special in my hands 😀 I started fiddling around, overclocking only the core, and when I pumped 1.5V into it it would do 500MHz easily, if a bit hot. And thus, the idea sprouted: lets mod the BIOS and turn this into a GeForce 5800 Ultra!
Why do this?
- because is neigh impossible to find a “real” 5800u,
- because when you find a “real” 5800u, you have to choose between buying it and paying rent,
- because you enjoy tinkering with hardware,
- because you want a quieter, single slot 5800u,
- because you can!
I knew from the get-go I didn't want to do any hardware mods to the card. I'm not averse to soldering and indeed enjoy modding my hardware, but I wanted something that could be easily reversible without whipping out a soldering iron. This meant tinkering with the BIOS. I had never done it extensively, so I was also eager to dive-in and learn a bit about it.
Online you will find a lot of references, ALL of them deal with turning a Geforce into a Quadro. And it makes lots of sense, if you are using contemporary hardware for work, you buy the cheap Geforce and turn it into the expensive Quadro! Indeed, I remember the first resistor mods appearing online for the Geforce and Geforce2 back in the day. The process is fairly well documented, just modify the so-called "straps" in the BIOS—or in hardware like with GF and GF2—and you're good. The reason for my write-up here is twofold: I want to document the process for a slightly older piece of hardware (although its basically the same), I want to encourage people in the retro community to rescue cheap, old Quadros and use them for retro-gaming!
The nouveau project has reverse engineered and documented all we need to touch for this little operation. In particular, the info we need on the straps can be found HERE. Throughout the whole process I used nvflash 18.104.22.168 and nvflash for windows 5.118
So, let's get our hands dirty!
0. A bit of theory first
The OS decides the identity of a card by looking at the card's BIOS and reading the DeviceID, so to have a Quadro FX 1000 recognized as a Geforce FX 5800 Ultra we must change its DeviceID. At the same time, the BIOS confirms the DeviceID on bootup depending on the configuration of the straps. Attempting to modify the DeviceID in the BIOS with a program like NiBiTor will not change the value of the straps, and will result in an identity crisis for the card: while the BIOS says its a GeForce, the straps are telling it its a Quadro. The card will not initialize properly on bootup and we'll get no video. To properly change the DeviceID we need to modify the BIOS and the straps.
On NV3x based cards there are 2 sets of straps, Strap0 and Strap1; each with 3 levels, Primary or Hardware (the resistors found physically on the card), Select or AND (this is a software strap embedded in the BIOS, the values specified here perform a bitwise AND on the Primary straps), and Secondary or OR (also a software strap embedded in the BIOS, the values of this strap perform a bitwise OR on the result of Primary AND Select).
So, the gist of it is the straps can be changed either in hardware, by moving resistors around; or in software, by adjusting the AND / OR straps in the BIOS. The approaches are IDENTICAL in result. In my opinion, modifying the software straps has 1 advantage: it can be reversed immediately without having to move resistors back to their original position.
So, the process to change the DeviceID is;
- modify the card's original BIOS with NiBiTor changing the DeviceID (and any other thing you want like clocks, voltages, etc). This change will not affect the strap values embedded in the BIOS. If you stop here, you will get no video upon reboot.
- "Calculate" new software straps and flash them into the BIOS. This is equivalent to moving the resistors on the PCB.
Once these steps are done, the BIOS in the card will be "strapped". Backing this up is recommended! Flashing the original BIOS or the strapped BIOS into the card can be done at any time, the card will work immediately, the only difference being the DeviceID (and any other change you did like clocks, voltages, etc).
1. Compare DeviceID
The DeviceIDs of the cards in question can be read directly from the nvidia drivers: just open up the nv4_disp.inf and search for the cards. In my case I need the following values (they are in hexadecimal, I have translated them into binary)
0309 = 00 00 00 11 00 00 10 01 (Quadro FX 1000)
0301 = 00 00 00 11 00 00 00 01 (GF FX 5800U)
DeviceID bit: 32 10
Notice that the only difference is in the final 4 bits, in particular, the difference is in DeviceID we need to convert a 1 into a 0.
2. Read straps from the ROM
According to the documentation, the software straps Strap0-AND, Strap0-OR, Strap1-AND, and Strap1-OR can be found in the locations 0x58, 0x5c, 0x60, 0x64 of the ROM image. We can read them with any hex editor. I read them directly with nvflash with the command nvflash --display 112, the last 2 lines displayed are the relevant ones;
0050: E9 8F 7A 00 DE 10 82 01 FF FF FF 7F 00 00 00 00
0060: FF FF FF 7F 00 00 00 80 22 00 A5 C1 E9 B4 16 E9
And of those lines, only a few bytes are of our interest. In the 2nd half of line 0050, the first 4 bytes represent Strap0-AND, the following represent Strap0-OR. In line 0060 the first 4 bytes represent Strap1-AND, the following 4 bytes are Strap1-OR. The order is little-endian, so we must rewrite them to work with them;
Strap0-AND: 7F FF FF FF
Strap0-OR: 00 00 00 00
Strap1-AND: 7F FF FF FF
Strap1-OR: 80 00 00 00
The NV30 chip used in both the Quadro FX 1000 and the Geforce FX 5800 Ultra has a total of 4 bits to set DeviceId, all of which are located in Strap0: Strap0[12,13] correspond to DeviceID[0,1], and Strap0[20,21] correspond to DeviceID[2,3]. so we only need to work with Strap0, but we must translate it from hexadecimal into binary;
DeviceID bits: xxxx xxxx xx32 xxxx xx10 xxxx xxxx xxxx
Strap0-AND (hex) : 7F FF FF FF
Strap0-AND (bin) : 0111 1111 1111 1111 1111 1111 1111 1111
Strap0-OR (hex) : 00 00 00 00
Strap0-OR (bin) : 0000 0000 0000 0000 0000 0000 0000 0000
How to read this table? The top line has the DeviceID bits in their respective positions in Strap0: DeviceID[0,1] in positions Strap0[12,13], and DeviceID[2,3] in positions Strap0[20,21]. Below each hexadecimal value I have translated into binary: 7F corresponds to 0111 1111, for example.
3. Calculate the new straps
Note that for the DeviceID bits the values in the Strap0-AND are all 1, and the values in the Strap0-OR are all 0: these are just a passthru for the Hardware straps (the resistors in the card). For example the Quadro FX 1000;
HW Strap : 1001 (DeviceID set by resistors)
Strap0-AND : 1111 (AND)
Results in : 1001 (result of bitwise AND)
Strap0-OR : 0000 (OR)
Results in : 1001 (result of bitwise OR, and effective DeviceID)
To have the card recognized as a 5800U we need the final result to be 0001. We have 2 possibilities to achieve this:
- Set all bits in the Strap0-AND to 0, effectively setting all values to 0, and then use Strap0-OR to set 0001;
- Set only bit  in Strap0-AND to 0, and leave Strap0-OR untouched.
I chose the 2nd approach, which would look like this when we look at the complete Strap0;
DeviceID bits : xxxx xxxx xx32 xxxx xx10 xxxx xxxx xxxx
Old Strap0-AND (hex) : 7F FF FF FF
Old Strap0-AND (bin) : 0111 1111 1111 1111 1111 1111 1111 1111
New Strap0-AND (bin) : 0111 1111 1101 1111 1111 1111 1111 1111
New Strap0-AND (hex) : 7F DF FF FF
Old Strap0-OR (hex) : 00 00 00 00
New Strap0-OR (hex) : 00 00 00 00
So, after all this, our set of 4 straps representing Strap0-AND, Strap0-OR, Strap1-AND, and Strap0-OR are respectively 0x7FDFFFFF, 0x00000000, 0x7FFFFFFF, and 0x80000000. We only had to change 1 bit!
Hard part's over.
Hard part's over, but now begins the dangerous part. If you intend to follow this "guide" then, before flashing anything...
MAKE A BACKUP OF YOUR BIOS!
MAKE A RECOVERY FLOPPY / CD THAT RUNS nvflash AUTOMATICALLY AND FLASHES THE BIOS BACK!
This part is done in NiBiTor. I opened up my backup of the BIOS and looked around, decided to change the following parts;
- I added a second performance level, to differentiate 2D from 3D. Set the 3D at 500 / 500
- Changed the Device ID and Sub System ID to a GeForce FX 5800 Ultra (changing the Sub System ID is not necessary, I did it to match a 5800U bios I found online)
- In the Voltage table editor there were, curiously, 2 active entries. I say curiously because the BIOS was configured for 3D only, so I have no clue when it would use the 1st voltage entry. I just changed the VID of the 2nd entry to 7 instead of 5, this will give the card 1.5 V instead of 1.3 V when it goes into 3D mode.
- Changed the bootup message to display QuForce FX 5800 Ultra 🤣
With all those changes made, I saved the ROM as NV30_qf5800u.rom and flashed it. Since I have no other nvidia card in my system I didn't bother setting the index parameter,
nvflash -j -5 -6 NV30_qf5800u.rom
After this step, if you check the strap values, they are unchanged from the original BIOS. Run again nvflash --display 112 and see the strap lines
0050: E9 8F 7A 00 DE 10 82 01 FF FF FF 7F 00 00 00 00
0060: FF FF FF 7F 00 00 00 80 22 00 A5 C1 E9 B4 16 E9
Before rebooting, I flashed the new software straps calculated in this post,
nvflash --straps 0x7FDFFFFF 0x00000000 0x7FFFFFFF 0x00000000
The last one, Strap1-OR, should be 0x80000000, but apparently the leftmost bit cannot be touched, so nvflash does it by itself: if you just put 0x00000000 you will get 0x80000000. Don't know why. Indeed, when I check the straps to check they have been flashed properly, I see the following
0050: E9 8F 7A 00 DE 10 81 01 FF FF DF 7F 00 00 00 00
0060: FF FF FF 7F 00 00 00 80 22 00 A5 E1 E9 B4 16 E9
The difference between 82 and 81 in line 0050 is the SubSystem ID we changed in NiBiTor, the difference between C1 and E1 in line 0060 is a checksum calculated by nvflash when flashing the straps (you will also get it if you only flash the straps without doing any other change at all), and the 80 of Strap1-OR is there even though we told nvflash 0x00000000.
All good, its done! Uninstall drivers, reboot, reinstall drivers…
So, after all this I have the original BIOS and a strapped BIOS, which will allow me to change the identity of the card with a single command and a reboot. Later I'll describe the necessary cooling mods to keep it at a manageable temperature when running in 3D.
EDIT: formatting, added TL;DR