Optiroc / SuperFamiconv

Flexible and composable tile graphics converter supporting Super Nintendo, Game Boy, Game Boy Color, Game Boy Advance, Mega Drive, PC Engine and WonderSwan formats.
MIT License
143 stars 20 forks source link

Question about generating 32x32 sprites for the PCE #48

Open zanto1 opened 2 months ago

zanto1 commented 2 months ago

I'm trying out this tool to convert a 32x32 png file to a sprite I can load into my PCE game. The problem is that I'm getting the result on the right when the image on the right is the correct one (ignore the palette difference between the two images)

image

This is the command I'm running. What am I doing wrong? .\superfamiconv.exe -i 04.png -t 04-conv.bin -p 04.palette -M pce_sprite -v

jbrandwood commented 2 months ago

Just dropping in to add an unwanted comment ...

Are you sure that you're obeying the HuC6270 VDC's limit on sprite placement in VRAM, because that result sure looks a lot like what you get when you misalign sprites in VRAM!

The VDC sees contiguous VRAM as a bunch of 32x64 sprites (on 512 word boundaries), and you MUST align any sprites larger than 16x16 within those areas; so a 32x32 sprite must be loaded on a 256 word boundary (i.e. VRAM $xx00).

This gets super confusing when you are using 16x32 sprites because the top and bottom halves are seperated in memory!

This is because the VDC builds sprites larger than 16x16 by flipping VRAM address bits directly rather than adding an offset from a base location (which the Genesis and SNES do IIRC).

est77 commented 2 months ago

I think that there is a bug when generating PCE sprites. They are horizontally flipped iirc. I found this diff in a Superfamiconv fork (I cannot seem to find which one) that seems to fix the issue for me (I didn't test it a lot).

diff --git a/src/Mode.h b/src/Mode.h
index 9d46454..bbe1616 100644
--- a/src/Mode.h
+++ b/src/Mode.h
@@ -748,7 +748,18 @@ inline byte_vec_t pack_native_tile(const index_vec_t& data, Mode mode, unsigned

   } else if (mode == Mode::pce_sprite) {
     for (unsigned p = 0; p < 4; ++p) {
-      auto plane = make_1bit_planes(data, p, false);
+      // PCE sprite data was previously generated incorrectly, it seems.
+      // Firstly, the call to make_1bit_planes here should specify 'reverse=true'.
+      // Second, sprite data is stored as 16-bit words in low/high order, meaning the byte pairs should
+      // be swapped here in order to be correct.
+      auto plane = make_1bit_planes(data, p, true);
+      int datalength = plane.size();
+      for (int i = 0; i < datalength-1; i += 2)
+      {
+        auto tmp = plane[i];
+        plane[i] = plane[i+1];
+        plane[i+1] = tmp;
+      }
       nd.insert(nd.end(), plane.begin(), plane.end());
     }
   }
Optiroc commented 2 months ago

I’m not familiar with PCE internals personally, so I’m happy to receive any fixes pertaining to the PCE code paths. I will have a closer look at the diff above.