Sprite Graphics

Share and discuss all facets of DKC ROM hacking...

Re: Sprite Graphics

Postby Cyclone » January 31st, 2023, 11:08 am

rainbowsprinklez wrote:
Cyclone wrote:The heart in the ingame screenshot appears to be mirrored horizontally?

Why is this?


Going left typically flips the sprite. Do you notice how pretty much all the sprites face right? The game programmatically flips these thereby not needing x flips of any sprites explicitly defined.


ahh that makes perfect sense. thanks for the clarification!

I came across another inconsistency.... See screenshot.
Notice how the ingame sprite looks more detailed compared with the other two screenshots. The one displayed in your sprite editor and the one that I used my extractor on. Both appear much more pixelated then the ingame one. However mine and yours are pixel perfect...

Also I noticed editing the sprite only changes the DK sprite that is displayed on the world map(DK Island) and not the sub world maps.

Differences4b.png
Differences4b.png (82.61 KiB) Viewed 115991 times
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby WesternTanager794 » January 31st, 2023, 4:00 pm

Odd. Could it have something to do with the compression system Rare invented? I’m probably going to do research on this to figure it out. I don’t really have too much time to go fiddling around with the sprites. (And I’m learning with that as well) But I like all the things you’ve been pointing out! It’s rather interesting! :parry:
Sage of Discovery
Bananas received 128
Posts: 2393
Joined: 2022

Re: Sprite Graphics

Postby Mattrizzle » January 31st, 2023, 4:04 pm

Cyclone wrote:Also I noticed editing the sprite only changes the DK sprite that is displayed on the world map(DK Island) and not the sub world maps.

For the Donkey Kong and Diddy Kong world map sprites, there are two different sizes: the smaller ones are used on the DK Island Map, while the slightly larger ones are used on the submaps. Funky's Jumbo (Jet) Barrel uses the same sprite regardless of what map you're on.

Here are the first sprites for each with all the info present, as seen in my in-game Sprite Viewer patch:
dkc1_spriteview22-20230131-004009.png
Donkey Kong (Submap)
dkc1_spriteview22-20230131-004009.png (3.83 KiB) Viewed 115985 times

dkc1_spriteview22-20230131-004054.png
Diddy Kong (Submap)
dkc1_spriteview22-20230131-004054.png (3.72 KiB) Viewed 115985 times

dkc1_spriteview22-20230131-004115.png
Donkey Kong (DK Island Map)
dkc1_spriteview22-20230131-004115.png (3.59 KiB) Viewed 115985 times

dkc1_spriteview22-20230131-004122.png
Diddy Kong (DK Island Map)
dkc1_spriteview22-20230131-004122.png (3.6 KiB) Viewed 115985 times


I can't see what you're talking about with the hearts. The ones in the window for Rainbowsprinklez's editor and on the spritesheet from The Spriter's Resource aren't using the correct palette--it looks like they are using Slippa's. The correct palette is used on the in-game screenshot and the rip using Simion's extractor.

Here's the largest of the heart sprites as seen in my Sprite Viewer:
dkc1_spriteview22-20230131-004247.png
Candy's blown kiss
dkc1_spriteview22-20230131-004247.png (3.39 KiB) Viewed 115985 times
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby Cyclone » January 31st, 2023, 8:14 pm

Thanks Mattrizzle. To the point as always!
It turns out the Palette I used for the DK Map sprites was wrong. I was using rainbowsprinkelz editor. But the palette in your screenshots seems correct.
I also notice there is some clipping of the DK Map sprite in rainbowsprinkelz's editor and in my extractor.

Care to elaborate Mr Sprinkelz? :funky:

Differences5b.png


I am sorry if its user error.
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby WesternTanager794 » January 31st, 2023, 8:19 pm

Interesting! I had no idea! Also, I didn't realize that the world map sprites were different! Thanks for the facts, Mattrizzle! :parry:
Sage of Discovery
Bananas received 128
Posts: 2393
Joined: 2022

Re: Sprite Graphics

Postby rainbowsprinklez » February 1st, 2023, 1:55 am

Cyclone wrote:Thanks Mattrizzle. To the point as always!
It turns out the Palette I used for the DK Map sprites was wrong. I was using rainbowsprinkelz editor. But the palette in your screenshots seems correct.


Yes. Your palettes were wrong. Palette makes a BIG difference. There is no array of available palettes like DKC2/3. Therefore, each palette is explicitly defined. I used Giangurgolo's doc for this.

Cyclone wrote:I also notice there is some clipping of the DK Map sprite in rainbowsprinkelz's editor and in my extractor.

Care to elaborate Mr Sprinkelz? :funky:


Clipping? What do you mean?
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Mattrizzle » February 1st, 2023, 3:01 am

rainbowsprinklez wrote:
Cyclone wrote:Thanks Mattrizzle. To the point as always!
It turns out the Palette I used for the DK Map sprites was wrong. I was using rainbowsprinkelz editor. But the palette in your screenshots seems correct.


Yes. Your palettes were wrong. Palette makes a BIG difference. There is no array of available palettes like DKC2/3. Therefore, each palette is explicitly defined. I used Giangurgolo's doc for this.


Each Sprite Viewer patch includes a text document with all the sprite palette locations for the respective game. These are more complete than Giangurgolo's document, but there are still a few unknowns which don't seem to correspond to any existing sprites.

Cyclone wrote:I also notice there is some clipping of the DK Map sprite in rainbowsprinkelz's editor and in my extractor.


Like rainbowsprinklez, I don't see the clipping. The different background colors can play tricks on how you perceive things. The anti-aliasing on those scaled-up screenshots could be a factor as well. The front of DK's face is a straight vertical line in all of those screenshots, but it doesn't look that way in my screenshot because of the dark blue background in conjunction with the shading on the sprite. The latter creates the illusion of a detailed contour where one doesn't exist. You never see these sprites in front of a white background in-game, so it isn't noticeable there either.

In short, both tools have the correct output in this case.
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby Cyclone » February 1st, 2023, 10:14 am

