Page 4 of 4

Re: Sprite Graphics

PostPosted: July 15th, 2023, 10:26 am
by Cyclone
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...

Re: Sprite Graphics

PostPosted: July 15th, 2023, 11:52 am
by rainbowsprinklez
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

Re: Sprite Graphics

PostPosted: July 16th, 2023, 4:17 am
by Cyclone
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?

Re: Sprite Graphics

PostPosted: July 16th, 2023, 4:44 am
by rainbowsprinklez
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?

Re: Sprite Graphics

PostPosted: July 16th, 2023, 8:39 am
by Cyclone
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?

Re: Sprite Graphics

PostPosted: July 16th, 2023, 11:23 am
by rainbowsprinklez
Cyclone wrote:How do we know when we encounter a garbage cell?


Reread our previous convo in this thread. YOU successfully identified.

Re: Sprite Graphics

PostPosted: July 17th, 2023, 11:29 am
by Cyclone
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.

Re: Sprite Graphics

PostPosted: July 17th, 2023, 12:09 pm
by rainbowsprinklez
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?

Re: Sprite Graphics

PostPosted: July 17th, 2023, 12:46 pm
by Cyclone
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?

Re: Sprite Graphics

PostPosted: July 17th, 2023, 1:58 pm
by rainbowsprinklez
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.

Re: Sprite Graphics

PostPosted: July 17th, 2023, 2:09 pm
by Cyclone
Yes I did a quick search and found that.

Thanks!

Re: Sprite Graphics

PostPosted: September 15th, 2024, 12:42 pm
by Cyclone
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 5008 times


Problem Tile and Problem Sprite...

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


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

Re: Sprite Graphics

PostPosted: September 16th, 2024, 12:05 pm
by Cyclone
I fixed it, there is a value that is off in the rom....



593.png
593.png (763 Bytes) Viewed 4888 times