This function is nothing but a PITA. It's not part of any vtable, nor any class, and it is called primarily in MxBitmap virtual functions. Additionally, there are local vars with no relation to the parameters. However, in the DLL, this function is placed after the last MxBitmap vtable function (which I named CopyColorData), and I can try to use those functions to figure out what is going on.. # Initial look ![](https://hackmd.io/_uploads/BkTUr77o3.png) So immediately I noticed that param_2 was likely an MxPalette, which I can look at later, but then also that there are some entries, which point to local_414, and then are later used in a loop which is definitely related to a palette entry. Basically, there is definitely MxPalette and PALETTEENTRY relationship here, and probably there's some weird function hiding. Also, the offsets of the functions are really weird, like `LEA EAX=>local_828,[EBP+0xfffff7dc]` but these area after calls to MxPalette functions. # First parameter - Call trees from other MxBitmap vtable functions This is vtable1c at 100bcaa0 in MxBitmap. It's call to 100bd450 is: ```iVar2 = FUN_100bd450(*(int *)((int)this + 0x10),param_3);``` So it's possible the first parameter is just an MxBitmap. If anything, very likely because FUN_100bd280 (vtable38 at 100bd280) is: ```FUN_100bd450(*(int *)((int)this + 0x10),param_1);``` So that's good for knowing our first parameter, MxBitmap.. sort of. The only helpful usage of it becomes: ```pBVar2 = (BYTE *)((int)&param_1->vtable + 2);``` This actually makes sense, because in those aforementioned functions it's passing a *member*, `RGBQUAD* m_paletteData` at 0x10. Setting our first parameter to RGBQUAD* we get an actually likely result from Ghidra! ![](https://hackmd.io/_uploads/BkHvvXmjn.png) To be fair, this stil looks weird, and I'm too lazy to rename the variable again and retake the screenshot, but `pBVar2` is assigned to the red field in the palette entry, which will come in helpful later with the loop. I'm going to predict it's some memcpy, but I'm not going to put my finger on it yet. ![](https://hackmd.io/_uploads/rknswQQjh.png) # Second parameter - clearly a MxPalette The only real context we have is those other MxBitmap vtable functions, which as of writing, we have no idea what that type it is trying to pass is - currently, we have it as a void* in 100bd280 and, a MxPalette from 100bcaa0. And the way how the entries are grabbed from the parameter here gives us more safety in ensuring the second param is a MxPalette. Once we set `param_2` to the tpye of MxPalette*, what *we know* falls into place. ![](https://hackmd.io/_uploads/HJ3DOQmin.png) At least, sort of? # Local variables ## local_828 This is specifically a MxPalette struct - not a pointer, just a plain `MxPalette`. It also is literally never used elsewhere, only for the purpose of being there so, probably to allow Ghidra to have a reason in its psuedocode for it to be initialized in there, that's my guess. ## local_414 Is an array of PALETTEENTRY's, where is only referred to in `pPVar3`, which is then used in the loop. ![](https://hackmd.io/_uploads/SJDUY77j3.png) So therefore, the loop is probably just iterating over every single `PALETTEENTRY` and doing.. something to it. Again, it's probably a memcpy. ## local_14 This is what actually gets returned, which seems like nothing after the loop, but since the loop updates while `pPVar4 < &local_14`, and then `pPVar3 = pPVar4` and `pPVar3 = local_414`, it does eventually, lead us to a single PALETTEENTRY. But, by itself, these local variables and this returning one isn't really initialized. It's data is all set to `\0`. ![](https://hackmd.io/_uploads/Hkb9cmXih.png) # So here's what I *think* is going on. (attempt #1/???) At a simpler level: - The function takes in a RGBQUAD* and a MxPalette. - If the MxPalette provided exists, it initializes it and grabs its entries. - Values of the RGBQUAD provided, at least the rgbRed is copied to other parts of the locally intialized palette. - Once its all done, it spits back, pretty much a NULL PALETTEENTRY. My immediate thought is: # What the heck is it returning and why? 100bd280 doesn't tell us, but 100bcaa0 does. ![](https://hackmd.io/_uploads/r1JeiXQjh.png) It's probably some hacky way of returning something to show that there was a result. By default, if the palette given to 100bd450 is NULL, the returning palette will have already been given `0xff` (and then it goes to the return, it doesn't do the loop.) `iVar4` is essentially the result of FUN_100bcaa0. So what's at MxBitmap `vtable+0x3c` that passes, to our knowledge an integer? ![](https://hackmd.io/_uploads/HJa5oXmo2.png) ## MxBitmap::vtable3c It actually takes a MxBool as a parameter, according to the current decomp headers, but it's literally another vtable function that *also* calls 100bd450. I fed Ghidra the proper information and got this: ![](https://hackmd.io/_uploads/SJG-3Qmjn.png) MxBitmap's field_0x18, appears to be a boolean as to whether color information in its BITMAPINFOHEADER was provided. What happens here to information we are looking for related to 100bd450 is at the mercy of the parameter passed to vtable1c, but basically, if the information provided was not the same as the boolean called, it checks to see if the parameter given is true, otherwise destroying the MxPalette member of MxBitmap. Then it tries to create a MxPalette using the constructor given a Bitmap Palette. Then it does some other operations I'm not going to deal with. ## So what is 100bd450's return? Probably some hacky way of a boolean showing whether the operation returned a success or not? Maybe it's an override or just a Mindscape developer being lazy, but regardless, it spits out an empty PALETTEENTRY if the operation was successful (maybe as a way of freeing memory?), and if it wasn't successful it returns values of `0xff`, which happens to be white! And I *believe* 0xffffffff is basically just `1`, indicating a failure. One more thing I want to do, and that is try to understand the loop. # The loop I know do while is rare in Java, and with that knowledge I highly doubt the original developers actually did this with C++ code. So here's the loop: ```cpp= pBVar2 = &p_rgbquad->rgbRed; pPVar3 = local_414; do { pPVar4 = pPVar3 + 1; *pBVar2 = pPVar3->peRed; pBVar2[-1] = pPVar3->peGreen; ((RGBQUAD *)(pBVar2 + -2))->rgbBlue = pPVar3->peBlue; pBVar2[1] = '\0'; pBVar2 = pBVar2 + 4; pPVar3 = pPVar4; } while (pPVar4 < &ret); ``` And here's me trying to dissect it: 1) The loop occurs each time the `PALETTEENTRY` pPVar4 is less than the returning PALETTEENTRY, therefore I'm going to assume this loop happens for every entry in the PALETTEENTRY index - again, since pPVar4 = pPVar3, which is the locally intialized MxPalette, we can assume this is probably some memcpy function. 2) During the loop, it takes the current, if not next entry in the MxPalette's entries, and: 3) Sets the local palette's (entry?) red value to the same as what is in the RGBQUAD* given into 100bd450. 4) The last element in the index of pBVar2 (which means for sure pBVar2 is a PALETTEENTRY, the fields make sense), which is pointing to, I guess the palette's last entry's flags to the value given of the locally intiialized palette's green? - Understanding this loop is another reason I tried to write out my attempt at understanding this. - I tried seeing what the reality is if pBVar2 was an RGBQUAD, which Ghidra suggested, and I guess would make sense with the way it sets it's rgbBlue to the palette's blue, but then looks for a .rgbReserved flag and set sit to the value of a green entry? Regardless, a value is being copied. Assuming the developers used common sense, I'll just assume and say: 5) not wasting my time: It's basically copying the values in the RGBQUAD to the local palette. This kind of feels weird until I remember that probably something like this could be done: ```cpp MxPalette* my_palette; RGBQUAD* my_quad = FunctionThatGivesMeMyRGBQUAD(); FUN_100bd450(my_quad, my_palette); // Some way of assering that the values in my_palette's entries are the same as the RGBQUAD's. ``` # Finalized reversing: My thoughts are confirmed by the assembly, especially with the local variables. For example, the retunring palette is definitely initialized to white as a local placeholder. In the asm its 0xffffffff. Just a way of showing how amazing Ghidra is! ![](https://hackmd.io/_uploads/HyFyWVXoh.png) I don't think this function has a real namespace, it's more a global function, just there so easily it can be used across both MxBitmap, MxPalette, and so on. Considering w/ current docs I can't find any functions with something like this, converting some RGBQUAD to a palette, I'm going to assume this is for LEGO Island. However, reading through DirectX Complete (1998) by Michael Root and James Boer, there is an example in Chapter 6 (Working With Palettes) on creating a palette with a Dib, where an RGBQUAD is used as a way of pointing to a color table and then creating a palette from it. In this section, it talks about working with palettes in windowed mode, and since Windows apparently forces apps in windowed mode not to use all 256 colors, the example provided that appears to be similar to 100bd450 creates a palette for windowed mode. It also returns a BOOL, so I do think the return type is just a hacky way of being a boolean. # Conclusion So yeah, this entire mess, is just either programmed weirdly, or the compiler produced it in a confusing way for Ghidra. But the purpose of this function is legit, importing a color table into a MxPalette. This function is used by most of the vtable function members of MxBitmap, so this is a really helpful boost in progress. In some ways, I thought about this function the wrong way, but looking at a different view really helped. I did consider if the return was just an integer. I did set `ret`/local_14 to an integer which cleaned up the psuedocode a LOT but with the loop, I'm not so sure: ![](https://hackmd.io/_uploads/SJJoSNmo2.png) <- the idea of counting your loop with your return variable is pretty weird, unless this is a memcmp (which this probably is)