Mattrizzle wrote:
Cyclone wrote:I also notice there is some clipping of the DK Map sprite in rainbowsprinkelz's editor and in my extractor.


Like rainbowsprinklez, I don't see the clipping. The different background colors can play tricks on how you perceive things. The anti-aliasing on those scaled-up screenshots could be a factor as well. The front of DK's face is a straight vertical line in all of those screenshots, but it doesn't look that way in my screenshot because of the dark blue background in conjunction with the shading on the sprite. The latter creates the illusion of a detailed contour where one doesn't exist. You never see these sprites in front of a white background in-game, so it isn't noticeable there either.

In short, both tools have the correct output in this case.


Ah I get it now. I'm sorry. I could have sworn the sprites didn't match up to the in-game version. But i looked more closely and now they appear to match... :scratch:

Is there a formula to follow to extract sprites that are made up of multiple tiles? So far I have Sprites with four 8x8 tiles working correctly...

Thanks!
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 1st, 2023, 11:41 am

http://www.dkc-atlas.com/forum/viewtopic.php?f=38&t=1167#p21471

My understanding has no group D, but whatever works :)

Here are my notes
Code: Select all
Sprite Header
Byte 0 is number of 2x2 chars
Byte 1 is number of  1x1 chars in group 1
Byte 2 is relative position of first 1x1 char of group 1
Byte 3 is number of 1x1 chars in group 2
Byte 4 is position of group 2
Byte 5 is number of chars in dma group 1
Byte 6 is where to place dma group 2 (0 if none)
Byte 7 is number of chars in dma group 2 (0 if none)


Cyclone wrote:Is there a formula to follow to extract sprites that are made up of multiple tiles? So far I have Sprites with four 8x8 tiles working correctly...


Technically, there is a formula. but mine is so sloppy, I can guarantee Matt's is better. I can look into it more tomorrow though.
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 1st, 2023, 3:31 pm

That would be great!

I attached my code of what I have working so far. just 16x16 sprites.
Keep in mind. I know my code is horrible... many things wrong with it but it works.
Attachments
main.zip
(5.19 KiB) Downloaded 1764 times
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 1st, 2023, 11:22 pm

Ok. Just looking at your code, I have a couple of suggestions on the palette.

    Never use decimal notation. Always use hex
    Be mindful of white space. The first few lines of my alterations to your code are much more readable.

Code: Select all
        { 0xff, 0xff, 0xff, 0xff }, /* White    */
        { 0x40, 0x30, 0x00, 0xff }, /* Index  1 */
        { 0x70, 0x48, 0x00, 0xff }, /* Index  2 */
        {  168, 104, 56, 255 }, /* Index  3 */
        {   216, 152, 0, 255 }, /* Index  4 */
        {   248, 216, 8, 255 }, /* Index  5 */ 
        { 255, 255, 255, 255 }, /* Index  6 */
        { 208, 208, 208, 255 }, /* Index  7 */
        { 160, 160, 160, 255 }, /* Index  8 */
        { 112, 120, 120, 255 }, /* Index  9 */
        {  72,   0,  0, 255 }, /* Index 10 */
        {   160,   8, 8, 255 }, /* Index 11 */
        {  248,  16, 16, 255 }, /* Index 12 */
        {  248, 104, 8, 255 }, /* Index 13 */
        {   0, 248,   0, 255 }, /* Index 14 */
        {   0,   0,   0, 255 }  /* Index 15 */


***EDIT***
You want your code as readable as possible so other coders (mostly you, though) could easily understand
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby rainbowsprinklez » February 1st, 2023, 11:31 pm

Cyclone wrote:
Is there a formula to follow to extract sprites that are made up of multiple tiles? So far I have Sprites with four 8x8 tiles working correctly...


Code: Select all
        private void ReadHeaderLemgth(int index /* ROM address */)
        {
            // Read each byte in header
            // To display
            byte b0 = (byte)rom.Read8(index++);
            byte b1 = (byte)rom.Read8(index++);
            byte b2 = (byte)rom.Read8(index++);
            byte b3 = (byte)rom.Read8(index++);
            byte b4 = (byte)rom.Read8(index++);
            byte b5 = (byte)rom.Read8(index++);
            byte b6 = (byte)rom.Read8(index++);
            byte b7 = (byte)rom.Read8(index++);

            headerLength = 8 + (b0 * 2) + (b1 * 2) + (b3 * 2);
            // Display size of data
            int size = headerLength + (b5 << 5) + (b7 * 0x20);
        }


Not that bad. I misunderstood :)

***EDIT***
Also, << 5 and * 0x20 are the same thing! :D
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 2nd, 2023, 10:59 am

Sorry if you misunderstood, or if I misunderstood but that function you wrote just gets the size of the header?

I thought it would have something to do with the x/y coordinates of each tile in a sprite. I was just thinking how to program a function that finds those coordinates and combines those tiles into one .png image.
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 2nd, 2023, 12:02 pm

Cyclone wrote:Sorry if you misunderstood, or if I misunderstood but that function you wrote just gets the size of the header?

You are right. That is just size.

Cyclone wrote:I thought it would have something to do with the x/y coordinates of each tile in a sprite. I was just thinking how to program a function that finds those coordinates and combines those tiles into one .png image.

Unfortunately, the way I do it is convoluted as DKC formats sprite data in such a way that they can optimally transfer the data with dma calls. if I recall correctly, mixing and matching 8x8s and 16x16s gets really boggling! I'm not sure I am the best to describe that... Matt?

The tldr is they are positioned to work well in vram

EDIT
The positioning of tiles is free. The convoluted part comes with identifying which tiles are paired with which coord. After the first 8 bytes, there are 2 bytes for each tile, denoting x and y offsets

EDIT 2
I desperately need to refactor my code. I actually never thought of a formula until the day before yesterday. I am 100% sure now that there is a simple way to do it. I emulate vram in my solution. There are a lot of if's in my solution.Like if byte 0 (# of 16x16's) is == 8, do this. I do not think that there is 1 formula though. Maybe I'm wrong
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Mattrizzle » February 3rd, 2023, 3:22 am

