|
Post by 0x8bitdev on Dec 28, 2022 8:53:17 GMT
Last update before the big break.
MAPeD v0.76b
The main changes:
- Layout viewport: hardware-accelerated rendering using OpenGL (OpenTK/SkiaSharp) - Overall performance improvement - Layout tab -> Painter tab: added functionality for user-selected screens: "Fill With Tile" and "Replace Tiles" - Layout tab: Map scaling: Press '1' - 100%, '2' - 200% - Layout tab -> Painter tab: 'Escape' to cancel an active tile - Layout tab -> Entities tab: 'Escape' to switch to the 'Edit Instances' mode, when the 'Edit Entity' mode is active - Layout tab -> Patterns tab: 'Escape' to cancel an active tile pattern - Layout tab -> Painter tab: fixed the bug with incorrect generation of 4x4 tiles, when painting using 2x2 blocks
All the changes in the dev build.
Happy New Year everyone!
|
|
|
Post by hyperfighting on Jan 23, 2023 15:35:15 GMT
0x8bitdev - Haaaaaapy New Year! We made it to the other side lol. I think I found a little bug in MAPeD v.076b this is also true in MAPeD v.074b Ok so here goes... Layout > Builder In my case I have 9 layouts 0-8 I wanted to adjust layout 3 to be 1 screen high. the Dim is 2x2. So I pressed "-U" As soon as I do this three things happen... 1. the new dim is now 2x1 (the desired effect) 2. the second screen has a different screen assigned. 3. Layouts 4-8 are all shuffled to have different screen layouts. This is the file I am using... Test MAPeD file
**Edit Feedback on MAPeD v.076B Now that I've had an opportunity to really bite into MAPeD v.076B I have some feedback. Overall I would say aside from having issues resizing existing layouts the new GUI design is excellent! This product is damn near perfect in my eyes... Welcome changes...
Full Screen Mode is amazing! The Layout Tab is a very clean way of editing the Map Data! This is much more intuitive than the original design! Very free flowing and smooth to use! Some suggestions
1. As I see it the "Patterns" Tab is an extension of the "Painter Tab" you are essentially painting with Patterns. Possibility 1 build the "Patterns Tab" into the "Painter Tab" - It looks like the "Painter Tab" has the space to facilitate this. Possibility 2 place the "Patterns Tab" beside "Painter Tab" - Both have Painting functionality. Feature Requests for what they are worth1. Palette Slot Selection on import Assuming I have a tileset with several screens and layouts built then you want to import more tiles into that set. Currently "plt#00" always adopts the palette of the imported image. This will mess up what you currently have going on assuming your palette "plt#00" is set up correctly. If at the time the import button is pressed EX: "plt#05" is selected the imported images palette will be imported into that slot not affecting the other palettes. Another option is to build an option of "start palette" into the import screen. 2. Colour picker The picker is mini. It is functional but the ability see the colours at a larger magnification would help for selecting the appropriate colour. Palettes 1,2,3,4 - Manipulating colours - EX: Typing values in after double clicking a colour / The ability to copy and paste colour values 3. Animated Tiles.... (I know this no small feat) Another "Painter Style Tab" or a feature within the painter tab. Allows the user to give multiple frames to a tiles set. There are two practical uses for this: Aesthetics EX: 16x16 Tile has 4 Frames as the game runs the tiles cycle 1,2,3,4 and loop again and again. Gameplay EX: 16x16 Tile has 2 Frames. Frame 1 is a solid block with a property ID of 1. Frame 2 is a blank block with a property ID of 0. As the blocks cycle per a user defined time the player must land the block before it disappears (EX: Curtesy of the Megaman series.) **Edit 4. Preferences In the "Builder Tab" I find myself turning off the Marks and the Grid checkbox every time I open MAPeD. If MAPeD remembered the state of the checkboxes from the last session that would be helpful.
|
|
|
Post by 0x8bitdev on Feb 6, 2023 9:21:27 GMT
I think I found a little bug in MAPeD v.076b this is also true in MAPeD v.074b Thanks for the bug report. Fixed! Possibility 2 place the "Patterns Tab" beside "Painter Tab" - Both have Painting functionality. Ok. I'll change the tabs order. 1. Palette Slot Selection on import Ok. I'll do it. 2. Colour picker The picker is mini. It is functional but the ability see the colours at a larger magnification would help for selecting the appropriate colour. Palettes 1,2,3,4 - Manipulating colours - EX: Typing values in after double clicking a colour / The ability to copy and paste colour values The palette question is still open. The colors magnifier can be a good solution. But I think it will not help much for selecting the appropriate color. In my experience I know that dynamic color selection is much more obvious and convenient. Hold down the left mouse button + mouse move on the main palette and you'll see how the color changes dynamically at the small palette/CHR bank/Block editor/Tile editor simultaneously. I'll think what to do with the colors copy/paste. 3. Animated Tiles.... (I know this no small feat) Another "Painter Style Tab" or a feature within the painter tab. Allows the user to give multiple frames to a tiles set. There are two practical uses for this: Aesthetics EX: 16x16 Tile has 4 Frames as the game runs the tiles cycle 1,2,3,4 and loop again and again. Gameplay EX: 16x16 Tile has 2 Frames. Frame 1 is a solid block with a property ID of 1. Frame 2 is a blank block with a property ID of 0. As the blocks cycle per a user defined time the player must land the block before it disappears (EX: Curtesy of the Megaman series.) **Edit What you have described here it is better implement at the entities basis. Old consoles in platform games do not redraw the entire screen per frame. So the fact that you dynamically changed the contents of your map will not instantly reflect it on the screen. You need to control the visibility of that dynamic blocks manually in your engine. And at the entities basis you can use sprites or write tiles directly into BAT memory, as you wish. 4. Preferences In the "Builder Tab" I find myself turning off the Marks and the Grid checkbox every time I open MAPeD. If MAPeD remembered the state of the checkboxes from the last session that would be helpful. Done!
|
|
|
Post by hyperfighting on Feb 6, 2023 16:16:19 GMT
0x8bitdev - I keeping trying to upload my max score 5.0 GamePro Magazine image but it won't let me for some reason lol I guess these changes are so off the charts not even that image can do them justice! Thanks for reviewing and implementing!!!! I'm still behind on SPReD testing I resaved all of my Sprites in the new format but had a complication with my code base so I reverted for the time being. I'm very excited about the ability to 'only include palette data and exclude gfx data if desired' not to mention the new optimal format!!!! Thanks again! (My pseudo GamePro review image)
|
|
|
Post by 0x8bitdev on Feb 12, 2023 9:18:48 GMT
As I promised, the small changes:
- MAPeD/SPReD: User palette: copy/paste the selected color using context menu - MAPeD: Image import: added the start palette slot to the image import options - MAPeD: Layout tab: reordered tool tabs
|
|
|
Post by hyperfighting on Feb 14, 2023 23:32:27 GMT
0x8bitdev - I tried out the previous version of MAPeD and the fix for the layout resizing works awesome! Also the preferences on the Marks, Grid feel great! I know the palette import and color copy will be very useful!!!! Thanks again!
|
|
|
Post by hyperfighting on Feb 24, 2023 2:56:41 GMT
0x8bitdev - I have a question regarding targeting and loading a single palette from a set of palettes. Currently I am loading a palette set with this function. void LoadPal_Zuk(unsigned char SLOT_ID) { load_palette( SLOT_ID+16, SPReD_ZUK_palette, SPRED_ZUK_PALETTE_SIZE); } It works great! It lets me load my palette data into any of the 16 slots. Assuming this palette data is a set of 8 palettes. Currently the function will load all 8 palettes sequentially starting with the slot I identify as SLOT_ID If I only want to load palette 4 into the slot I have identified as SLOT_ID is there a way to do this? **Edit - My apologies! I should have dug deeper before posting this question! This does the trick - Info was located in my "SPReD_ZUK.h" exported from SPReD! void LoadPal_Zuk_Pal4(unsigned char SLOT_ID) { load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot4, 1); } I guess the question changed to - is the smoothest way to access this palette set of 8 as separate palettes to make 8 separate functions.... whereby the parameter above "SPReD_ZUK_palette_slot4" is modified to represent the targeted palette? void LoadPal_Zuk_Pal0(unsigned char PAL_ID) void LoadPal_Zuk_Pal1(unsigned char PAL_ID) void LoadPal_Zuk_Pal2(unsigned char PAL_ID) void LoadPal_Zuk_Pal3(unsigned char PAL_ID) void LoadPal_Zuk_Pal4(unsigned char PAL_ID) etc...? Or could the function take an additional parameter that is used to target the desired palette? I would love to do something like this but I don't know what value PAL_ID would need to be to increment to the next palette. void Load_One_Zuk_Pal(unsigned char SLOT_ID, unsigned short PAL_ID) { load_palette( SLOT_ID+16, PAL_ID+SPReD_ZUK_palette_slot0, 1); } **Edit yet again So since I can't get the incrementing to the next palette figured out; I decided to make a switch table to see if I could get the job done that way but there is still some trouble. //The Setup
//This function is intended to load an "entire palette set" or an "individual palette" into a specific slot
void LoadPal_Zuk(unsigned char SLOT_ID, unsigned char PAL_ID) { switch (PAL_ID) { case 0: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot0, 1); break;
case 1: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot1, 1); break;
case 2: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot2, 1); break;
case 3: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot3, 1); break;
case 4: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot4, 1); break;
case 5: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot5, 1); break;
case 6: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot6, 1); break;
case 7: load_palette( SLOT_ID+16, SPReD_ZUK_palette_slot7, 1); break;
case 8: load_palette( SLOT_ID+16, SPReD_ZUK_palette, SPRED_ZUK_PALETTE_SIZE); break; } }
//The Application
//This examples is attempt at: //Loading an individual palette from a set of 8. //Loading a palette into a unique palette slot.
load_palette( 16, SPReD_SFX_palette, SPRED_SFX_PALETTE_SIZE); //loads SFX palette into palette slot 0 //1 palette is loaded LoadPal_Zuk(1,0); //Load Palette Slot 1 with palette 0 of the Zuk Pal Set //Works Great! The palette can be referenced and is visible LoadPal_Zuk(2,1); //Load Palette Slot 2 with palette 1 of the Zuk Pal Set //Works Great! The palette can be referenced and is visible LoadPal_Zuk(3,2); //Load Palette Slot 3 with palette 2 of the Zuk Pal Set //!DOES NOT WORK! The palette that is referenced appears to be the previous "Palette Slot 2 with palette 1 of the Zuk Pal Set" //SPECIAL NOTE 1: In SPReD Gui this "palette 2" has the active red dot beside it.
//SPECIAL NOTE 2: If ignore the SFX Palette and load the palettes from Slot "0" there is no issue. //It appears that offsetting the PAL SLOT creates the issue. LoadPal_Zuk(0,0); //Load Palette Slot 0 with palette 0 of the Zuk Pal Set //Works Great! The palette can be referenced and is visible LoadPal_Zuk(1,1); //Load Palette Slot 1 with palette 1 of the Zuk Pal Set //Works Great! The palette can be referenced and is visible LoadPal_Zuk(2,2); //Load Palette Slot 2 with palette 2 of the Zuk Pal Set //Works Great! The palette can be referenced and is visible
I'm stuck at this point. I'm not quite sure how to correctly load individual palettes into unique slots.
|
|
|
Post by 0x8bitdev on Feb 26, 2023 14:04:24 GMT
hyperfighting - Glad you figured out how to access individual palettes. As for your last setup with the switch... It is a simple, but ugly way to solve your task. When I wrote the MPD library, the first things I implemented were extended versions of some HuC functions that work with data offsets. Because MAPeD exported data are arrays of similar data and I need to access them by offset. One of that functions is mpd_load_palette(_palette_slot, _palette_ptr, _offset_in_bytes, _num_palettes). So it's the same HuC's load_palette, but after the palette pointer you use the offset in bytes (one palette 16-colors, 2-bytes per color ->32 bytes per palette). In your case, you can try the following: void Load_One_Zuk_Pal(unsigned char SLOT_ID, unsigned short PAL_ID) { mpd_load_palette( SLOT_ID+16, SPReD_ZUK_palette, PAL_ID<<5, 1); }
|
|
|
Post by hyperfighting on Feb 26, 2023 16:50:53 GMT
0x8bitdev - Huge thanks for your help on this one! Regarding my ugly switch - Thank you for verifying that it was formatted correctly....I was having issues with it... I was passing two unsigned chars as parameters. As per our previous conversation I was trying to split a BYTE into the upper and lower nibble as I don't need values higher than 0...15 in either parameter. I also remember you telling me bit shifts are slow but since this is only done once to perform the loading of the palette I took this direction. Long story short there was a flaw in my BIT masking that led to the odd behavior I experienced. At this stage the switch works as intended! Regarding your custom MAPeD function...I am not using MAPeD exported data in this case I am using SPReD exported data with simple sprites. I am using simple sprites so my main loop has this standard HuC convention in it not the custom SPReD palette loading functions. spr_pal(SLOT_ID); Assuming your MAPeD function works with SPReD data I tried to use the function you provided but the BG colors get messed up when I call the function. I believe I am using the function you posted as intended. void LoadPal_Zuk(unsigned char SLOT_ID, unsigned char PAL_ID) //NIBBLES are passed in here... { unsigned short PAL_ID_NUM; PAL_ID_NUM=PAL_ID; //The PAL_ID is passed in by a NIBBLE and this is my way of converting it to an unsigned short //I realize there are more elegant ways to achieve this conversion
//Internal test to ensure the values being passed appear as intended. put_number(PAL_ID_NUM, 5, 1, 14); put_number(SLOT_ID, 5, 1, 15);
mpd_load_palette( SLOT_ID+16, SPReD_ZUK_palette, PAL_ID_NUM<<5, 1); }
|
|
|
Post by 0x8bitdev on Feb 27, 2023 10:57:05 GMT
Regarding my ugly switch - Thank you for verifying that it was formatted correctly....I was having issues with it... I was passing two unsigned chars as parameters. As per our previous conversation I was trying to split a BYTE into the upper and lower nibble as I don't need values higher than 0...15 in either parameter. I also remember you telling me bit shifts are slow but since this is only done once to perform the loading of the palette I took this direction. Long story short there was a flaw in my BIT masking that led to the odd behavior I experienced. At this stage the switch works as intended! Just a reminder, just in case. Data optimization makes sense when you free up significant memory: hundreds of bytes, kilobytes. It's a lot when you're dealing with limited hardware, because it frees up resources for other purposes. Or when you're optimizing procedures that are CPU-intensive and take a lot of frame time. If you're trying to optimize a few bytes of memory and procedures that are rarely called, you need very good reasons for that. Otherwise it's all tantamount to saving money on matches. A little about the switches that you like so much. Why the switch is ugly? Because there is a better alternative. It's faster and doesn't bind to unnecessary constants. Why a switch can be a great solution? Because it has no alternatives and is rarely called. But even if a function is rarely called, this is not a reason to write it inefficiently. Regarding your custom MAPeD function...I am not using MAPeD exported data in this case I am using SPReD exported data with simple sprites. As for palette data, both MAPeD/SPReD export raw uncompressed palette data. So, you can use the HuC or MPD functions to load palette. Assuming your MAPeD function works with SPReD data I tried to use the function you provided but the BG colors get messed up when I call the function. I believe I am using the function you posted as intended. You are right... I've fixed the function to work with all palette slots (background and sprites). It's never used outside the library, so its time has come. You can get the 'mpd.h' from the dev build again. Let me know how it works now. void LoadPal_Zuk(unsigned char SLOT_ID, unsigned char PAL_ID) //NIBBLES are passed in here... { unsigned short PAL_ID_NUM; PAL_ID_NUM=PAL_ID; //The PAL_ID is passed in by a NIBBLE and this is my way of converting it to an unsigned short //I realize there are more elegant ways to achieve this conversion
//Internal test to ensure the values being passed appear as intended. put_number(PAL_ID_NUM, 5, 1, 14); put_number(SLOT_ID, 5, 1, 15);
mpd_load_palette( SLOT_ID+16, SPReD_ZUK_palette, PAL_ID_NUM<<5, 1); } You don't need to make such conversion from char to int. HuC automatically converts 8-bit values to 16-bit arguments.
|
|
|
Post by 0x8bitdev on Feb 27, 2023 13:32:15 GMT
...I also remember you telling me bit shifts are slow... Let's clear the fog around the question that someone said something works faster or slower than something else. Here is a very simple relative performance tester. It doesn't show any absolute values. It just shows that one test function works faster/slower than another. And you can see that on the border color. main.c// Relative performance tester
#define FUNC_ALPHA_ENABLED 1 // 1 - func_alpha() call; 0 - func_beta() call #define NUM_ITERATIONS 200 // the number of iterations for both alfa an beta functions
#include <huc.h>
// func_alpha() and func_beta() are user defined functions that implement some test functionality you want to compare.
void func_alpha() { static unsigned short arr[5] = { 0, 32, 64, 96, 128 }; static unsigned short val;
val = arr[ 3 ]; }
void func_beta() { static unsigned short val;
val = 3 << 5; }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void border_color( unsigned short _clr ) { pokew( 0x0402, 0x0100 ); pokew( 0x0404, _clr ); }
main() { static int i;
disp_off(); cls();
load_default_font();
/* print an abstract scale of values */ for( i = 0; i < 26; i++ ) { put_number( i, 2, 0, i ); }
#if FUNC_ALPHA_ENABLED put_string( "ALPHA", 14, 0 ); #else put_string( "BETA", 14, 1 ); #endif
disp_on();
/* run performance test */ for( ;; ) { vsync();
border_color( 511 );
for( i = 0; i < NUM_ITERATIONS; i++ ) { #if FUNC_ALPHA_ENABLED func_alpha(); #else func_beta(); #endif }
border_color( 0 ); } }
How to use:1. Implement your func_alpha() and func_beta() with a functionality you want to compare. 2. Adjust the value of the NUM_ITERATIONS so that when the program runs the significant part of the border is colored white. If the border blinks, it means you are out of frame time and you need to decrease the NUM_ITERATIONS value. 3. Set the FUNC_ALPHA_ENABLED to 1, run the program, then set FUNC_ALPHA_ENABLED to 0 and run again. 4. Compare the results. The less white color on the border, the faster test function works. NOTE: Test the both func_alfa() and func_beta() with the same NUM_ITERATIONS value! Now you can check for yourself what works faster and what works slower, without looking at the HuC sources. Use Mednaffen PCE Dev, because it shows the border by default. p.s.: compile.bat @del *.pce
@echo Compiling... huc -fno-recursive -msmall main.c @if ERRORLEVEL 1 goto failure @echo Ok!
@del *.lst *.sym *.s
main.pce @goto exit
:failure @echo Build error! :exit
|
|
|
Post by hyperfighting on Feb 27, 2023 18:53:33 GMT
0x8bitdev - What can I say today has been an exciting day to say the least! As always THANK YOU! 1. Tested and verified! The function you hooked up for loading a single palette in a set works great! void Load_One_Pal(unsigned char SLOT_ID, unsigned short PAL_ID)
{ mpd_load_palette( SLOT_ID+16, "INSERT_SPRED_PALETTE_SET", PAL_ID<<5, 1); //Note: "INSERT_SPRED_PALETTE_SET" - SPReD.h file for your exported sprite resides in your root directory }
2. Tested and verified! The "simple relative performance tester" - I renamed it to "speedTest" in my project! This is extremely helpful! A. I used a make.bat to compile and run.bat to run.... your compile.bat let's me choose a file association for .pce files. Eliminating the need for run.bat step! B. I was vaguely aware of the Dev Mednafen build. Now I have it looped in and working. C. After running ALPHA and BETA functions. (BIT SHIFTING - LOST THAT RACE) D. I improvised with my own adjustments to see what is indeed faster. I had already bet on "ASM" based on elmer 's __fastcall in-depth and awesome explanation but now was my chance to do the "SpeedTest" Using elmer and turboxray example code! //The Setup -
//Using "simple relative performance tester" base code provided by 0x8bitdev //Replacing func_alpha and func_beta with ASM vs __fastcall
unsigned char vramSlot=0; unsigned char state[5]=0; unsigned char prevState[5]=0;
void func_alpha(unsigned char _STATE_CHANGE); #asm .proc _func_alpha txa ldx _vramSlot ldy _state, x sta _state, x tya sta _prevState, x rts .endp #endasm
extern unsigned int _ax, _bx; void __fastcall __nop getStateVars (unsigned char tmp1<__ax>, unsigned char tmp2<__bx>);
void func_beta( void ) { prevState[vramSlot] = _ax; state[vramSlot] = _bx; }
//The Application #if FUNC_ALPHA_ENABLED func_alpha(5); #else func_beta(getStateVars (state[vramSlot], 5)); #endif
Now it is clear to see ASM wins in this case
|
|
dogen
Deep Blooper
Posts: 31
|
Post by dogen on Mar 10, 2023 3:27:10 GMT
maybe i'm stupid, but where are the docs or examples for the assembly library
|
|
|
Post by 0x8bitdev on Mar 10, 2023 10:54:53 GMT
maybe i'm stupid, but where are the docs or examples for the assembly library I hope everything is okay with you. There is simply no MAPeD-PCE/SPReD-PCE library for use with pure assembly, and there were no plans for it. There are several examples in pure assembly for SPReD-PCE: showing static sprites, animated sprites, and simple character controller with a big meta-sprite character. This was done more for testing exported data and trying out the platform on a low level. In this regard, versions of the tools for other platforms are more fortunate. For the NES/SMS/ZX, there are many map scrollers and simple character controllers, written in assembly. And if desired, they can be adapted for your own purposes. The README.md says:
Warning: The sample codes coming with the tools were made just for testing of exported data. You can use/modify them for free at your own risk without any warranties. However, the PCE versions are luckier with high-level libraries for HuC that were optimized in assembly. The SPD library was completely written in assembly with HuC interface functions. The MPD library has mixed code: HuC+ASM optimizations. There is a lot of non-performance-critical code that can be used during the initialization stage. Therefore, I don't see the point in completely rewriting everything in assembly. However, performance-critical things like map scrolling, getting a tile property in a map and initial screen drawing have been optimized in assembly. To be honest, I don't want to box the user of the tools into any strict concepts or data formats and write rigid universal solutions based on them, which as you understand, will not always be effective. I would say that for now the PCE version is the exception. The MAPeD/SPReD default data export is just one of the possibilities for data export. Both MAPeD/SPReD have a built-in simple Python script editor and API, which can be used to write data exports in any "super-optimal" format that will fit for your project. There are a couple of scripts in the './scripts' directory that output all the data of a current project. Also MAPeD supports exports to JSON format. So, knowing assembly and having a specific goal, you can use these tools more effectively.
|
|
dogen
Deep Blooper
Posts: 31
|
Post by dogen on Mar 10, 2023 15:09:14 GMT
Oh ok. I was thinking of using it as a tilemap generating tool and then just porting my nes scrolling code. I just wasn't sure what was available.
|
|