|
Post by matthew on Feb 1, 2020 17:37:33 GMT -8
Ok, this is gonna sound kinda weird but I hope you all can help. I load a set of assets at the program start using the LoadAssets() define. 2 of these assets are sprites that I would like to change to different sprites during run time from data sent to this module from across a network. I create the 'new' asset using the gd3asset maker using a sprite that is the exact same size and color depth. I get the data to the module, but then I don't know how I would replace the existing asset. I have tried the following..
memcpy(spriteImageData, networkCommandBuffer, dataLength.inputInt);
GD.BitmapHandle(12);
GD.cmd_loadimage(0x6f5e4UL, 0);
GD.copyram(spriteImageData, dataLength.inputInt);
I get the data from the buffer. I thought I need to select the handle, and then I thought loadimage would set the address where that asset would be located and try to replace it using copyram. Of course none of this works. If there is a way to do this, I would love to hear any ideas or if in general anyone has a better idea of how to accomplish this goal, please let me know!! I can provide more info or code detail if that would help.
|
|
|
Post by jamesbowman on Feb 1, 2020 18:08:10 GMT -8
That's roughly correct. One thing is that cmd_loadimage() expects the data following it to be either a PNG or a JPG.
So you might send a PNG for the sprite over the network, then do:
memcpy(pngImageData, networkCommandBuffer, dataLength.inputInt); GD.BitmapHandle(12); GD.cmd_loadimage(0x6f5e4UL, 0); GD.copyram(pngImageData, dataLength.inputInt); So the GPU sees a "cmd_loadimage()" followed by the image data. It decodes the PNG or JPG data, and sets all the bitmap parameters properly. In this case handle 12 will be ready to draw the sprite:
GD.Begin(BITMAPS); GD.Vertex2ii(10, 10, 12, 0);
|
|
|
Post by matthew on Feb 1, 2020 22:56:50 GMT -8
Ok, this did get me going in the right direction. I can now send PNG files over to the module and they display in the place of the original sprite. So I took out the sprite from the original asset data and now only use the PNG data that is sent, but the only way I could get this to work either way was to use:
GD.cmd_loadimage(-1, 0);
Now I know this is just appending to the end of the video ram and after intentionally sending it a PNG a lot of times, it did overflow the memory and crash as expected. I tried to use ASSETS_END as the pointer, but this didn't work either. Is there a way to use the -1 option the first time and then retrieve the pointer for that handle so I can overwrite the same location later?
|
|
|
Post by jamesbowman on Feb 2, 2020 7:32:24 GMT -8
Yes, there is a command "getprops" which returns some of the parameters of the last image loaded. It returns the base pointer, width and height of the image. You can use these to compute the start of free memory by:
base + 2 * width * height
Here's an example:
GD.cmd_loadimage(-1, 0); GD.load("healsky3.jpg");
uint32_t base, w, h; GD.cmd_getprops(base, w, h); GD.finish(); printf("healsky3.jpg is at %6d (%d x %d)\n", GD.rd32(base), GD.rd16(w), GD.rd16(h));
GD.cmd_loadimage(-1, 0); GD.load("tree.jpg"); GD.cmd_getprops(base, w, h); GD.finish(); printf("tree.jpg is at %6d (%d x %d)\n", GD.rd32(base), GD.rd16(w), GD.rd16(h));
printf("free memory is at %6d\n", GD.rd32(base) + 2 * GD.rd16(w) * GD.rd16(h));
which displays
healsky3.jpg is at 0 (128 x 128) tree.jpg is at 32768 (480 x 272) free memory is at 293888
|
|
|
Post by matthew on Feb 2, 2020 13:24:50 GMT -8
Ok, this has been the most helpful!! I have sent now a ton of PNG data and it seems to always work right. The first time through have it get the first available free spot using -1 and then after that I reuse the address that was assigned. See below for the weird part though.
uint32_t sprite_base; Boolean hasSpriteData;
… … …
case SpriteImageData: { if (debugMode) { Serial.print("Sprite Data Size: "); Serial.println(dataLength.inputInt); }
GD.BitmapHandle(12);
uint32_t base, w, h;
if (hasSpriteData) { GD.cmd_loadimage(sprite_base, 0); GD.copyram(networkCommandBuffer, dataLength.inputInt); } else { GD.cmd_loadimage(-1, 0); GD.copyram(networkCommandBuffer, dataLength.inputInt);
GD.cmd_getprops(base, w, h); sprite_base = GD.rd32(base); }
if (debugMode) { Serial.print("Sprite Address: "); Serial.println(sprite_base); }
hasSpriteData = true; break; } results in:
Sprite Data Size: 1539
Sprite Address: 0
Sprite Data Size: 1432
Sprite Address: 0
Sprite Data Size: 1617
Sprite Address: 0
Sprite Data Size: 1071
Sprite Address: 0
I am a little confused why the address always shows 0. I do load 11 assets at the beginning of the program so I would have expected the 0 to be a bigger number after the -1 would have found the first empty space. Maybe I'm reading this wrong.
But, like I said at the top, this seems to be working perfectly so far! So if you see anything else I might be doing wrong, would love the input, but otherwise THANK YOU for your time!!
|
|