Sprite Graphics

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

Re: Sprite Graphics

Postby Cyclone » July 15th, 2023, 10:26 am

So i know how the tiles are ordered in the ROM according to your examples. But I'm not sure i understand how the second example wastes space.

I'm also not really sure what a DMA group is lol. Is it just groups of tiles?

Sorry for being dumb and thank you for your patience!



Edit.
Does it have anything to do with the game having to skip bytes when displaying the 2x2 chars in the second example? The one that wastes space...
Expedition Leader
Bananas received 559
Posts: 1253
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 15th, 2023, 11:52 am

Cyclone wrote:I'm also not really sure what a DMA group is lol. Is it just groups of tiles?

Sorry for being dumb and thank you for your patience!


Not dumb. You just don't know. Yes. DMa groups are just a group of tiles and where to put them in vram. If you run into garbage while there are still more tiles, a second DMA group is needed. Garbage space is not reflected in ROM. That is the key, i think. So the example is stored in ROM as

Image

After dividing the dma groups like i showed you, just remove all garbage space and the tiles are stored sequentially like that
Veteran Venturer
Bananas received 110
Posts: 596
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 16th, 2023, 4:17 am

hmmm... still hasn't clicked in my head yet.
What exactly are "garbage tiles" are they the ones in red in your previous image?

Edit...

When you said no space is wasted do you mean VRAM or the ROM?
Expedition Leader
Bananas received 559
Posts: 1253
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 16th, 2023, 4:44 am

Cyclone wrote:hmmm... still hasn't clicked in my head yet.
What exactly are "garbage tiles" are they the ones in red in your previous image?


Image

Tiles, chars, I hop back and forth between these names, but probably shouldn't.

Cyclone wrote:When you said no space is wasted do you mean VRAM or the ROM?


Think about it and tell me. Where are we cutting down on space used?
Veteran Venturer
Bananas received 110
Posts: 596
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 16th, 2023, 8:39 am

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


For clarification purposes what would this image look like without the garbage cells?

How do we know when we encounter a garbage cell?

rainbowsprinklez wrote:
Cyclone wrote:When you said no space is wasted do you mean VRAM or the ROM?


Think about it and tell me. Where are we cutting down on space used?


Not sure. I'm guessing the ROM...




Edit.

Are 16x16 sprites always arranged like that in the VRAM?
I mean the Left and Right tiles are on the first row and the bottom ones on the second row?
Expedition Leader
Bananas received 559
Posts: 1253
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 16th, 2023, 11:23 am

Cyclone wrote:How do we know when we encounter a garbage cell?


Reread our previous convo in this thread. YOU successfully identified.
Veteran Venturer
Bananas received 110
Posts: 596
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 17th, 2023, 11:29 am

Thanks for pointing me to the right direction. I think I understand it now... I think...

One thing though. What program did you use to view those sprites in VRAM with?
Reason is I want to write a tutorial.

Thanks again.
Expedition Leader
Bananas received 559
Posts: 1253
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 17th, 2023, 12:09 pm

Cyclone wrote:One thing though. What program did you use to view those sprites in VRAM with?
Reason is I want to write a tutorial.


You JUST said you are unsure if you 100% get this, do you really feel like you are equipped enough to write a tutorial? It sounds like you are sharing answers without fully understanding. I'm unsure, but something tells me that this is not the best idea right now. I recommend taking time to let it soak in. Mattrizzle? As an OG like Cyclone here, what are your thoughts?
Veteran Venturer
Bananas received 110
Posts: 596
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 17th, 2023, 12:46 pm

The tutorial is meant mainly for me.
It’s a way to sort out my thoughts.
Yes I am sharing things.

I already made a tutorial on bitplains and it has helped me a lot.

And I need to do the tutorial soon while it’s still in my head

Am I making sense?
Expedition Leader
Bananas received 559
Posts: 1253
Joined: 2008

Re: Sprite Graphics

Postby rainbowsprinklez » July 17th, 2023, 1:58 pm

Cyclone wrote:Am I making sense?


Yes. Ahh for you. Wish I did that myself. I just relearn things as I need them. Which is terribly inefficient.

***EDIT***
Those images were created with a combination of Mesen-S and Microsoft paint.
Veteran Venturer
Bananas received 110
Posts: 596
Joined: 2016