rainbowsprinklez wrote:Unfortunately, the way I do it is convoluted as DKC formats sprite data in such a way that they can optimally transfer the data with dma calls. if I recall correctly, mixing and matching 8x8s and 16x16s gets really boggling! I'm not sure I am the best to describe that... Matt?


Ugh, tell me about it... Building tilemaps/OAM arrangements for custom sprites is a pain. It would be great if a tool could convert a 256x256 (or maybe smaller than that, due to ROM, VRAM, and OAM limitations) image into sprite tiles and an OAM table.

I've looked at several sprites from throughout the trilogy trying to figure out a pattern, but never have. Some sprites that look like they would fit neatly into a 16x16 space (e.g. the lives counter icon in DKC2) are instead broken into 4 8x8s. The 8x8s use up less rows in VRAM, but are more wasteful in OAM and ROM (due to the additional x,y coordinates that have to be stored). Generally, new sprites get loaded into separate rows rather than occupying partially filled rows in VRAM (likely to avoid potential overlap, which would glitch out tiles), so I guess this makes sense.

This isn't all there is to it, though. What rules are there for what parts of a sprite get a 16x16 tile versus an 8x8? I know there is optimization going on to avoid tiles with too many transparent pixels. If a sprite is larger than 16x16, and a 16x16 region only has a handful of transparent pixels in it, that would likely be made into a 16x16 tile. You aren't likely to find a 16x16 tile where half of the pixels are transparent, as that is wasteful. 8x8 tiles would be used for that area instead.

EDIT:
Adding to what rainbowsprinklez mentioned in his edit, 16x16 tile coordinates always come before the 8x8 tile coordinates, and are always ordered from left-to-right, top-to-bottom in VRAM. This doesn't mean that the first tile in VRAM will be the one closest to the upper left in the tile arrangements, hence what rainbowsprinklez said: "The positioning of tiles is free". Where the bottom row of 16x16 tiles is start in the tile data is dependent on the value of byte 7. I'll be honest, I'm not sure how things work when you have more than 8 16x16 tiles.
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 3rd, 2023, 3:53 am

Mattrizzle wrote:Ugh, tell me about it... Building tilemaps/OAM arrangements for custom sprites is a pain. It would be great if a tool could convert a 256x256 (or maybe smaller than that, due to ROM, VRAM, and OAM limitations) image into sprite tiles and an OAM table.


Well, I made this sloppy tool for doing just that. But there are some caveats.

    Upon launch, an open file dialog appears
    Only 256x256 is supported
    Only 16-color images work.

Proof it works
Spoiler!
Image
Image


This creates both a palette and the image data. This is by far NOT optimal. Only 8x8s are used. So a lot of OAM is used.
Attachments
DKC_Sprite_creator.zip
(7.22 KiB) Downloaded 1615 times
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Mattrizzle » February 3rd, 2023, 4:17 am

Whoa, I didn't expect that! Not too bad for a first attempt.

One particular image I need to make into a sprite is over 128 pixels wide by over 32 pixels tall. If using only 8x8 tiles, that would use more than 64, or over half of OAM!

In all three DKC games, K. Rool is the largest character made entirely out of sprites, so some of his sprites would possibly have more than 8 16x16 tiles. I don't know if any other Rare games would have larger sprites. Several (maybe all?) Rare-developed games for the SNES use this format, including games in the Battletoads, Killer Instinct, and Ken Griffey Jr. series (the normal format anyway; I'm not sure if the alternate double-paletted one some DKC3 sprites use appears in any other games). I'll investigate later.

EDIT: Here's the complete list of Rare-developed games for the SNES, in order of release:
1993 Battletoads in Battlemaniacs
1993 Battletoads & Double Dragon - The Ultimate Team
1994 Donkey Kong Country
1995 Killer Instinct
1995 Donkey Kong Country 2: Diddy's Kong Quest
1996 Ken Griffey Jr.'s Winning Run
1996 Donkey Kong Country 3: Dixie Kong's Double Trouble!
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby Cyclone » February 3rd, 2023, 7:54 am

I thought each sprite was made up of individual 8x8 tiles no matter the size of the entire sprite?

I attached a screen of rainbowsprinkelz's editor. Could you briefly explain each of the values? I think I understand what a 2x2 char and a 1x1 char is but i need clarification on what it is. Also i'm not really sure what a "group / offset is".

Thanks,
Cyclone the noob.... :oops:
Attachments
Untitled.png
Untitled.png (64.49 KiB) Viewed 115826 times
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 3rd, 2023, 11:08 am

Cyclone wrote:I thought each sprite was made up of individual 8x8 tiles no matter the size of the entire sprite?

I attached a screen of rainbowsprinkelz's editor. Could you briefly explain each of the values? I think I understand what a 2x2 char and a 1x1 char is but i need clarification on what it is. Also i'm not really sure what a "group / offset is".

Thanks,
Cyclone the noob.... :oops:


Lol noob is no problem. You contradict yourself there. 2x2 is another way to say 4 8x8's are joined into one 16x16, so in your example image, there are 5 16x16s. You can see this in the tile editor and pixel assignment.
Group and offset are vram terms.
Look at this image
Spoiler!
Image


