|
Post by hyperfighting on Jul 19, 2022 16:50:16 GMT
0x8bitdev - Oh man this is a game changer! I see I will need to change my HuC calls to SPReD library calls now. My plan is to work with the version before this release for now. I am grinding through refactoring 1 size fits all animation system removing code bloat etc. Once that's in a clean state and the previous routines are functional. I will circle back and attempt to integrate the new and true SPReD Library calls! I'm so excited offsets are integrated with simple sprites...I have been making my own provisions with the basic HuC calls.... Awwww screw it (thought just shifted lol).....no time like the present...I'll start ripping my code apart and plugging in the new SPReD conventions! CRAZY!!!!!!
|
|
|
Post by hyperfighting on Jul 19, 2022 20:14:03 GMT
0x8bitdev - I have re-exported all of my projects and made change regarding the "'_frame' postfix" everything is compiling and running great! I am performing a test and I'm having trouble with getting the GFX to display at an address other than the exported value. The code below works fine with "0x2000 (exported value)" but when I change the value the gfx are garbled. load_palette( SPRED_ZUK_PALETTE_SLOT, SPReD_ZUK_palette, SPRED_ZUK_PALETTE_SIZE) spd_sprite_params( SPReD_ZUK_SG_arr, 0x2000, SPD_FLAG_IGNORE_SG, 0xff); spd_copy_SG_data_to_VRAM( SPReD_ZUK_frames_data, 0 );
/* set the SATB position to push sprites to */ spd_SATB_set_pos( 45 ); //spd_alt_VRAM_addr(0x6000); /////I think I might need this was thinking just changing the value 0x2000 above might be good enough spd_SATB_set_sprite_LT( SPReD_ZUK_frames_data, 0, 50, 50); spd_set_palette_LT( 4 ); spd_SATB_to_VRAM();
Up until now my method for swapping data in and out of VRAM has been using this initialization and then handling the rest with HuC calls. In this case I have no issue with the alternate vram address but the case of using the new library calls has me stumpted. spd_sprite_params( SPReD_ZUK_SG_arr, slot.vramLoc[vramSlot], SPD_FLAG_IGNORE_SG, 0xff); spd_copy_SG_data_to_VRAM( SPReD_ZUK_frames_data, actor.frameset[slot.firstActor[vramSlot]] );
|
|
|
Post by 0x8bitdev on Jul 20, 2022 10:31:06 GMT
hyperfighting , the functions order should be as follows (like in the sample projects): 1) spd_sprite_params(...)
2) spd_alt_VRAM_addr(...)
and then:
spd_copy_SG_data_to_VRAM(...)
spd_SATB_push_sprite(...)
spd_SATB_set_sprite_LT(...) ' spd_alt_VRAM_addr(...)' - replaces exported VADDR that was passed to ' spd_sprite_params(...)' and calculates a pattern code correction value. So, after that all calls to: spd_copy_SG_data_to_VRAM(...)
and/or
spd_SATB_push_sprite(...)
and/or
spd_SATB_set_sprite_LT(...)
...will give you the right result. Once again, in short. If you want to make a sprite instances in VRAM, you need to call these two functions for each instance:
1) spd_sprite_params(...)
2) spd_alt_VRAM_addr(...) and after that you can load SG to VRAM, push your sprites to SATB etc...
|
|
|
Post by turboxray on Jul 20, 2022 16:07:40 GMT
I'm just looking at your color #0 benchmark and the number of lines it's taking. And then matching them up the metasprites you have on screen. Are the scanline groups not representative of the entire meta-sprite decode call? Not the most accurate way. You can be wrong by ~2 lines. Because the benchmark lines can start and end in the middle of the screen where you can't see them. Each scanline group is representative of the entire meta-sprite decode call. And a meta-sprite cells transformation loop takes up a significant part, but not all. There are some other things need to be done, like: meta-sprite data indexing in an array for animated sprites +bank switching, XY coordinates correction, mapping meta-sprite data, checking SATB overflow, other minor checks like double-buffering, SG need to be loaded or not, calculating SATB address for the next sprite. All this simple things also take a certain amount of time. I subtracted like 1 to 1.5 lines from the count because of that. Correlating it to that (your overall process), I got numbers like ~350 cycles per cell in the end. That seems a bit excessive/expensive. Do you have any ideas/plans for optimizations??
|
|
|
Post by hyperfighting on Jul 20, 2022 16:43:44 GMT
0x8bitdev Thanks for clearing this up! I did do my best at reviewing the sample projects but I got lost Again thanks very much for your breakdown time and patience! Next question is this.... Of course I could be very wrong.... It seems to me to use the new library calls I need to do something to this effect for every cycle. If this is accurate my concern is calling the top 3 functions on a per cycle basis per sprite. //On every cycle spd_sprite_params( SPReD_ZUK_SG_arr, EXPORTED_VALUE, SPD_FLAG_IGNORE_SG, 0xff); spd_alt_VRAM_addr(ANY_ADDRESS); spd_copy_SG_data_to_VRAM( SPReD_ZUK_frames_data, FRAME_SET); //Concerned calling these 3 lines every cycle
spd_SATB_set_pos(spriteIndex); spd_SATB_set_sprite_LT( SPReD_ZUK_frames_data, FRAME_NUMBER, X, Y); spd_SATB_to_VRAM(); In my current implementation using HuC calls I only call SPReD library calls when a new animation set is triggered. So the code below executes when new information is loaded to VRAM. //Only when triggering new animation frames void ONLY_ON_NEW_ANIMATION { spd_sprite_params( SPReD_ZUK_SG_arr, ANY_ADDRESS, SPD_FLAG_IGNORE_SG, 0xff); spd_copy_SG_data_to_VRAM( SPReD_ZUK_frames_data, FRAME_SET ); }
//On every cycle spr_set(spriteIndex); //Update Sprite Pattern after ticks have elapsed "spr_pattern(..);" spr_x(X);//I get I am losing the exported offset with these basic calls spr_y(Y);//I get I am losing the exported offset with these basic calls satb_update();//It appears I can subsitute this "spd_SATB_to_VRAM();" at no consequence potentially faster call than satb_update?
Would my HuC method be quicker given I use "spd_sprite_params (....), spd_copy_SG_data_to_VRAM(...)" only on animation changes and I don't need "spd_alt_VRAM_addr(...);" in this case? Sorry if this sounds stupid...I'm likely missing something.
|
|
|
Post by 0x8bitdev on Jul 22, 2022 15:52:38 GMT
I subtracted like 1 to 1.5 lines from the count because of that. Correlating it to that (your overall process), I got numbers like ~350 cycles per cell in the end. That seems a bit excessive/expensive. Do you have any ideas/plans for optimizations?? Since the time you asked the question, I did some optimizations: changed ASM format to simplify sprite data indexing for animated sprites +other changes. And the changes have speed upped more non-animated meta-sprites than animated. Also I added 'cyan' color to the benchmark lines. And now you can see how long meta-sprite transformation takes up. You can compare the results. Updated .PCE binaries of the samples you can find in the dev build ( .samples/pce/bin/animation_test_huc3.pce). BTW, how many cycles one scanline takes? [upd]: ~350 cycles to transform one meta-sprite cell is too much... 1 transformation iteration doesn't take so.
|
|
|
Post by dshadoff on Jul 22, 2022 17:18:41 GMT
BTW, how many cycles one scanline takes? My calculations have it at 1365 "master clock" cycles (master clock is ~21.48 MHz). This puts it at 455 CPU clock cycles (when running at ~7.16MHz, which it is nearly always running at).
|
|
|
Post by 0x8bitdev on Jul 22, 2022 17:53:45 GMT
hyperfighting , You can copy SG data to VRAM every frame if you have 60 frames per second animations. I guess this is not your case. Don't do things you shouldn't do if you want your program to run fast. Use SPD_DEBUG. Nothing changed for you. The new library functions do not change your program logic. Just replace your calls with the new ones. If you need sprite graphics -> load it to VRAM. If you don't need it -> don't load it to VRAM. You can do the same things without HuC functions: 1. Set sprite data, reserve SATB slot - ' spd_SATB_set_pos', preload SG to VRAM manually or automatically with sprite attributes calling ' spd_SATB_set_sprite_LT' and then in update loop ' spd_SATB_set_pos' + spd_set_x_LT() / spd_set_y_LT()
OR 2. In update loop: set sprite data with a last SG bank value to avoid SG data loading to VRAM on each call ' spd_SATB_set_sprite_LT' and don't use spd_set_x_LT() / spd_set_y_LT() if you use sprite offsets. (1) is faster than (2). Writing 2-3 values directly to SATB is always faster than calling something complex like ' spd_SATB_push_sprite' or ' spd_SATB_set_sprite_LT'. Once again, the only rule for perfomance - don't do unnecessary things! If you want to use a sprite instancing -> preload SG data VRAM once and then use it. Don't load the same SG data to VRAM every frame.
|
|
|
Post by 0x8bitdev on Jul 22, 2022 17:59:02 GMT
The new update for SPReD-PCE
- Added the palettes manager (Main Menu->Palette->Manager) - Added red markers to active palettes - Added palettes reset when closing a project - Improved 'Swap Colors' (also in the MAPeD-PCE)
As usual the changes in the dev build.
|
|
|
Post by 0x8bitdev on Jul 22, 2022 18:08:08 GMT
BTW, how many cycles one scanline takes? My calculations have it at 1365 "master clock" cycles (master clock is ~21.48 MHz). This puts it at 455 CPU clock cycles (when running at ~7.16MHz, which it is nearly always running at). Thanks! With your calculations a meta-sprite cell transformation takes up ~200 cycles ( not ~350 ). And this is a correct value for a meta-sprite that needs a pattern code correction. This is a meta-sprite instancing case.
|
|
|
Post by hyperfighting on Jul 23, 2022 15:35:31 GMT
0x8bitdev - Incredible work on the Palette Manager. It looks Wicked. Reordering pals is gonna be very very handy! The streamlined "swap" is also slick! Is there a way to delete palettes? Some of my SPReD projects have additional palettes due to the File>Close bug you just squashed. I can re-build these projects just curious if deleting palettes is an option. [upd] Also many thanks on the breakdown for the new SPReD library calls I will definitely integrate the new calls!
|
|
|
Post by 0x8bitdev on Jul 24, 2022 7:46:36 GMT
Is there a way to delete palettes? No, you can't delete what you can't add. Use copy/paste of the blank palette. BTW, inactive palettes don't affect anything.
|
|
|
Post by hyperfighting on Jul 24, 2022 22:27:21 GMT
0x8bitdev Geez! Of course! Copy/Paste of the blank palette is an easy fix! Thanks for the heads up!
|
|
|
Post by hyperfighting on Jul 29, 2022 15:48:59 GMT
0x8bitdev - Ok I know I'm gonna be in trouble for asking but I'm stuck.... I have the big Zuks! logo (Meta Sprite) and the Cloud(s) (also Meta Sprite...) Both are saved in the same SPReD project I can make them appear separately but when I combine my codez together....the VRAM for the Zuks logo gets overwritten To make the Zuks! logo appear I init this: spd_sprite_params( SPReD_STATIC_SG_arr, EXPORTED_VRAM_LOCATION, SPD_FLAG_IGNORE_SG, 0xff); // spd_alt_VRAM_addr(0x6000); Also tried this so both Logo and clouds have an alt address..... spd_copy_SG_data_to_VRAM( SPReD_STATIC_frames_data, SPR_ZUKS_TITLE );
spd_SATB_set_pos( 20 ); spd_SATB_push_sprite( ZUKS_TITLE, block.x[0], block.y[0]); and loop this: spd_SATB_set_pos( 20 ); spd_SATB_push_sprite( ZUKS_TITLE, block.x[0], block.y[0]); Then as the Map Scrolls I init this for the Clouds to appear: spd_sprite_params( SPReD_STATIC_SG_arr, EXPORTED_VRAM_LOCATION, SPD_FLAG_IGNORE_SG, 0xff); spd_alt_VRAM_addr(0x5500);<-Trying to load cloud frame here...I'm guessing the entire Zuks! Logo and cloud is loading here? and overwriting the 0x6000 (EXPORTED_VRAM_LOCATION) spd_copy_SG_data_to_VRAM( SPReD_STATIC_frames_data, SPR_CLOUD );
spd_SATB_set_pos( 0 ); spd_SATB_push_sprite( CLOUD, block.x[17], block.y[17]); spd_SATB_push_sprite( CLOUD, block.x[18], block.y[18]); spd_SATB_push_sprite( CLOUD, block.x[19], block.y[18]); spd_SATB_push_sprite( CLOUD, block.x[7], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[9], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[11], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[13], block.y[8]); spd_SATB_push_sprite( CLOUD, block.x[15], block.y[8]); and loop this: spd_SATB_set_pos( 0 ); spd_SATB_push_sprite( CLOUD, block.x[17], block.y[17]); spd_SATB_push_sprite( CLOUD, block.x[18], block.y[18]); spd_SATB_push_sprite( CLOUD, block.x[19], block.y[18]); spd_SATB_push_sprite( CLOUD, block.x[7], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[9], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[11], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[13], block.y[8]); spd_SATB_push_sprite( CLOUD, block.x[15], block.y[8]); Bottom of the loop has this spd_SATB_to_VRAM(); In the end the Zuks! logo appears perfect but when the cloud is initalized the Zuks! Logo gets garbled but the clouds render perfectly... I'm sorry in advance... Little Video describing the troubles
|
|
|
Post by 0x8bitdev on Jul 30, 2022 15:41:51 GMT
I can make them appear separately but when I combine my codez together....the VRAM for the Zuks logo gets overwritten How did you determine that VRAM for the Zuks logo was overwritten? From your video I saw that the logo VRAM wasn't overwritten. Do you use the Mednaffen debugger? Don't trust yourself, trust debugger. Debugger doesn't lie and gives you the right chain of reasoning. I can understand the problem without debugger, but you can't so far. Watching graphics in VRAM is elementary. That is not debugging assembly code. So always use debugger and even if everything seems right. So many words 'debugger'. I hope that was catchy for your mind. Because debugger is a programmer eyes. The video matches your code completely. The problem of your code is that you don't use the correct VRAM address for the logo. You are doing the following: // preload the logo gfx set_sprite_params(...exported_VADDR...) <--- !!! spd_copy_SG_data_to_VRAM(...)
... // push the logo attributes into SATB spd_SATB_push_sprite( logo_gfx ) ...
// preload the cloud gfx set_sprite_params(...) spd_alt_VRAM_addr(...new_VADDR...) <--- !!! spd_copy_SG_data_to_VRAM(...)
... // push the cloud attributes into SATB spd_SATB_push_sprite( cloud_gfx ) spd_SATB_push_sprite( cloud_gfx ) ...
// and then again... logo spd_SATB_push_sprite( logo_gfx ) <--- what VADDR will be used for the logo? do you think the exported one?! no, the last one -> 'spd_alt_VRAM_addr(...new_VADDR...)'
...
The correct code looks like this: The logo: // preload the logo gfx
spd_sprite_params( SPReD_STATIC_SG_arr, EXPORTED_VRAM_LOCATION, SPD_FLAG_IGNORE_SG, 0xff); spd_copy_SG_data_to_VRAM( SPReD_STATIC_frames_data, SPR_ZUKS_TITLE );
// this was useful for simple sprites, when you preload sprite attributes and then transform coordinates in update loop. // this doesn't make any sense for meta-sprites... // //spd_SATB_set_pos( 20 ); //spd_SATB_push_sprite( ZUKS_TITLE, block.x[0], block.y[0]); Then in loop: spd_sprite_params( SPReD_STATIC_SG_arr, EXPORTED_VRAM_LOCATION, SPD_FLAG_IGNORE_SG, 0xff); <--- !!!
spd_SATB_set_pos( 20 ); <--- *** spd_SATB_push_sprite( ZUKS_TITLE, block.x[0], block.y[0]); *** Using fixed SATB positions was good idea for simple sprites. But when you are using meta-sprites, you can call 'spd_SATB_set_pos( 0 )' at the beginning of your update loop and then call 'spd_SATB_push_sprite(...)' for each meta-sprite without setting the SATB position. The cloud(s): // preload the cloud gfx spd_sprite_params( SPReD_STATIC_SG_arr, EXPORTED_VRAM_LOCATION, SPD_FLAG_IGNORE_SG, 0xff); spd_alt_VRAM_addr(0x5500); spd_copy_SG_data_to_VRAM( SPReD_STATIC_frames_data, SPR_CLOUD );
// the same here. this doesn't make any sense for meta-sprites... // //spd_SATB_set_pos( 0 ); //spd_SATB_push_sprite( CLOUD, block.x[17], block.y[17]); //spd_SATB_push_sprite( CLOUD, block.x[18], block.y[18]); //spd_SATB_push_sprite( CLOUD, block.x[19], block.y[18]); //spd_SATB_push_sprite( CLOUD, block.x[7], block.y[7]); //spd_SATB_push_sprite( CLOUD, block.x[9], block.y[7]); //spd_SATB_push_sprite( CLOUD, block.x[11], block.y[7]); //spd_SATB_push_sprite( CLOUD, block.x[13], block.y[8]); //spd_SATB_push_sprite( CLOUD, block.x[15], block.y[8]); Then in loop: spd_sprite_params( SPReD_STATIC_SG_arr, EXPORTED_VRAM_LOCATION, SPD_FLAG_IGNORE_SG, 0xff); <--- !!! spd_alt_VRAM_addr(0x5500); <--- !!! spd_SATB_set_pos( 0 ); <--- *** spd_SATB_push_sprite( CLOUD, block.x[17], block.y[17]); spd_SATB_push_sprite( CLOUD, block.x[18], block.y[18]); spd_SATB_push_sprite( CLOUD, block.x[19], block.y[18]); spd_SATB_push_sprite( CLOUD, block.x[7], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[9], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[11], block.y[7]); spd_SATB_push_sprite( CLOUD, block.x[13], block.y[8]); spd_SATB_push_sprite( CLOUD, block.x[15], block.y[8]); The same you can see in the meta-sprites instancing sample with Double Dragon's guys. // for instance #1 spd_sprite_params(...) spd_alt_VRAM_addr(...) spd_SATB_push_sprite(...)
...
// for instance #2 spd_sprite_params(...) spd_alt_VRAM_addr(...) spd_SATB_push_sprite(...)
... etc
You are doing the same instancing, but per meta-sprite frame.
|
|