Re: Sprite Graphics

Postby Cyclone » July 17th, 2023, 2:09 pm

Yes I did a quick search and found that.

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

Re: Sprite Graphics

Postby Cyclone » September 15th, 2024, 12:42 pm

I'm having an issue with one row of a tile. I got the extraction working on most sprites so far except for this one below.
The top row of each tile is not writing to the png properly. I think its a problem with the bit set function?

Any ideas would be much appreciated. Thanks.

Seen here...

558_working_Sprite.png
558_working_Sprite.png (736 Bytes) Viewed 4879 times


Problem Tile and Problem Sprite...

Problem_Sprite.png
Problem_Sprite.png (785 Bytes) Viewed 4879 times


Problem_Tile.png
Problem_Tile.png (217 Bytes) Viewed 4879 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;
}

int main()
{
    const size_t width = 256, height = 256;
    const size_t no_elems = width * height * 4;
    using Image = std::vector<unsigned char>;
    std::vector<Image> Image_PNG(1000, 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;

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

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

    long long int address = 0x381C46;  // add 0xC00000 to get the SNES address.
    int offset = 0; // The location of the next set of sprites.
    int Data_Size = 0;
    int x_coord = 0;
    int y_coord = 0;
    int X;

        char oDataK[0x10000]; // Sprite buffer
        ifstream inFileK;
        inFileK.open("C:\\Users\\Chris\\Desktop\\dkc1.sfc", ios::binary); // Note. this opens a binary stream. 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(address + Data_Size, 1); // Seek to the current sprite header location.
        inFileK.read(oDataK, 0x10000);
        inFileK.close();

        int Header = 8;
        int tile_offset = 0;
        int Size_of_coordenants = (oDataK[0] + oDataK[1]) * 2;   // 0 contains the value of the number of 2x2 chars (16 x 16 pixel tiles). 1 contains the value of the number of 1x1 chars (8x8 pixel tiles). These two values are multiplied by 2 (two bytes for each set of coordenants).
        int Start_Of_First_Tile = Header + Size_of_coordenants;  // 8 is the size of the header. 6 is the total size of coordinates(3 chars (tiles) * 2 bytes for earch char) (these are also part of the header...)

       // Assign each Bitplane Row the data from the buffer. oData is the buffer containing the bytes from the rom.
        for (int p = 0, t = 0; t < 5; t++) // 16x16 Tiles
        {
            p = 24;
            tile_offset = (32 * 17);
           
            Bitplane0__ROW[p++] = oDataK[14 + Start_Of_First_Tile + tile_offset ];
            Bitplane0__ROW[p++] = oDataK[12 + Start_Of_First_Tile + tile_offset  ];
            Bitplane0__ROW[p++] = oDataK[10 + Start_Of_First_Tile + tile_offset  ];
            Bitplane0__ROW[p++] = oDataK[8 + Start_Of_First_Tile + tile_offset  ];
            Bitplane0__ROW[p++] = oDataK[6 + Start_Of_First_Tile + tile_offset  ];
            Bitplane0__ROW[p++] = oDataK[4 + Start_Of_First_Tile + tile_offset  ];
            Bitplane0__ROW[p++] = oDataK[2 + Start_Of_First_Tile + tile_offset  ];
            Bitplane0__ROW[p++] = oDataK[0 + Start_Of_First_Tile + tile_offset  ];

            p = 24;

            Bitplane1__ROW[p++] = oDataK[15 + Start_Of_First_Tile + tile_offset  ];
            Bitplane1__ROW[p++] = oDataK[13 + Start_Of_First_Tile + tile_offset  ];
            Bitplane1__ROW[p++] = oDataK[11 + Start_Of_First_Tile + tile_offset  ];
            Bitplane1__ROW[p++] = oDataK[9 + Start_Of_First_Tile + tile_offset  ];
            Bitplane1__ROW[p++] = oDataK[7 + Start_Of_First_Tile + tile_offset  ];
            Bitplane1__ROW[p++] = oDataK[5 + Start_Of_First_Tile + tile_offset  ];
            Bitplane1__ROW[p++] = oDataK[3 + Start_Of_First_Tile + tile_offset  ];
            Bitplane1__ROW[p++] = oDataK[1 + Start_Of_First_Tile + tile_offset  ];


            p = 24;

            Bitplane2__ROW[p++] = oDataK[30 + Start_Of_First_Tile + tile_offset  ];
            Bitplane2__ROW[p++] = oDataK[28 + Start_Of_First_Tile + tile_offset  ];
            Bitplane2__ROW[p++] = oDataK[26 + Start_Of_First_Tile + tile_offset  ];
            Bitplane2__ROW[p++] = oDataK[24 + Start_Of_First_Tile + tile_offset  ];
            Bitplane2__ROW[p++] = oDataK[22 + Start_Of_First_Tile + tile_offset  ];
            Bitplane2__ROW[p++] = oDataK[20 + Start_Of_First_Tile + tile_offset  ];
            Bitplane2__ROW[p++] = oDataK[18 + Start_Of_First_Tile + tile_offset  ];
            Bitplane2__ROW[p++] = oDataK[16 + Start_Of_First_Tile + tile_offset  ];

            p = 24;

            Bitplane3__ROW[p++] = oDataK[31 + Start_Of_First_Tile + tile_offset  ];
            Bitplane3__ROW[p++] = oDataK[29 + Start_Of_First_Tile + tile_offset  ];
            Bitplane3__ROW[p++] = oDataK[27 + Start_Of_First_Tile + tile_offset  ];
            Bitplane3__ROW[p++] = oDataK[25 + Start_Of_First_Tile + tile_offset  ];
            Bitplane3__ROW[p++] = oDataK[23 + Start_Of_First_Tile + tile_offset  ];
            Bitplane3__ROW[p++] = oDataK[21 + Start_Of_First_Tile + tile_offset  ];
            Bitplane3__ROW[p++] = oDataK[19 + Start_Of_First_Tile + tile_offset  ];
            Bitplane3__ROW[p++] = oDataK[17 + Start_Of_First_Tile + tile_offset  ];

        }

        /////////////////////////////////////////////////////////////////////////////////////////////////

        Start_Of_First_Tile = Start_Of_First_Tile + Data_Size; // the location of the curent sprite.
        int c = 0;
        for (int p = 24 ; p < 32; p++)
        {
                // Bottom Right of 16x16
                if (p == 24) { c = 256 * (y_coord + 15) * 4 + x_coord + 0 + 0;; }
                if (p == 25) { c = 256 * (y_coord + 14) * 4 + x_coord + 0 + 0;; }
                if (p == 26) { c = 256 * (y_coord + 13) * 4 + x_coord + 0 + 0;; }
                if (p == 27) { c = 256 * (y_coord + 12) * 4 + x_coord + 0 + 0;; }
                if (p == 28) { c = 256 * (y_coord + 11) * 4 + x_coord + 0 + 0;; }
                if (p == 29) { c = 256 * (y_coord + 10) * 4 + x_coord + 0 + 0;; }
                if (p == 30) { c = 256 * (y_coord + 9) * 4 + x_coord + 0 + 0;; }
                if (p == 31) { c = 256 * (y_coord + 8) * 4 + x_coord + 0 + 0;; }

                // Write the PNG Images
                if (p < 32)
                {
                    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_PNG[X][c++] = coloursB[Index][0]; // Red
                        Image_PNG[X][c++] = coloursB[Index][1]; // Green
                        Image_PNG[X][c++] = coloursB[Index][2]; // Blue
                        Image_PNG[X][c++] = coloursB[Index][3]; // Alpha   
                    }
                } 
        }
             string combined_file_path(string(filepath) + to_string(X) + ".png");
            encodeOneStep(combined_file_path.c_str(), Image_PNG[X], width, height);  // Write the .png image file.
       
    return 0;
}
Expedition Leader
Bananas received 559
Posts: 1253
Joined: 2008

Re: Sprite Graphics

Postby Cyclone » September 16th, 2024, 12:05 pm

I fixed it, there is a value that is off in the rom....



593.png
593.png (763 Bytes) Viewed 4759 times
Expedition Leader
Bananas received 559
Posts: 1253
Joined: 2008

Previous

Return to ROM Hacking

Who is online

Users browsing this forum: No registered users and 1 guest