Let's talk about the 8 bytes in the header.

    2x2 chars is number of 16x16's. So we can see the first 10 chars are part of the 2x2's (5 * 2)

    1x1 chars (group 1) is the number of chars until the last char OR the end of the VRAM row. this is not a great example because all the space is used in these 2 rows. Not your fault, just saying, it gets WAY more complicated.

    1x1 offset (group 1): If you count the available chars horizontally, you get 16 (0x10). 16 is the magic number here.So this says which offset after all the 2x2s to start the 1x1 chars (0xA or 10)

    There's another group in VRAM. I'm not explaining groups here. Tldr; group 2 in this case is row 2 8x8's. In this case, group 2 refers to the additional chars after the bottom half of the 2x2s. There are 6 more chars in group 2.

    There are 5 2x2's, or 10 (0xa) - so this offset is index A in the second row, or 1A

    Size to send to VRAM group 1 is 0x20 or basically the number of chars in dma group 1. (5 16x16's = 20 (0x14), 6 chars group 1, 6 chars group 2. 0x14 + 6 + 6 = 0x20)

    Group 2 dma not applicable here... maybe this example was better as to not overload you.

Here, this image might help in comprehending
Spoiler!
Image


EDIT
This image explains it MUCH easier.
Image

Left of the blue line is the 16x16's.
To the right is the 8x8. Above green is sprite group 1. Below green is sprite group 2.

DMA groups are different and not discussed here
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby rainbowsprinklez » February 3rd, 2023, 3:23 pm

Mattrizzle wrote:Whoa, I didn't expect that! Not too bad for a first attempt.


Yeah, that was just done quickly one day as a fun challenge one day. Ask H4v0c! He is the one I got that DKC2 pic from!
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby rainbowsprinklez » February 3rd, 2023, 11:43 pm

Here is a good example (by good I mean harder) for comprehension. Consider this,
Image

Now look at this image I sectioned off.
Image

Everything in green is the 16x16s. Every cell is an 8x8, so if we look at 2x2 chars we can see the 16x16's. There are 9 16x16's here.
Every cell outlined in blue are the remaining 8x8's, of which there are 9.
Every cell outlined in red is just garbage and shouldn't be considered (Leftovers from previous sprites).

If we look at that same image but think of dma groups,
Image
The cells with the yellow line through are part of dma group 1. The cells with pink are part of dma group 2. This is done because of the garbage 8x8's after the yellow line.

Image
In this image, 0x2b represents every 8x8 in the yellow line. 0x30 tells you where to start the pink line (which row starting with row 0). The final 2 is just the count of the pink in dma group 2.

I hope I explained well. Ask me for any clarifications!

EDIT
This is an example of a big sprite (uses 4 rows). Most sprites are small (uses 2). These are ordered in ROM sequentially, with the pink after the yellow. This is why I don't have a concrete formula. My method is to emulate vram
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby rainbowsprinklez » February 4th, 2023, 4:15 am

Ok. Let's talk about this image.
Image

Here is what VRAM looks like in game.
Image

These are my markups following the same formatting as before.
Image

We have 2 dma groups. Why? Well, look at the first row. Even though it's full, according to the sprite header we only need the first 15 chars (3 * 2 + 9 = 15). So the last is garbage. So our first dma group has 15 (or 0xf). I dpm't want to explain dma group 2. I want to see if you can describe them!

Alternatively, look at this picture for a dma breakdown
Image

Why did the big banana not have a dma group 2?
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Mattrizzle » February 5th, 2023, 3:30 am

I figured out what the largest single sprite in the entire DKC trilogy is (This is spoilered for Cyclone. Don't look at this without understanding rainbowsprinklez's examples!):
Spoiler!
It's the Banana Bird Queen's huge egg from the true ending of DKC3 (sprite #$3B33)!

dkc3_banana_bird_queen_egg.png
dkc3_banana_bird_queen_egg.png (5.56 KiB) Viewed 115668 times


It's located at SNES $DC:5F65 in the Donkey Kong Country 3 (U) (v1.0) ROM.
Here is its header info, using the same terminology as rainbowsprinklez's DKC editor:
Code: Select all
# of 2x2 chars:                            1F


# of 1x1 chars (group 1):                   2


1x1 offset (group 1):                      6E


# of 1x1 chars (group 2):                  13


1x1 offset (group 2):                      7E

Size to send to vram shifted
5 times (dma group 1):                     91


Offsets in VRAM dma group 2 (0 if none):    0


# of chars in dma group 2 (0 if none):      0

Here are the char groups. Unlike rainbowsprinklez's two examples, there are three: the 2x2 char group is surrounded by green borders, 1x1 char group 1 is surrounded by light blue, and 1x1 char group 2 is surrounded by darker blue. Cells surrounded by red are garbage.
dkc3_banana_bird_queen_egg-char_groups.png
dkc3_banana_bird_queen_egg-char_groups.png (20.75 KiB) Viewed 115668 times

Cyclone, can you give an answer as to why there are two 1x1 char groups here?

Despite its size (or because of it?), this uses only one DMA group:
dkc3_banana_bird_queen_egg-dma_groups.png
dkc3_banana_bird_queen_egg-dma_groups.png (22.67 KiB) Viewed 115668 times
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 5th, 2023, 8:52 am

Mattrizzle wrote:I figured out what the largest single sprite in the entire DKC trilogy is (This is spoilered for Cyclone. Don't look at this without understanding rainbowsprinklez's examples!):


Wow! That is absolutely massive! I don't even want to THINK about how much OAM that takes! Also, thank you for sticking with my formatting. My color choices were completely random from ms paint lol
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 5th, 2023, 2:33 pm

rainbowsprinklez wrote:Ok. Let's talk about this image.
Image

Here is what VRAM looks like in game.
Image

These are my markups following the same formatting as before.
Image

We have 2 dma groups. Why? Well, look at the first row. Even though it's full, according to the sprite header we only need the first 15 chars (3 * 2 + 9 = 15). So the last is garbage. So our first dma group has 15 (or 0xf). I dpm't want to explain dma group 2. I want to see if you can describe them!


How did you arrive at 0xf for the size of dma group 1?
can you help me with the below example?

I tried (5 * 2 + 6 = 16)

Thanks.
dk1.png
dk1.png (40.51 KiB) Viewed 115611 times
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 5th, 2023, 3:39 pm

Cyclone wrote:How did you arrive at 0xf for the size of dma group 1?
can you help me with the below example?

I tried (5 * 2 + 6 = 16)

Thanks.


Not your fault. That was a detail I missed. When a row has no garbage, you carry on counting with the next row. In my example, the first DMA call encounters a garbage cell after 0xf chars. I like that. That is a better way to explain things. A DMA group counts chars left to right until you run into a garbage cell. Sorry for not explaining that way the first time.

So in your example, you have 5 2x2's, so you count 5 * 4

EDIT
It's funny. Similar was explained in the part you posted including exactly how f was found

rainbowsprinklez wrote:We have 2 dma groups. Why? Well, look at the first row. Even though it's full, according to the sprite header we only need the first 15 chars (3 * 2 + 9 = 15). So the last is garbage. So our first dma group has 15 :) (or 0xf). I don't want to explain dma group 2. I want to see if you can describe them!
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Mattrizzle » February 5th, 2023, 4:18 pm

Rainbow ninja'd me, but since I put so much effort into this answer, I'm posting it anyway :mrgreen:
Cyclone wrote:can you help me with the below example?

I tried (5 * 2 + 6 = 16)


Rainbow alluded to something similar to this example when he asked you "Why did the big banana not have a dma group 2?"

Open the spoiler for the answer:
Spoiler!
Keep in mind that your example has five 2x2 chars and six 1x1 chars, totaling 16 (0x10 in hexadecimal). This means the entire first row is full, and there is no need to skip any chars to get to the next row in VRAM. Thus, you can write the whole next row without another DMA group, and the group continues beyond 0x10.
The next row is has 5 * 2 for the bottom halves of the 2x2 chars, and the single 1x1 in char group 2 (header byte 0x3, or the fourth byte). That single 1x1 is at offset 0x1A (the 27th char; as seen in header byte 0x4).
So, 5 * 2 + 1 = 11 (0xB in hex)

For your first row, you have 16. For your second row, you have 11. 16+11 = 27, which is 0x1B in hex, matching byte 0x5 (the sixth byte) in the header: "Size to send to vram [...] (dma group 1)"
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 6th, 2023, 1:11 am

Mattrizzle wrote:"Size to send to vram [...] (dma group 1)"

This is a really bad name for this. A much better name would be "# of chars in dma group 1"
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 6th, 2023, 9:35 am

How come offset group 1 is 22? Shouldn't it be 18?
Also how come there isn't a group 2?
I'm just trying to understand when a sprite uses just one group or when it needs to use two groups.
Image

I'm sorry, I really am trying...
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby Mattrizzle » February 6th, 2023, 10:11 am

Cyclone wrote:How come offset group 1 is 22? Shouldn't it be 18?
Also how come there ins't a group 2?

There are 9 2x2 chars.

9 * 2 = 18 (0x12 in hexadecimal)

Remember, only 16 (0x10 in hex) chars fit in one row. This means the top halves of the first 8 2x2 chars will fill this space (0x0-0xF).
Also, since 2x2 chars have two rows, the entirety of the second row will be filled with the bottom halves of the first 8 2x2 chars (0x10-0x1F).

The first two chars in the second row (0x20-0x21) will house the top half of the 9th 2x2 char.
Thus, the next place the 1x1 chars can go in is 0x22.

Since you don't want the bottom half of the 9th 2x2 char to be loaded next to the last 1x1 char (if you did, the bottom half would be garbage), you need a second DMA group to place these last two chars on the fourth row, where the belongs (chars 0x30-0x31). Hence, the last two header values of 0x30 and 0x2.

Don't forget that all the values are in hexadecimal. 1x1 group 1 offset is 0x22, which is 34 in decimal. You mixed the two in your question.

As for why there isn't a group 2, are you referring to the big banana example? The Funky Jumbo Jet Barrel does use dma group 2.

EDIT: Oh wait, you meant the 1x1 char group 2? The answer is that there aren't enough 1x1 chars to need that group.
EDIT 2: If there are so many 1x1 chars that they would exceed the end of the row that 1x1 group 1 started on and occupy the same space as the bottom half of a 2x2 char (causing a conflict), you would need a second 1x1 char group.
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 6th, 2023, 3:07 pm

Cyclone wrote:Also how come there isn't a group 2?
I'm just trying to understand when a sprite uses just one group or when it needs to use two groups.


Another way to think of it is if a new 1x1 char is char 0x10 (decimal index 16) or above, a new char group is used



Cyclone wrote:I'm sorry, I really am trying...

You're actually doing well! It took me a while to understand, and I'm still learning most days!

EDIT
That's not 100% true. Group 2 only happens when the next char wraps around and conflicts with the lower half of a 2x2
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 8th, 2023, 2:19 pm

Mattrizzle wrote:Since you don't want the bottom half of the 9th 2x2 char to be loaded next to the last 1x1 char (if you did, the bottom half would be garbage), you need a second DMA group to place these last two chars on the fourth row, where the belongs (chars 0x30-0x31). Hence, the last two header values of 0x30 and 0x2.


Image

How come the bottom half of the 9th 2x2 char isn't loaded on the 3rd row? Right before the chars in blue?

I almost grasp this, just hasn't 'clicked' in my head yet...
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby Cyclone » February 8th, 2023, 2:45 pm

rainbowsprinklez wrote:Not your fault. That was a detail I missed. When a row has no garbage, you carry on counting with the next row. In my example, the first DMA call encounters a garbage cell after 0xf chars. I like that. That is a better way to explain things. A DMA group counts chars left to right until you run into a garbage cell. Sorry for not explaining that way the first time.


rainbowsprinklez wrote:We have 2 dma groups. Why? Well, look at the first row. Even though it's full, according to the sprite header we only need the first 15 chars (3 * 2 + 9 = 15). So the last is garbage. So our first dma group has 15 :) (or 0xf). I don't want to explain dma group 2. I want to see if you can describe them!


To clarify. Is a dma group needed when you need to skip garbage cells?

Edit..
The large Banana doesn't have dma group two because there are no garbage cells? Meaning all the rows are full and garbage cells don't need to be skipped?
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 8th, 2023, 10:31 pm

Cyclone wrote:To clarify. Is a dma group needed when you need to skip garbage cells?

An extra dma group yes. My pedantic answer is you always need at least 1 dma group, but I think you knew that...
Cyclone wrote:Edit..
The large Banana doesn't have dma group two because there are no garbage cells? Meaning all the rows are full and garbage cells don't need to be skipped?

Correct!
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Mattrizzle » February 9th, 2023, 1:42 am

Cyclone wrote:How come the bottom half of the 9th 2x2 char isn't loaded on the 3rd row? Right before the chars in blue?

I almost grasp this, just hasn't 'clicked' in my head yet...


It wouldn't be possible to go from the fourth row to the third, as the chars in ROM are always stored in the order they are DMAed to VRAM (left to right, and top to bottom). If the bottom half of the 2x2 char was DMAed next to the top half, it wouldn't be usable as the bottom half of the 2x2 char. In VRAM, the bottom of a 2x2 char must be DMAed exactly 0x10 chars (0x200 bytes) after the top half. A 2x2 char with value 0x00 uses 1x1 chars 0x00, 0x01, 0x10, and 0x11. You could have the halves stored next to each other in ROM, but you would still need 2 DMA groups, as the 1x1 chars would consequently need to be DMAed to the fourth row instead.

"Char" is probably a bit ambiguous. There are graphical chars, which are the 4BPP tile data which is DMAed to VRAM, and there are OAM chars, which are what actually gets drawn to the OBJ or sprite layer. OAM chars reference these graphical chars but are also assigned X- and Y- coordinates, as well as palette, priority, flip and size values (1x1/8x8 or 2x2/16x16 in the case of DKC).
Veteran Venturer
Bananas received 222
Posts: 559
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 9th, 2023, 4:29 am

Cyclone wrote:How come the bottom half of the 9th 2x2 char isn't loaded on the 3rd row? Right before the chars in blue?

I almost grasp this, just hasn't 'clicked' in my head yet...


To extend what Matt said, that is because of the way the SNES displays sprites. When all 4 of a 2x2 are placed logically together, the SNES can easily display them. Else it needs fancy logic to do so. So we use a separate DMA call to place them in the right spot in VRAM.
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 9th, 2023, 9:13 am

Is this correct? I added an extra 2x2 char to the example. Circled in green. Changed the other highlighted areas reflect that.

D4Yp3Nx.png
D4Yp3Nx.png (7.79 KiB) Viewed 115258 times


SU5dkHW.png
SU5dkHW.png (8.18 KiB) Viewed 115258 times


rainbowsprinklez wrote:When all 4 of a 2x2 are placed logically together, the SNES can easily display them.


Can you elaborate?
by 4 do you mean the 4 individual cells that make up a 2x2?
And what do you mean logically together?
Thanks again.
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 9th, 2023, 1:03 pm

Cyclone wrote:Is this correct? I added an extra 2x2 char to the example. Circled in green. Changed the other highlighted areas reflect that.

I'm not 100% sure what you are asking.... Are you asking if your dma calls are right if you added one 2x2? If so, yes. If not, idfk :) I would use my gfx editor to find an example. Index 0x150 is good

Cyclone wrote:
rainbowsprinklez wrote:When all 4 of a 2x2 are placed logically together, the SNES can easily display them.


Can you elaborate?
by 4 do you mean the 4 individual cells that make up a 2x2?
And what do you mean logically together?
Thanks again.

If you look at a 2x2 char, those are made up of 4 chars. Arranging them logically in VRAM is just something I made up to describe when the chars are stacked/positioned in a way that makes sense.
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 9th, 2023, 2:47 pm

rainbowsprinklez wrote:
Cyclone wrote:Is this correct? I added an extra 2x2 char to the example. Circled in green. Changed the other highlighted areas reflect that.

I'm not 100% sure what you are asking.... Are you asking if your dma calls are right if you added one 2x2? If so, yes. If not, idfk :) I would use my gfx editor to find an example. Index 0x150 is good


yea, that was what I was asking. Thanks.

Cyclone wrote:
rainbowsprinklez wrote:When all 4 of a 2x2 are placed logically together, the SNES can easily display them.

Can you elaborate?
by 4 do you mean the 4 individual cells that make up a 2x2?
And what do you mean logically together?
Thanks again.

If you look at a 2x2 char, those are made up of 4 chars. Arranging them logically in VRAM is just something I made up to describe when the chars are stacked/positioned in a way that makes sense.


When you say...
"just something I made up to describe when the chars are stacked/positioned in a way that makes sense. "

Do you mean when the chars are positioned in 2x2 blocks/squares?

Might be going in circles. if so I'm sorry.
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 9th, 2023, 4:02 pm

Do you see how the 2x2's make a small part of the image? that

EDIT
I don't know how else to describe it, sorry. I think this is getting way more complicated than it is. I mean the chars in a 2x2 should appear AS a 16x16 in vram
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » February 9th, 2023, 11:52 pm

That’s ok rainbowsprinkelz. Thanks for getting me this far.
Cheers
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » February 10th, 2023, 12:29 am

When I said logically, I meant this:

Image

not this

Image
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 9th, 2023, 8:47 am

A question for you mr rainbowsprinklez .

How come these two sprites don't match up? There are differences in the bottom right tiles.
Thanks in advance.

compare.png
compare.png (39.2 KiB) Viewed 109105 times


compare2.png
compare2.png (15.01 KiB) Viewed 109105 times
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 12th, 2023, 12:54 pm

Cyclone wrote:A question for you mr rainbowsprinklez .

How come these two sprites don't match up? There are differences in the bottom right tiles.
Thanks in advance.


Where did you get that image from? The life balloon is animated. Animation index on normal show is animation index 189.

Image

Animation index on pop is 18a
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 12th, 2023, 2:28 pm

Sorry typos in my code lol
That image is just a test that I extracted from the rom.

It’s now pixel perfect
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 12th, 2023, 8:10 pm

Cyclone wrote:Sorry typos in my code lol
That image is just a test that I extracted from the rom.


No prob :) Image 784? Was the typo getting the wrong image? Or...?

***EDIT***
Also, it was luck I even checked here. If I haven't been here in a bit, please tag me :)
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 14th, 2023, 7:53 am

So I noticed there are inconsistency's in the order of the tiles. Any tips on how the tiles are ordered in the rom?
Bellow is my code. It extracts a single 2x2 char.
tile_order.png
tile_order.png (38.14 KiB) Viewed 108857 times

Code: Select all

#include "C:\Users\Chris\source\repos\PNG\lodepng.h"
#include "C:\Users\Chris\source\repos\PNG\lodepng.cpp"
#include <fstream>
#include <sstream>
#include <string>
#include <atlstr.h>
#include <iterator>
#include <iostream>
#include <bitset>
using namespace std;

//Encode from raw pixels to disk with a single function call
//The image argument has width * height RGBA pixels or width * height * 4 bytes
void encodeOneStep(const char* filename, std::vector<unsigned char>& image, unsigned width, unsigned height) {
    //Encode the image
    unsigned error = lodepng::encode(filename, image, width, height);

    //if there's an error, display it
    if (error) std::cout << "encoder error " << error << ": " << lodepng_error_text(error) << std::endl;
}
//const unsigned width = 32, height = 32, no_elems = 4096; // no_elems is the size of the png image array.

int main()
{
    //const unsigned width = 32, height = 32, no_elems = 4096; // no_elems is the size of the png image array.
    const unsigned width = 256, height = 256, no_elems = 262144; // no_elems is the size of the png image array.
    std::vector<unsigned char> image(no_elems);

    CString File_Path;
    char sztmp[1024];
    const char* filepath = " ";


    cin.clear();
    cout << "Enter Path to extract sprite graphics to: " << endl;
    cin.getline(sztmp, sizeof(sztmp), '\n');
    filepath = sztmp;

    // Balloon Pallette? Needs correcting.
    static const unsigned char coloursD[16][4] = { // An array of colour values.
       //RRR  GGG  BBB  AAA
       { 255, 255, 255, 255 }, /* White    */
       {   24,  16,  0, 255 }, /* Index  1 */
       {   64,  32, 0, 255 }, /* Index  2 */
       {  96, 48, 0, 255 }, /* Index  3 */
       {   96, 48, 0, 255 }, /* Index  4 */
       {   136, 64, 0, 255 }, /* Index  5 */
       { 168, 80, 0, 255 }, /* Index  6 */
       { 192, 96, 0, 255 }, /* Index  7 */
       { 208, 112, 0, 255 }, /* Index  8 */
       { 248, 0, 0, 255 }, /* Index  9 */
       {  128,   0,  0, 255 }, /* Index 10 */
       {   248,   128, 112, 255 }, /* Index 11 */
       {  248,  128, 112, 255 }, /* Index 12 */
       {   248, 160, 144, 255 }, /* Index 13 */
       {  248, 192,  184, 255 }, /* Index 14 */
       {   248, 224,  216, 255 }  /* Index 15 */
    };

    char oDataK[0x6000]; // Balloon buffer
    ifstream inFileK;
    inFileK.open("C:\\Users\\Chris\\Desktop\\DK\\Emulators ad Debuggers\\zsnesw150\\dkc1.sfc", ios::binary); // Note. this opens a binary streem. This is needed. cuzz the program was using 0x1a values as a Substitute AscII charter which halts the program/Using it as End Of File.
    inFileK.seekg(0x2B67d6 + 10 + 4, 1);
    inFileK.read(oDataK, 0x6000);
    inFileK.close();

    int offset = 0; // The location of the next set of sprites.

     // Create the Bitplanes
    int* Bitplane0__ROW = new int[100];
    int* Bitplane1__ROW = new int[100];
    int* Bitplane2__ROW = new int[100];
    int* Bitplane3__ROW = new int[100];

    int tile_offset = 0;

    // Assign each Bitplane Row the data from the buffer. oData is the buffer containing the bytes from the rom.
    for (int X = 0; X <= 80; X++)

    {
            for (int p = 0, t = 0; t < 5;t++) //  Tiles
            {
                p = 0;
                if (t == 1) { p = 0; tile_offset = 0; }
                if (t == 2) { p = 8; tile_offset = 32; }
                if (t == 3) { p = 16; tile_offset = 128; }
                if (t == 4) { p = 24; tile_offset = 160; }
                Bitplane0__ROW[p++] = oDataK[14 + tile_offset];
                Bitplane0__ROW[p++] = oDataK[12 + tile_offset];
                Bitplane0__ROW[p++] = oDataK[10 + tile_offset];
                Bitplane0__ROW[p++] = oDataK[8 + tile_offset];
                Bitplane0__ROW[p++] = oDataK[6 + tile_offset];
                Bitplane0__ROW[p++] = oDataK[4 + tile_offset];
                Bitplane0__ROW[p++] = oDataK[2 + tile_offset];
                Bitplane0__ROW[p++] = oDataK[0 + tile_offset];

                p = 0;
                if (t == 1) { p = 0; tile_offset = 0; }
                if (t == 2) { p = 8; tile_offset = 32; }
                if (t == 3) { p = 16; tile_offset = 128; }
                if (t == 4) { p = 24; tile_offset = 160; }
                Bitplane1__ROW[p++] = oDataK[15 + tile_offset];
                Bitplane1__ROW[p++] = oDataK[13 + tile_offset];
                Bitplane1__ROW[p++] = oDataK[11 + tile_offset];
                Bitplane1__ROW[p++] = oDataK[9 + tile_offset];
                Bitplane1__ROW[p++] = oDataK[7 + tile_offset];
                Bitplane1__ROW[p++] = oDataK[5 + tile_offset];
                Bitplane1__ROW[p++] = oDataK[3 + tile_offset];
                Bitplane1__ROW[p++] = oDataK[1 + tile_offset];


                p = 0;
                if (t == 1) { p = 0; tile_offset = 0; }
                if (t == 2) { p = 8; tile_offset = 32; }
                if (t == 3) { p = 16; tile_offset = 128; }
                if (t == 4) { p = 24; tile_offset = 160; }
                Bitplane2__ROW[p++] = oDataK[30 + tile_offset];
                Bitplane2__ROW[p++] = oDataK[28 +  tile_offset];
                Bitplane2__ROW[p++] = oDataK[26 +  tile_offset];
                Bitplane2__ROW[p++] = oDataK[24 +  tile_offset];
                Bitplane2__ROW[p++] = oDataK[22 +  tile_offset];
                Bitplane2__ROW[p++] = oDataK[20 +  tile_offset];
                Bitplane2__ROW[p++] = oDataK[18 +  tile_offset];
                Bitplane2__ROW[p++] = oDataK[16 +  tile_offset];

                p = 0;
                if (t == 1) { p = 0; tile_offset = 0; }
                if (t == 2) { p = 8; tile_offset = 32; }
                if (t == 3) { p = 16; tile_offset = 128; }
                if (t == 4) { p = 24; tile_offset = 160; }
                Bitplane3__ROW[p++] = oDataK[31 +  tile_offset];
                Bitplane3__ROW[p++] = oDataK[29 +  tile_offset];
                Bitplane3__ROW[p++] = oDataK[27 +  tile_offset];
                Bitplane3__ROW[p++] = oDataK[25 +  tile_offset];
                Bitplane3__ROW[p++] = oDataK[23 +  tile_offset];
                Bitplane3__ROW[p++] = oDataK[21 +  tile_offset];
                Bitplane3__ROW[p++] = oDataK[19 +  tile_offset];
                Bitplane3__ROW[p++] = oDataK[17 +  tile_offset];
            }

       
        int c = 0;

        for (int p = 0, t = 0; p < 32; p++, t++) 
        {
            // Assign each row of the tiles a value from the image buffer. p is the row offset. c is the location within the buffer.

            // Top Left
             // 256 is the row offset. 4 is the pixel offest. for example Red, Green, Blue and Alpha = 4.
            if (p == 0) { c = 256 * 28; }
            if (p == 1) { c = 256 * 24; }
            if (p == 2) { c = 256 * 20; }
            if (p == 3) { c = 256 * 16; }
            if (p == 4) { c = 256 * 12; }
            if (p == 5) { c = 256 * 8; }
            if (p == 6) { c = 256 * 4; }
            if (p == 7) { c = 0; }

            // Top Right
            if (p == 8) { c = 256 * 28 + 32; }
            if (p == 9) { c = 256 * 24 + 32; }
            if (p == 10) { c = 256 * 20 + 32; }
            if (p == 11) { c = 256 * 16 + 32; }
            if (p == 12) { c = 256 * 12 + 32; }
            if (p == 13) { c = 256 * 8 + 32; }
            if (p == 14) { c = 256 * 4 + 32; }
            if (p == 15) { c = 0 + 0 + 32; }

            // Bottom Right
            if (p == 24) { c = 256 * 28 + 32; }
            if (p == 25) { c = 256 * 24 + 32; }
            if (p == 26) { c = 256 * 20 + 32; }
            if (p == 27) { c = 256 * 16 + 32; }
            if (p == 28) { c = 256 * 12 + 32; }
            if (p == 29) { c = 256 * 8 + 32; }
            if (p == 30) { c = 256 * 4 + 32; }
            if (p == 31) { c = 0 + 0 +  32; }
         
            // Bottom Left
            if (p == 16) { c = 256 * 28; }
            if (p == 17) { c = 256 * 24; }
            if (p == 18) { c = 256 * 20; }
            if (p == 19) { c = 256 * 16; }
            if (p == 20) { c = 256 * 12; }
            if (p == 21) { c = 256 * 8; }
            if (p == 22) { c = 256 * 4; }
            if (p == 23) { c = 0 + 0 + 0; }
            if (p > 15) { c = c + 8192; }

            for (int j = 0, N = 7; j < 8; j++, N--) // Check which bits are set for each pixel of the tiles. Then assign the index colour to the image Array location.
            {
                std::bitset<4> bs;
                bs.set(0, (Bitplane0__ROW[p] >> N) & 1);
                bs.set(1, (Bitplane1__ROW[p] >> N) & 1);
                bs.set(2, (Bitplane2__ROW[p] >> N) & 1);
                bs.set(3, (Bitplane3__ROW[p] >> N) & 1);
                unsigned long Index = bs.to_ulong();

                image[c++] = coloursD[Index][0]; // Red
                image[c++] = coloursD[Index][1]; // Green
                image[c++] = coloursD[Index][2]; // Blue
                image[c++] = coloursD[Index][3]; // Alpha
            }
        }

        if (X <= 2) // x is the number of sprite image files to write.
        {
            string combined_file_path(string(filepath) + to_string(X) + ".png");
            encodeOneStep(combined_file_path.c_str(), image, width, height);  // Write the .png image file.
        }
    }

    return 0;
}
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 14th, 2023, 11:38 am

Cyclone wrote:So I noticed there are inconsistency's in the order of the tiles. Any tips on how the tiles are ordered in the rom?
Bellow is my code. It extracts a single 2x2 char.


Sorry, my mind-reading helmet is in the shop :) C++ isn't my language of choice. All I know is that by a quick glance, I don't see any inconsistencies in my output. It must be your algorithm. What exactly are the inconsistencies you notice? That image doesn't tell me what you think is wrong. I could guess, but I could be wrong, and then it's more confusing for both of us.

Thank you for posting your code, but to be honest I haven't tried yet to understand it.
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 14th, 2023, 11:55 am

I thought that the tiles go in this order...

TL
TR
BL
BR

with each tile 32 bytes after the previous one.

Does that make sense?

Well according to that screen shot that isn't true.

the 1x1 chars come right after the TL and TR of the 2x2 chars
Expedition Leader
Bananas received 559
Posts: 1257
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 14th, 2023, 12:48 pm

Cyclone wrote:the 1x1 chars come right after the TL and TR of the 2x2 chars


Yes, that makes sense when you consider this image

Image

Think about that in terms of DMA groups. That image uses 2 DMA groups. The data is arranged in ROM for those DMA groups so no space is wasted.

EDIT

The way you propose would have the data arranged like this in the ROM
Image

Do you see why this is inefficient?

This is the whole reason DMA groups are used in the first place! There are few scenarios where BL is directly after TR in rom. Think of Kong letters, for one.

EDIT 2
Let's start with this. Do you understand what a DMA group is?
Veteran Venturer
Bananas received 110
Posts: 605
Joined: 2016

PreviousNext

Return to ROM Hacking

Who is online

Users browsing this forum: No registered users and 0 guests