kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Jul 17, 2022 10:42:57 GMT -5
The approach of manually pairing all of the assets to their textures seems to be working. There are two aspects that I need to address. The first being multiple textures for the same asset. This seems to happen with reaverbots, and the game doesn't have any obvious mechanism for how these are paired. As the reaverbots only seem to popup in one archive or two, and the textures seem to be the same.
- Golbesh (silver gold) - Horroko has like 4 versions in this game. - Fingerii (i think) - Mirumijee
The second is checking for possible variations in animations. Which I'm probably going to have to do later anyways. So it's not something I need to make a mental note of to actually go back and do.
Right now the problem with manually porting all of the characters into a list means that the operation gets repetitive pretty fast. Luckily it doesn't take too long to add a new entry, and MML2 doesn't have a super massive library of characters and enemies. Which means that i'm kind of tempted to be looking into something else as I'm porting everything else over.
I think the obvious next step is to start looking at what I think are the boss enemies, which have a different EBD header which is not a list of entities. I haven't actually looked at the file yet. But basing on the fact that these files don't parse that would be my best guest. That being said it's probably time to start cracking these open to see what's in there.
Looks like there are weird EBD files found in the following locations:
ST5C01.BIN ST3C02.BIN ST5201.BIN ST3A02.BIN ST1803.BIN ST1700.BIN ST1801.BIN ST1702.BIN ST1C01.BIN ST2801.BIN ST4B02.BIN ST4B01.BIN ST1401.BIN ST1201.BIN ST2501.BIN ST2802.BIN
I guess one is good as any. We'll take a look at ST5C01.BIN and go from there.
Quick look at the header.
000000000: 0a000000 48470100 29000000 00000000 ....HG..)....... 000000010: 00000000 00000000 00000000 00000000 ................ 000000020: 00000000 00000000 00000000 00000000 ................
Nothing too special here. Magic number is 0x0A for entity (theoretically). File length is 0x014748, which isn't small, but not huge either. Not sure what the average length for this file is on the other grouped model types. And 0x29. Not sure what this is doing. Might be something that I have to so a scan through all of the data to look to see if this has a meaning for where and how it's used. For right now I'm just going to skip over it and see if the file itself has any hints to work with.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Aug 14, 2022 10:29:48 GMT -5
Looks like i need to hold off on getting too excited and jumping into a new data format. I'm going to take a second to make sure I have a handle on the existing .EBD models, and then figure out what to move into next. As far as .EBD files go, I'm running into a few issues.
0x40 - vertice joining on Pajama roll's model 0x02 - armature flag 0x01 - armature flag
0x002320 reporter missing texture 0x002520 cameraman missing texture
animations are missing root bone position animations don't look like have the y = -y axis change applied properly
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Dec 28, 2022 11:03:15 GMT -5
I guess it's been a few months since posting here. I've been poking around at a few different locations in the game. Most of my attention has been fixed on getting the file versions of the .EBD entities. Taking the time to match up the textures with the correct meshes is taking a while. I'm tempted to go with another save state viewer. It seems like the easiest option which provides the largest effect. I think I can provide some quality of life improvements. Mainly the ability to load and store more than one save state at a time to be able to switch between them.
This is what I have mapped out of the game's memory. Megaman's mesh is at 0x110800, Entities are at 0x124800, and Map Tiles are at 0x154800. And the textures for what's important should be loaded into vram. With the technical limitation that the vram isn't able to hold all of the scene's textures at once. So only a portion of the tiles and entities will have the correct texture loaded in for any given save state. What that does mean is that if you snap something that is correct in game, it should be correct in the save state. Not including unloaded stages or entities.
Before I jump into that I'm going to get started with the player mesh and dig into that. These files are effectively exactly the same in file and in memory. So there's no change. But I want to go ahead and drill down and try to document as much as I can with respect to these files before moving on.
Attachments:
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Dec 30, 2022 10:11:10 GMT -5
I'm going to shift my attention to the Megaman model in the COMMON folder. Which contains the following files:
- PL00P000.BIN - PL00P001.BIN - PL00P002.BIN - PL00P003.BIN - PL00P004.BIN - PL00P005.BIN - PL00P010.BIN - PL00P011.BIN - PL00P012.BIN - PL00P013.BIN - PL00P014.BIN - PL00P015.BIN - PL00R01.BIN - PL00R02.BIN - PL00R03.BIN - PL00R04.BIN - PL00R05.BIN - PL00R06.BIN - PL00R07.BIN - PL00R08.BIN - PL00R09.BIN - PL00R0A.BIN - PL00R0B.BIN - PL00R0C.BIN - PL00R0D.BIN - PL00R0E.BIN - PL00R0F.BIN - PL00R10.BIN - PL00T.BIN - PL00T2.BIN - PL01P000.BIN - PL01T.BIN - PL02P000.BIN - PL02T.BIN - PL03P000.BIN - PL03T.BIN - PL04P000.BIN - PL04T.BIN - PL05P000.BIN - PL05T.BIN - PL06P000.BIN - PL06T.BIN - PL07P000.BIN - PL07T.BIN
The way I think this is going to break down is that PL00P000.BIN through PL00P015.BIN are likely going to be body parts. Which one mesh for each limb included in the file. And PL00R01.BIN through PL00R10.BIN are probably the special weapons. First, I think I should try and scan the files to extract all of the textures to give me a sense of grounding to use as a reference for working with the other files.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Jul 30, 2023 23:28:05 GMT -5
Going to start breaking down the COMMON folder. We have the following files that I want to start breaking down and looking into: - PL00P000.BIN - PL00P001.BIN - PL00P002.BIN - PL00P003.BIN - PL00P004.BIN - PL00P005.BIN - PL00P010.BIN - PL00P011.BIN - PL00P012.BIN - PL00P013.BIN - PL00P014.BIN - PL00P015.BIN What's interesting about these files is there are all the same length, and all seem to get copied into the same area of memory. But since that area of memory is where the Megaman player character, this could indicate you could play as other character. I think the approach to take for this will be to start a new game, passed the tutorial and then make a save state. From there we can start splicing in different files and see what the result is. After some testing, it looks like the files were more innocent than I might have hoped. Each of the files is a different version of Megaman with different shoes. This makes it easier to sketch out what the files are for. Red is the megaman player model. Green is the specical weapons, cyan is the high poly other character. Going to need to start breaking down the contents of more of these file types.
A few more notes for the player model, it looks like all of the files are the same length. Inside each of the bin archives, there are three individual files that copoed into memory.
File 1
Archive Offset: 0x0 Memory Offset: 0x110800 File Length: 0x2b40
File 2
Archive Offset: 0x3000 Memory Offset: 0x113a00 File Length: 0xe420
File 3
Archive Offset: 0x11800 Memory Offset: 0x123000 File Length: 0x 16b0
There's somewhat of a limited scope to work with here, which is somewhat encouraging. I think it would be interesting to compare PL00P000.BIN to PL00P010.BIN as the only change I would expect to be there is the helmet versus the hair in the mesh. Other minor changes might be interesting here. Also since we only have three files with lengths and offsets in memory we can comment out or change these in memory to see what the effect is to see if they're worth mapping out.
I think that before going deep, I want to keep scoping out the horizontal to get a better idea of what files are in the COMMON folder. Next I want to look at the special weapon files to get an idea of what's going on there.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Jul 31, 2023 15:00:39 GMT -5
The next thing that I want to look at is the special weapon files. Before I dive into the overall structure I mostly want to see what the length of the first file in the archive is, how large it is, and where it get's copied into memory.
Reading : PL00R01.BIN Memory: 0x10d000 Length: 0x56c
Reading : PL00R02.BIN Memory: 0x10a000 Length: 0x1e34
Reading : PL00R03.BIN Memory: 0x10a000 Length: 0x1800
Reading : PL00R04.BIN Memory: 0x10a000 Length: 0xbf4
Reading : PL00R05.BIN Memory: 0x10a000 Length: 0x754
Reading : PL00R06.BIN Memory: 0x10a000 Length: 0x900
Reading : PL00R07.BIN Memory: 0x10a000 Length: 0xef0
Reading : PL00R08.BIN Memory: 0x10a000 Length: 0xd28
Reading : PL00R09.BIN Memory: 0x10a000 Length: 0x1b18
Reading : PL00R0A.BIN Memory: 0x10a000 Length: 0x14c0
Reading : PL00R0B.BIN Memory: 0x10a000 Length: 0x1f14
Reading : PL00R0C.BIN Memory: 0x10a000 Length: 0x1f10
Reading : PL00R0D.BIN Memory: 0x10a000 Length: 0xfc0
Reading : PL00R0E.BIN Memory: 0x10a000 Length: 0x12a4
Reading : PL00R0F.BIN Memory: 0x10a000 Length: 0x11d0
Reading : PL00R10.BIN Memory: 0x10a000 Length: 0xbfc
The interesting thing here is that PL00R01.BIN gets copied into 0x10d000, where as everything else gets copied into 0x10a000. I think that would indicate that PL00R01.BIN is the unequiped right arm, and then there are 15 special weapons that get copied into 0x10a000, meaning there can only be one special weapon in memory at a time.
The other interesting aspect here is the file length is different depending on the archive. Normally this isn't interesting, but all of the player model files were the same length, so the same restriction doesn't apply here. The main reason to keep this in mind is that when iterating over the file, I'll have to keep track of the offset and jump to the next multiple of 0x400 to read the next file. The next thing I want to know is how many files are in each archive, is the number of files consistent, and where do they get copied into memory?
For PL00R02.BIN we can go the old-fashion way and scan though the archive: (start offset, ignoring length)
File 1: 0x0000 File 2: 0x2000 File 3: 0x2800 File 4: 0x3800 File 5: 0x4000 File 6: 0x4800
For PL00R03.BIN we can look through it too: (start offset, ignoring length)
File 1: 0x0000 File 2: 0x2000 File 3: 0x2800 File 4: 0x3800 File 5: 0x4000 File 6: 0x4800
In this case the files matched up pretty closely. My hypothesis is the first file has the most length variability. Since the length is rounded to the nearest multiple of 0x800 before the start of the next file, that means the second file will likely start at 0x800, 0x1800, or 0x2000, depending on the size of the first file. From there, my hypothesis is that the lengths of the files after the first one would be pretty consistent.
Another aspect I want to poke at here is, I thought it might be easier to try and figure out which special weapon is equipped to start tracking down the file, but since everything is copied into 0x10a000, that means I could probably go there and start messing around to see what the effects would be. Once I have an idea of how that changes, I can probably go back to make a list of which file is what weapon.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Aug 1, 2023 16:13:24 GMT -5
Doing another pass on the Special weapons.
The first weapon is PL00R01.BIN which I think is the Lifter Arm. In Legends 2, they let you equip or unequip a single special weapon at any time. So the lifter arm is always copied into memory. There are four internal files in this archive. Offset 0x0 Memory: 0x10d000 Length: 0x56c
Offset 0x800 Memory: 0x116240 Length: 0x39c
Offset 0x1000 Memory: 0x124000 Length: 0xb88
Offset 0x2000 Memory: 0x128400 Length: 0xc8
PL00R02.BIN, PL00R03.BIN, PL00R04.BIN, PL00R05.BIN, PL00R06.BIN, PL00R07.BIN, PL00R08.BIN, PL00R09.BIN, PL00R0A.BIN, PL00R0B.BIN, PL00R0C.BIN, PL00R0D.BIN, PL00R0E.BIN, PL00R0F.BIN are all similar with a few minor differences.
They all have four files that get copied into 0x10a000, 0x113340, 0x121e20 and 0x1246b0. Each of these seems to have some kind of max length since the game is pretty tight on what gets copied into memory where. The lengths don't matter as much as the functionality.
I think the mesh and animation get copied in. Maybe something for the behavior or projectile? I'd need to copy parts, or comment out parts to see what changes for each of the sections. And finally there are two files that do not get copied into memory directly. These might be sound files that get copied into audio memory.
Offset 0x0 Memory: 0x10a000 Length > 0x800 && Length < 0x1800
Memory: 0x113340 Length: < 0x800
Memory: 0x121e20 Length: 0xb88 || 0x1188
Memory: 0x1246b0 Length: 0xc8 || 0x128
Memory: 0xf000c0(?) Length: 0x80
Memory: 0xd0003(?) Length> 0x4000 && length < 0x4800
It might be worth figuring out which of the files in the archive is the mesh to have a very narrow target for what the struct for the faces is. The format used here looks to be simpler than the one used for the entities, but it's better to have something to test a hypothesis if needed as opposed to going straight from a file. But I'll probably take a look at the file to see what I can guess from what's there.
I guess the next two steps look something like this: 1. Look at the character model files 2. Figure out the mesh offset, figure out a single special weapon to look at, start narrowing down the format
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Sept 26, 2023 23:16:13 GMT -5
I wish I could stop getting b**** slapped by reality long enough to make any progress. Back to mapping out the common folder. We have the following files in the COMMON folder which break down into a few groups. Player Mesh
- PL00P000.BIN
- PL00P001.BIN
- PL00P002.BIN
- PL00P003.BIN
- PL00P004.BIN
- PL00P005.BIN
- PL00P010.BIN
- PL00P011.BIN
- PL00P012.BIN
- PL00P013.BIN
- PL00P014.BIN
- PL00P015.BIN
Special Weapons - PL00R01.BIN
- PL00R02.BIN
- PL00R03.BIN
- PL00R04.BIN
- PL00R05.BIN
- PL00R06.BIN
- PL00R07.BIN
- PL00R08.BIN
- PL00R09.BIN
- PL00R0A.BIN
- PL00R0B.BIN
- PL00R0C.BIN
- PL00R0D.BIN
- PL00R0E.BIN
- PL00R0F.BIN
- PL00R10.BIN
Texture Files High Poly Mesh - PL01P000.BIN
- PL01T.BIN
- PL02P000.BIN
- PL02T.BIN
- PL03P000.BIN
- PL03T.BIN
- PL04P000.BIN
- PL04T.BIN
- PL05P000.BIN
- PL05T.BIN
- PL06P000.BIN
- PL06T.BIN
- PL07P000.BIN
- PL07T.BIN
Random Files - DEMO.BIN
- GAME.BIN
- G_OVER00.BIN
- G_OVER01.BIN
- G_OVER02.BIN
- INIT.BIN
- LOGO.BIN
I want to make these files easier to work with on the command line without having to make a tool around them. I think that means for the texture files that I want to be able to quickly dump the png. For the mesh files I want to be able to dump the model as an obj for viewing. And then I need to keep notes around which file contains what because the file names really don't help at all and coming back to them is completely jarring. Once I get better documentation for each file to get a better sense of what is where, I can make a more detailed map of the contents of each of the files to know specifically what is at each offset.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Dec 22, 2023 22:08:06 GMT -5
I guess I'll pick some thread to continue off of. Right now what I'm trying to do is replace Megaman with a different model to be able to play with a custom character from start to finish of the game. For the Playstation version what these means is replacing the following files: - COMMON/PL00P000.BIN
- COMMON/PL00P001.BIN
- COMMON/PL00P002.BIN
- COMMON/PL00P003.BIN
- COMMON/PL00P004.BIN
- COMMON/PL00P005.BIN
- COMMON/PL00P010.BIN
- COMMON/PL00P011.BIN
- COMMON/PL00P012.BIN
- COMMON/PL00P013.BIN
- COMMON/PL00P014.BIN
- COMMON/PL00P015.BIN
- COMMON/PL00T.BIN
And similarly for the PC version, this means replacing - COMMON/PL00P000.DAT
- COMMON/PL00P001.DAT
- COMMON/PL00P002.DAT
- COMMON/PL00P003.DAT
- COMMON/PL00P004.DAT
- COMMON/PL00P005.DAT
- COMMON/PL00P010.DAT
- COMMON/PL00P011.DAT
- COMMON/PL00P012.DAT
- COMMON/PL00P013.DAT
- COMMON/PL00P014.DAT
- COMMON/PL00P015.DAT
- COMMON/PL00T.DAT
This might look like a lot of files, but effectively it's two files. PL00P000 - PL00P015 are just the Megaman model with and without helmet, and with different kind of shoes. Most of the content of the files is completely the same. and PL00T is the texture. For the model format, they are effectively the same on both PSX and PC. The only difference is that COMMON/PL00T.BIN on PSX is compressed. And COMMON/PL00T.DAT is not. This is a fairly large hurdle for me, as I am okay with vertices and model formats, but I'm completely out of my element when it comes to compression and decompression. In terms of approach, I should be using the PC version as a place to start, it hasn't been working on my laptop, so I've been focusing on the PSX version. I should probably try finding another PC to install it on to be able to use it as a target to be able to separate concerns. The first concern of writing to the format for the proof of concept. And the second concern being to package the file for the PSX version. Focusing on the PSX version first has caused me to spend all of my time on the latter, since it is a requirement for the prior. In terms of compression, the PSX uses this function described in this thread by OmbraRD: mmls.proboards.com/post/97969. To describe it simply, the game uses a very simple compression format. The game uses a "bitfield" which is a series of 1's and 0's followed by a "bitbucket", which is the compressed content. The game reads the bitfield in order, and if it reads a 0, it will copy two bytes from the bitbuck as-is, otherwise if the game read's a 1, it will copy previous bytes that it's already seen. My attempt at writing the reverse for this is shown below: const bitfield: boolean[] = []; let windowOfs = 0; const WINDOW_LENGTH = 0x2000;
let ofs = 0; let outOfs = 0; const MAX_CAP = 7; const MIN_CAP = 2;
do {
if (ofs === decompressed.length) { compressed.writeUInt16LE(0xffff, outOfs); bitfield.push(true); outOfs += 2; break; }
if (ofs >= windowOfs + WINDOW_LENGTH) { console.log("Moving window up at: 0x%s", outOfs.toString(16)) compressed.writeUInt16LE(0xffff, outOfs); bitfield.push(true); outOfs += 2; windowOfs += WINDOW_LENGTH; }
let found = false; const wordsLeft = (ofs - windowOfs) / 2; const maxCount = wordsLeft < MAX_CAP ? wordsLeft : MAX_CAP;
// Check ahead
for (let count = maxCount; count >= MIN_CAP; count--) { const len = count * 2 const needle = decompressed.subarray(ofs, ofs + len) const window = decompressed.subarray(windowOfs, ofs); const needleOfs = window.indexOf(needle);
if (needleOfs !== -1) { found = true; const lowBits = count - 2; const highBits = needleOfs << 3 const word = highBits | lowBits; compressed.writeUInt16LE(word, outOfs); bitfield.push(true); outOfs += 2; ofs += len; break; } }
// If we don't find at least two words then we need // to just copy the existing word over
if (!found) { const word = decompressed.readUInt16LE(ofs); ofs += 2; bitfield.push(false); compressed.writeUInt16LE(word, outOfs); outOfs += 2; }
} while (ofs < decompressed.length)
This creates a compressed file that my decompress function is able to convert back the original bytes, but it seems to crash when actually used in game. In terms of the data being compressed, it's the 0x80 length palette, followed by 0x8000 length indexed image. It can be thought of any arbitrary bytes with length of 0x8080 being compressed and restored by this function. In order to keep the file size the same, 0x8080 bytes needs to be compressed down to a size of less than 0x3000 bytes to be able to fit in PL00t.BIN without changing the length. This is generally easy to do with image files which repeat a lot of the same indexes. In terms of alternative approaches, the PSX game also has PL00T2.BIN, which is the same content as PL00T.BIN, just decompressed and with padding added between the palette and indexed image. To avoid dealing with compression I've tried several approaches to try and trick the game into reading PL00T2.BIN when it wants to read PL00T.BIN in the hopes the devs are using a generic readFile interface instead of writing specialized code to get Megaman's texture (I wouldn't put it passed them). So far, the following approaches haven't worked: - Manually editing the file index in the .BIN (cd image) header to make PL00T reference PL00T2
- Renaming PL00T2 to PL00T in the CD image
- Swapping PL00T and PL00T2 in the the CD image
So far every approach seems to greet me with a crash screen right after the Capcom logo. The issue that I'm finding with editing the CD image. I think i'll poke around with compression. Some sanity checks that I still need to run are: - Editing the palettes for PL00T and PL00T2 to see which file is referenced when
- Replacing the Megaman texture with another already compressed texture
- Making a proof of concept texture that can use less or simple compression
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Dec 23, 2023 23:15:06 GMT -5
Adding a few more notes for compression. I tried to write another version of the decompression which is closer to the C code provided by OmbraRD. Javascript is kind of wonky with managing bits correctly, so I need to play around with it some more to get that working. Also there is a 2 byte value at 0x26 in the header which might be the word (2 bytes) length of the compressed payload. Which means that I also need to scan through the files and see if they follow a specific pattern that I haven't picked up on.
Thanks to Trege for re-introducing the idea of playing as Roll. With the gameshark code you can play as Roll. The way it needs to be activated is get to the Yosyonke launch pad and activate the code. You shouldn't see anything change yet, go into the Flutter. You should see texture errors and then leave the Flutter and you should be playing as Roll.
8008C252 00000602 E308C0CF 00000002 8008C252 0000FFFF
The background to what I think is happening is the game has a code for which version of Megaman is loaded in. By "version" i mean, helmet or no helmet and which shoes. All of these are different files in the game. So when you change equipment the game has a different number for which of the equipment is activated and the game will know to load that version of the model. The game also has other NPC's stored in the same format as the Megaman character, which were cut out of the final game. I think this means the devs left in the loading function but it's never triggered normally.
By setting the number higher than the intended version of Megaman, this will cause the game to load in a different character from the other models when the scene changes. This is why we need to go into and then leave the Flutter for it to work. I think there are still a few quirks like special weapons and stuff. What this means for me is that I only need to mod PL01T.BIN and PL01P000.BIN (model) keeping the files the same size and then replacing them in the CD image file.
The easiest place to start is going to be encoding the texture. Then we can move on to encoding the model, which we can take one segment at a time.
|
|
kion
Arukoitan
@kion_dgl
Posts: 193
|
Post by kion on Dec 24, 2023 1:13:29 GMT -5
We can start with images as the first thing to encode and observe if the game has changed successfully. Here is my hacked together code for encoding an image.
import { PNG } from 'pngjs'; import { readFileSync, writeFileSync } from 'fs'; import { createCanvas } from 'canvas'
// Read Source image to be encoded const pngSrc = readFileSync('Miku/miku_body.png'); const pngInfo = PNG.sync.read(pngSrc); const { width, height, data } = pngInfo;
// For some reason the type definition has palette as a boolean const palette = pngInfo.palette as unknown as number[][];
// Then we make sure transparency is the first 'color' palette.pop(); palette.unshift([0, 0, 0, 0])
// Then we create target buffers for paletter and image const pal = Buffer.alloc(0x20, 0) const image = Buffer.alloc(0x8000, 0)
// Encode the palette let palOfs = 0; for (let i = 0; i < palette.length; i++) { const r = (palette[i][0] >> 3) & 0x1f; const g = ((palette[i][1] >> 3) & 0x1f) << 5 const b = ((palette[i][2] >> 3) & 0x1f) << 10 const a = palette[i][3] === 0 ? 0 : 0x8000 const texel = r | g | b | a; pal.writeUInt16LE(texel, palOfs) palOfs += 2 }
// Encode the image let ofs = 0; let imageOfs = 0; const readPixel = () => {
const a = data.readUInt8(ofs + 3) === 0 ? 0 : 255; const r = a === 0 ? 0 : data.readUInt8(ofs + 0) const g = a === 0 ? 0 : data.readUInt8(ofs + 1) const b = a === 0 ? 0 : data.readUInt8(ofs + 2) console.log(r, g, b, a); ofs += 4
for (let i = 0; i < palette.length; i++) { const color = palette[i]; if (r !== color[0]) { continue; } if (g !== color[1]) { continue; } if (b !== color[2]) { continue; } if (a !== color[3]) { continue; }
return i; }
return 0; }
for (let y = 0; y < height; y++) { for (let x = 0; x < width; x += 2) { const lowByte = readPixel() const highByte = readPixel() const byte = ((highByte << 4) | lowByte) & 0xff image[imageOfs] = byte; imageOfs++; } }
This will depend on the image being encoded. In this case Xinus22 provided a png that was already a palette of 16 images. But for the body what we expect is an image with dimensions 256x256 and 16 colors where transparency is a color (if used). Technically this can be more colors. For the body, the game declares one palette and image together followed by an alternative palette. What this means is that when we encode the image with two separate palettes, we need to make sure the indexes match up for the body for each palette. It's not terribly complicated, but it makes sense to reduce complexity where we can on a proof of concept.
As for encoding we're basically just doing the reverse of decoding. We take the rgba values and encode them as rgba5551, and then we cycle through the image and make every pixel a reference back to the palette. Since each reference is a value between 0 and 15, this can be encoded with 4 bits. We shift and merge the bits so we have two 4 bit pixel values encoded per byte.
|
|