Big endian

Technical discussion for those interested in Supermodel development and Model 3 reverse engineering. Prospective contributors welcome.
Forum rules
Keep it classy!

  • No ROM requests or links.
  • Do not ask to be a play tester.
  • Do not ask about release dates.
  • No drama!

Big endian

Postby Arbee » Thu Oct 20, 2011 2:23 pm

As I mentioned elsewhere, I built SuperModel on my PowerMac, mostly out of morbid curiosity. It falls over immediately with the PowerPC hitting an unknown opcode. Any tips where to look to possibly make it work? I don't expect acceptable performance, but as a just-for-giggles thing it has some appeal :)
Arbee
 
Posts: 69
Joined: Sun Sep 25, 2011 6:41 pm

Re: Big endian

Postby Bart » Thu Oct 20, 2011 4:15 pm

For performance, Supermodel stores most RAM regions with each 32-bit word byte reversed, so an address a is accessed as:

UINT8 data = ram[a^3];
UINT16 data = *(UINT16 *) &ram[a^2];
UINT32 data = *(UINT32 *) &ram[a];

This is optimized for 32-bit accesses (which all PowerPC instruction fetches are).

The real mess is in the Model3/ subdirectory. In Model3.cpp, the RAM handlers would need to be modified. The three most confusing things are:

1. The use of FLIPENDIAN32(). The reason this exists is because some Model 3 devices (namely, the Real3D and tile generator) are actually little endian. Because the PowerPC is writing in big endian order, the game program takes care to manually reverse the bytes first. Well, when the PowerPC reversed it, Supermodel reversed it again, so it needs to be manually reversed one more time before being written into a little endian memory space (e.g. tile gen VRAM or Real3D RAM).

Now, the graphics engine reads these 32-bit values directly so, on a big endian system, I think you actually want to leave these macros intact. You don't want the values stored in little endian as the PPC intends because you'll be reading them back in a big-endian graphics engine, so they need to be swapped again. This actually works out kind of nicely.

It is the naked accesses (not wrapped by a macro) to memory regions in Model3.cpp that have to be corrected, and you basically just have to drop the ^3 and ^2 for UINT8 and UINT16. Everything else will work fine. You will have to comment out the function that byte-reverses the ROM regions. The ROM loader loads ROMs in their native layout and then Reverse32() in Model3.cpp adjusts them. You would comment that out.

Something similar happens for 68K ROMs. For starters, I would recommend disabling all sound board emulation to make life more manageable.

2. MPC10x.cpp is kind of a nightmare. I didn't think very hard about these issues before I went ahead and implemented it. The problem is that the register file can be accessed in different sizes. The device is always kept in big endian mode, so it's probably an easy fix.

3. PCI.cpp (which is coupled to CMPC10x) is a serious mess. I did not handle different-sized accesses elegantly. But it may be endian neutral as a result. It's really kind of a nasty hack. Devices attach PCI callbacks to the CPCI object and then listen for commands. The problem is that I just pass the address and access size and devices have to figure out what part of what command word is actually being accessed. I _think_ it should be endian neutral.


Did that make sense? I can give you more details if you're confused later this evening. This could definitely be done in a more elegant fashion, namely by wrapping up all accesses in one of two kinds of macros: same endian access, different endian access (for when the PPC writes to a little endian region).


As far as I know, the DMA (Model3/Real3D.cpp) and SCSI DMA (Model3/53C810.cpp) should be endian neutral as well...
User avatar
Bart
Site Admin
 
Posts: 3086
Joined: Thu Sep 01, 2011 2:13 pm
Location: Reno, Nevada


Return to The Dark Room

Who is online

Users browsing this forum: No registered users and 1 guest