Forums

Sega Master System / Mark III / Game Gear
SG-1000 / SC-3000 / SF-7000 / OMV
Home - Forums - Games - Scans - Maps - Cheats - Credits
Music - Videos - Development - Hacks - Translations - Homebrew

View topic - [WIP] GG : The Sword of Stone

Reply to topic Goto page Previous  1, 2, 3, 4  Next
Author Message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Apr 08, 2023 9:50 am
Yes, of course you need to make sure that the palettes get updated quickly, which means to switch to precalculated values instead of the on-the-fly calculations those devkitSMS functions are using.

So workflow could be:
- prepare the new palette(s) in some temporary RAM area (16 bytes for each palette you want to update)
- wait for vblank
- (do something else)
- wait for a specific scanline (screen rate dependent)
- write the palette(s) as quickly as possible

Anyway even official games weren't really worrying much about CRAM dots... it's up to you if you want to tackle that issue. It's not a big headache after all.
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 670
  • Location: London, UK
Reply with quote
Post Posted: Sat Apr 08, 2023 9:58 am
sverx wrote
edit: it's here. Scroll for the PAL values.

Okay so 216 vs. 219 - there might be enough margin here to just wait for 219...

Here's an updated version using vcounter I think works for both PAL and NTSC and should be relatively tolerant to CPU / optimisation variation then:

https://gist.github.com/willbritton/6f2218094561e758bc4a5870bd1661d5/2f1c2a39de5...

EDIT: cross-posted with you, I see great minds think alike :)

I did initially try precalculating everything, but that made the whole process take longer so although this way is kind of scrappy (and allocates more stack space than it generally needs) I think it gives the tightest timings and not too much CPU wasted just polling.

EDIT2: damn, I misread the timings - it's actually 240 for PAL, which doesn't give enough time in NTSC so it will need to be a bit more intelligent :/
  View user's profile Send private message Visit poster's website
  • Joined: 16 May 2002
  • Posts: 1356
  • Location: italy
Reply with quote
Post Posted: Sat Apr 08, 2023 11:56 am
sverx wrote
But this is easier said than done, as the retrace is pretty quick and to time to that even correctly you have to poll the vCount counter and act accordingly to the 50/60 Hz refresh rate of your TV/consolle.
He's developing a Game Gear game, though, wouldn't that help a lot since there are huge unseen borders around the visible area?
  View user's profile Send private message Visit poster's website
  • Joined: 06 Mar 2022
  • Posts: 670
  • Location: London, UK
Reply with quote
Post Posted: Sat Apr 08, 2023 12:59 pm
Tom wrote
He's developing a Game Gear game, though, wouldn't that help a lot since there are huge unseen borders around the visible area?

Very good point!!
I guess it's just a case of making sure that the palette changes don't get down to the 24th line of the active display. Could just be if op was attempting to fade both palettes in the same frame as I was then.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Sat Apr 08, 2023 2:21 pm
I am currently digesting all the information, thanks for the very technical and precise feedback.

My game is a Game Gear game indeed, and I never use any scrolling. So my screen is set at the top of the virtual area (not sure how you call it).

Game Gear also allows for much more steps in the effect, and I wanted it to be as nice as possible. I basically do 15 steps (which makes sense).

It might be possible to improve it if before doing anything, I wait for a vblank to be sure of the timing, then wait whatever time is necessary doing things, then update everything, then then repeat. I think I will do some trial and error to see if it improves.

I am indeed updating both Sprite and BG at once. I have been using loops and calculating/setting colors one by one. I also have an alternate version where I calculate everything and update the palette all at once (this is much faster by the way, but generates more code).

I never noticed it in retail games, I guess I will be check games some more.

Edit : I managed to get rid of the dots, here is my code in case you might be interested.


unsigned int bg_pal[16];
unsigned int sprite_pal[16];
unsigned int tmpColor1, tmpColor2, tmpColor3;

void updatePaletteBGSingleColor(unsigned char colorNb, unsigned char dec) {
   tmpColor1 = (current_palette_bg[colorNb] & 0x00F) - dec;
   tmpColor2 = (current_palette_bg[colorNb] & 0x0F0) - (dec << 4);
   tmpColor3 = (current_palette_bg[colorNb] & 0xF00) - (dec << 8);

   if(tmpColor1 & 0x8000) tmpColor1 = 0x000;
   if(tmpColor2 & 0x8000) tmpColor2 = 0x000;
   if(tmpColor3 & 0x8000) tmpColor3 = 0x000;

   bg_pal[colorNb] = tmpColor1 + tmpColor2 + tmpColor3;
}

void updatePaletteSpriteSingleColor(unsigned char colorNb, unsigned char dec) {
   tmpColor1 = (current_palette_sprite[colorNb] & 0x00F) - dec;
   tmpColor2 = (current_palette_sprite[colorNb] & 0x0F0) - (dec << 4);
   tmpColor3 = (current_palette_sprite[colorNb] & 0xF00) - (dec << 8);

   if(tmpColor1 & 0x8000) tmpColor1 = 0x000;
   if(tmpColor2 & 0x8000) tmpColor2 = 0x000;
   if(tmpColor3 & 0x8000) tmpColor3 = 0x000;

   sprite_pal[colorNb] = tmpColor1 + tmpColor2 + tmpColor3;
}

//generate less code
void updateBothPalettes() {
   wait_vblanks(1);
   while(SMS_getVCount() != 176); //wait
   GG_loadBGPalette(bg_pal);
   GG_loadSpritePalette(sprite_pal);
   wait_vblanks(1);
}

void paletteChangetoBlack(void)  {
   unsigned char dec, colorNb;

   for(dec = 2; dec <= 16; dec+=2) {
      for(colorNb = 0; colorNb < 16; colorNb++) {
         updatePaletteBGSingleColor(colorNb, dec);
         updatePaletteSpriteSingleColor(colorNb, dec);
      }
      updateBothPalettes();
   }
}


void paletteChangeFromBlack(void)  {
   unsigned char dec, colorNb;

   for(dec = 14; dec > 0; dec-=2) {
      for(colorNb = 0; colorNb < 16; colorNb++) {
         updatePaletteBGSingleColor(colorNb, dec);
         updatePaletteSpriteSingleColor(colorNb, dec);
      }
      updateBothPalettes();
   }
   wait_vblanks(1);
   while(SMS_getVCount() != 176); //wait
   GG_loadBGPalette(current_palette_bg);
   GG_loadSpritePalette(current_palette_sprite);
   wait_vblanks(1);
}
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Apr 08, 2023 4:23 pm
Tom wrote
He's developing a Game Gear game, though, wouldn't that help a lot since there are huge unseen borders around the visible area?


Ahah, I'm an idiot!

Since he's coding a GG game, he shouldn't worry about updating the palettes in any specific moment during vblank as any moment during vblank is not visible on screen anyway.
So @cireza: just make sure you update the palette(s) during vblank

Also I didn't (yet?) provide any SMS_load[BG|Sprite]PaletteafterColorSubtraction functions for the Game Gear - but I might do that if they're needed.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Sat Apr 08, 2023 8:07 pm
sverx wrote
Also I didn't (yet?) provide any SMS_load[BG|Sprite]PaletteafterColorSubtraction functions for the Game Gear - but I might do that if they're needed.

I don't have this function in the lib I use so I guess you added it some time after I started my dev. But overall, I don't use that many functions from your lib (the few I use are very useful, don't get me wrong :) )and I have been able to do what I wanted until now.

From its name, I guess this method is meant to set a whole palette with a decrement given in parameter ? It could probably be useful.

Do these functions you add to the library take space in the ROM, or only if I actually call them in my code ?
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 886
  • Location: Spain
Reply with quote
Post Posted: Sun Apr 09, 2023 8:49 am
cireza wrote


I never noticed it in retail games, I guess I will be check games some more.



I would say that 99% of Master System games show the dots. Even some of the Bios do. I suppose Game Gear games were not showing as much this problem due to the smaller active window.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sun Apr 09, 2023 9:01 am
cireza wrote
From its name, I guess this method is meant to set a whole palette with a decrement given in parameter ? It could probably be useful.


The decrement parameter is a color, so it's actually three decrement parameters (red, green, blue). You can read the details here. These functions are not yet available on Game Gear, but I can likely add them in the coming days.

cireza wrote
Do these functions you add to the library take space in the ROM, or only if I actually call them in my code ?


The library is a collection of (small) modules and each module gets linked to your code only if a function is used.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Sun Apr 09, 2023 9:58 am
sverx wrote
The decrement parameter is a color, so it's actually three decrement parameters (red, green, blue).

So for a fadeOut effect you would use RGB(1,1,1) then RGB(2,2,2) ... up to RGB(F,F,F) on Game Gear, if I understood correctly. This could be useful indeed.

sverx wrote
The library is a collection of (small) modules and each module gets linked to your code only if a function is used.

This is what I expected, thank you for confirming.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sun Apr 09, 2023 3:49 pm
cireza wrote
So for a fadeOut effect you would use RGB(1,1,1) then RGB(2,2,2) ... up to RGB(F,F,F) on Game Gear, if I understood correctly. This could be useful indeed.


Yes, if you want. Or you can even fade out reds/greens/blues separately - check the example in the linked post.
I posted an SMSlib update on GitHub a few minutes ago so now GG_loadBGPaletteafterColorSubtraction and GG_loadSpritePaletteafterColorSubtraction functions for the GameGear are also available. Enjoy! :)
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Sun Apr 09, 2023 7:25 pm
sverx wrote
Yes, if you want. Or you can even fade out reds/greens/blues separately - check the example in the linked post.
I posted an SMSlib update on GitHub a few minutes ago so now GG_loadBGPaletteafterColorSubtraction and GG_loadSpritePaletteafterColorSubtraction functions for the GameGear are also available. Enjoy! :)

Since you invested your time in this, I updated the lib and sdcc for my project to try it out and share some feedback.

I noted that I have much less code used in the 32 KB allowed, so that was a pleasant surprise, especially as I am getting near the end of the project and I was at around 85% used. Now I am at 77% which is a huge gain.

Otherwise I have used your new functions like this :

void paletteChangeBGtoBlack(void)  {
   unsigned char dec, colorNb;

   for(dec = 1; dec <= 15; dec+=2) {
      wait_vblanks(1);
      while(SMS_getVCount() != 176); //wait
      GG_loadBGPaletteafterColorSubtraction(current_palette_bg, RGB(dec,dec,dec));
   }
}

void paletteBGChangeFromBlack(void)  {
   unsigned char dec, colorNb;

   for(dec = 15; dec != 255; dec-=2) {
      wait_vblanks(1);
      while(SMS_getVCount() != 176); //wait
      GG_loadBGPaletteafterColorSubtraction(current_palette_bg, RGB(dec,dec,dec));
   }
   wait_vblanks(1);
   while(SMS_getVCount() != 176); //wait
   GG_loadBGPalette(current_palette_bg);
}

The effect is the one expected, however this is not fast enough for the music not to stutter. I reverted to my previous code for now (which is available in a previous post).

Maybe I did something wrong, otherwise it cannot be used with music playing in the background.
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 670
  • Location: London, UK
Reply with quote
Post Posted: Sun Apr 09, 2023 7:36 pm
What's inside your `wait_vblanks` function?
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Sun Apr 09, 2023 7:40 pm
willbritton wrote
What's inside your `wait_vblanks` function?

Good point indeed. Here is the content :


void wait_vblanks(unsigned char nb_vblanks) {
   for(int i=0; i<nb_vblanks; i++) {
      SMS_waitForVBlank();

      //continue playing music at each vblank
      SMS_mapROMBank(current_music_bank);
      PSGFrame();

      //animate flames, birds and water on map
      if(bg_anim_active == 1) {
         ...
      }
   }
}


Not much, but I can replace it with SMS_waitForVBlank and PSGFrame just in case.
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 670
  • Location: London, UK
Reply with quote
Post Posted: Sun Apr 09, 2023 8:15 pm
Vcounter will be at 193 following the call to SMS_waitForVBlank, then you play the PSG frame, do some stuff, and then you have a while loop that waits for vcounter to be 176 - which causes the CPU to spin for almost an entire frame, then your call to GG_loadBGPaletteafterColorSubtraction will take you past line 193 and you'll miss the next vblank, causing the audio to play at half speed.

I'm curious why you need the while loop at all - based on the previous discussion it feels like you should almost certainly be able to make a single call to GG_loadBGPaletteafterColorSubtraction immediately after waiting for vblank without getting the CRAM dots.
If you are seeing the CRAM dots without the wait, could it perhaps be that because you're doing some more inside wait_vblank that's pushing the timing of the palette shift too far? Do you need to do the animation stuff while you're fading the palette?
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Mon Apr 10, 2023 11:40 am
willbritton wrote
Vcounter will be at 193 following the call to SMS_waitForVBlank, then you play the PSG frame, do some stuff, and then you have a while loop that waits for vcounter to be 176 - which causes the CPU to spin for almost an entire frame, then your call to GG_loadBGPaletteafterColorSubtraction will take you past line 193 and you'll miss the next vblank, causing the audio to play at half speed.

I'm curious why you need the while loop at all - based on the previous discussion it feels like you should almost certainly be able to make a single call to GG_loadBGPaletteafterColorSubtraction immediately after waiting for vblank without getting the CRAM dots.
If you are seeing the CRAM dots without the wait, could it perhaps be that because you're doing some more inside wait_vblank that's pushing the timing of the palette shift too far? Do you need to do the animation stuff while you're fading the palette?

So I implemented what you suggested. It looks like this :


void paletteChangeBGtoBlack(void)  {
   unsigned char dec;

   SMS_mapROMBank(current_music_bank);

   for(dec = 1; dec <= 15; dec+=2) {
      //wait_vblanks(1);
      //while(SMS_getVCount() != 176); //wait
      SMS_waitForVBlank();
      GG_loadBGPaletteafterColorSubtraction(current_palette_bg, RGB(dec,dec,dec));
      PSGFrame();
   }
}

void paletteBGChangeFromBlack(void)  {
   unsigned char dec;

   SMS_mapROMBank(current_music_bank);

   for(dec = 15; dec != 255; dec-=2) {
      //wait_vblanks(1);
      //while(SMS_getVCount() != 176); //wait
      SMS_waitForVBlank();
      GG_loadBGPaletteafterColorSubtraction(current_palette_bg, RGB(dec,dec,dec));
      PSGFrame();
   }
   //wait_vblanks(1);
   //while(SMS_getVCount() != 176); //wait
   SMS_waitForVBlank();
   GG_loadBGPalette(current_palette_bg);
   PSGFrame();
}

I do not get the C-dots, which means that I have not fully understood what waitForVBlank does. I thought that vblank was the moment where the console was starting to draw a new picture, so I was sure to get C-dots.

I have also functions that deal with both palettes :

void paletteChangetoBlack(void)  {
   unsigned char dec;

   for(dec = 1; dec <= 15; dec+=2) {
      SMS_waitForVBlank();
      GG_loadBGPaletteafterColorSubtraction(current_palette_bg, RGB(dec,dec,dec));
      GG_loadSpritePaletteafterColorSubtraction(current_palette_sprite, RGB(dec,dec,dec));
      PSGFrame();
   }
}


void paletteChangeFromBlack(void)  {
   unsigned char dec;

   for(dec = 15; dec != 255; dec-=2) {
      SMS_waitForVBlank();
      GG_loadBGPaletteafterColorSubtraction(current_palette_bg, RGB(dec,dec,dec));
      GG_loadSpritePaletteafterColorSubtraction(current_palette_sprite, RGB(dec,dec,dec));
      PSGFrame();
   }
   SMS_waitForVBlank();
   GG_loadBGPalette(current_palette_bg);
   GG_loadSpritePalette(current_palette_sprite);
   PSGFrame();
}

This actually has the game crash sometimes. Either the music will get stuck or the game will completely crash.

Edit : I took some time to read the developer documentation a bit more and now understand that vblanks actually occurs after display, but there are still some lines available to process stuff.

With that in mind, I find that it makes for sense to actually count the VCounter until whatever limit I see fit (for me it is 171 in the end) rather than waiting for vblank, which happens a bit later. My screen is set at the top of the Virtual Area, so according to documentation, this 27 lines + 18*8, so 171. I should wait for line 171 to process music, palettes and any update to animated tiles.

This helps making things better, so thanks for the insight.
  View user's profile Send private message
  • Joined: 06 Mar 2022
  • Posts: 670
  • Location: London, UK
Reply with quote
Post Posted: Mon Apr 10, 2023 12:24 pm
Strange about the crashing - could it be because you were switching ROM bank before when you were calling wait_vblanks are not in your revised code? Trying to play a PSG frame with the wrong ROM bank selected I guess might lead to some strange stuff.

Yes, SMS_WaitForVblank will detect the frame interrupt from the VDP which is the line after the active display has finished. It's different depending on the exact screen height being used. It's not really in true vblank at all, as far as the screen is concerned, but the Sega docs call it vblank as soon as the active display has ended.

I don't see why you shouldn't wait for line 171 assuming you have enough time in your frame to stop doing CPU stuff that much earlier. That said there are probably some GG programmers here who can advise better whether that's a common trick. SMS_WaitForVblank just runs a tight loop anyway. Continuously polling got the vcounter will incur some extra overhead so possibly you'll need to play it safe and do >= 171 rather than strict equality - I guess it might be possible to miss the line sometimes?

Also I suppose given line 171 is still in the active display you won't be able to run any of the UNSAFE_* routines straight away - not until line 192/3.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Mon Apr 10, 2023 2:38 pm
There was probably an error in my code and I didn't set the bank.

Right now, I simply set the music bank before manipulating the palettes. The operations are based on values that I have set in RAM previously, so no need to switch banks.

About the UNSAFE functions, I don't use any of them. I only use few functions in game actually.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Apr 12, 2023 9:07 am
This got me curious and I went on and check how many cycles were required for a single GG_loadBGPaletteafterColorSubtraction call... turns out they're far more than what I thought it would require as, according to Emulicious' Profiler, a single call takes almost 11500 cycles.

But still means that if you do that call right when vblank start, you will make it on time before vblank ends, being the vblank phase longer than 15000 cycles on a Game Gear. Just make sure you're not doing anything else... which I suspect would be the case when fading out/in.
  View user's profile Send private message Visit poster's website
  • Joined: 01 Feb 2014
  • Posts: 877
Reply with quote
Post Posted: Wed Apr 12, 2023 12:48 pm
sverx wrote
This got me curious and I went on and check how many cycles were required for a single GG_loadBGPaletteafterColorSubtraction call... turns out they're far more than what I thought it would require as, according to Emulicious' Profiler, a single call takes almost 11500 cycles.

Lol, yes, Emulicious's Profiler has a tendency to rain on one's parade like that. The code in my head always performs much better than the one I actually write.
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Wed Apr 12, 2023 12:51 pm
sverx wrote
This got me curious and I went on and check how many cycles were required for a single GG_loadBGPaletteafterColorSubtraction call... turns out they're far more than what I thought it would require as, according to Emulicious' Profiler, a single call takes almost 11500 cycles.

So I wasn't crazy when I heard the music stuttering when doing both BG + Sprite at once :)

It is required to have a vblank call between each then.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Apr 12, 2023 2:12 pm
audio doesn't need to be played during vblank.
so you can actually update palettes and sprites in vblank and after that update audio and there won't be no issue if this ends up running outside vblank
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Wed Apr 12, 2023 2:36 pm
sverx wrote
audio doesn't need to be played during vblank.
so you can actually update palettes and sprites in vblank and after that update audio and there won't be no issue if this ends up running outside vblank

How do you guarantee that you have the perfect timing if you don't do it right after vblank though ?
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Apr 13, 2023 7:40 am
cireza wrote
How do you guarantee that you have the perfect timing if you don't do it right after vblank though ?


well, I'm not an expert on audio perception, but I believe that even a 70 scanlines (the entire vblank) jitter on a 60 Hz system won't be (much?) perceivable.

but if you aim for perfect timing, you should probably have your audio update routines tied to the line irq, and you can probably fire that on line 128 and have it done before next vblank starts

otherwise you can update audio after the game logic, with a check to ensure that you're at least say on line 150, and next thing is the wait for vblank... in this case there would be some (small) jitter anyway.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Thu Apr 13, 2023 12:31 pm
sverx wrote
well, I'm not an expert on audio perception, but I believe that even a 70 scanlines (the entire vblank) jitter on a 60 Hz system won't be (much?) perceivable.

but if you aim for perfect timing, you should probably have your audio update routines tied to the line irq, and you can probably fire that on line 128 and have it done before next vblank starts

otherwise you can update audio after the game logic, with a check to ensure that you're at least say on line 150, and next thing is the wait for vblank... in this case there would be some (small) jitter anyway.

From my own experience developing this game, I can say that having a perfect timing for the music is much more complicated than expected. You can very easily have too many instructions stacking that will lead to missing a vblank.

Also, trying to work with Vcounter can lead to stuttering for the exact same reason. It is a challenge about deciding where to put the cursor between having enough lines for your game logic, and still enough line after whenever you decide to process palette update etc...

In the end, to have perfect timing, the only solution that really works in my case is to always have these two instructions coming together :

   
SMS_waitForVBlank();
PSGFrame();


If you go with Vcounter, you will have to always use the exact same value as well if you do not want to have stuttering in your music.

I suppose it can be different depending on the game and the logic. For me it is very important to have impeccable fade-ins fade-outs, as there are a lot of them (which means that I do not want to see any color-dots), as well as having perfectly timed music as the music is pretty much always playing, even during transitions.

Overall this was a good exercise and helped understand the finer details of how the screen is displayed and when to do things.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Apr 13, 2023 1:03 pm
If you're aiming to the highest possible precision on audio timing, you should probably pick the line irq route.
I you use any value >96 for the line, you won't ever get more than one line IRQs in the same frame, so you don't need to disable and enable that again in your service routine.

Just make sure you save (and restore!) ROM map in your handler, as in:
SMS_saveROMBank();
SMS_mapROMBank(your_music_bank);
PSGFrame();
SMS_mapROMBank(current_SFX_bank);
PSGSFXFrame();
SMS_restoreROMBank();
so even if the game (or screen logic) ever 'skips', the music won't.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Thu Apr 13, 2023 4:59 pm
sverx wrote
If you're aiming to the highest possible precision on audio timing, you should probably pick the line irq route.
I you use any value >96 for the line, you won't ever get more than one line IRQs in the same frame, so you don't need to disable and enable that again in your service routine.

Just make sure you save (and restore!) ROM map in your handler, as in:
SMS_saveROMBank();
SMS_mapROMBank(your_music_bank);
PSGFrame();
SMS_mapROMBank(current_SFX_bank);
PSGSFXFrame();
SMS_restoreROMBank();
so even if the game (or screen logic) ever 'skips', the music won't.

So, my understanding of what you are saying :)

I am guessing that IRQ has something to do with interrupts. You are suggesting to have a specific function that is triggered when the chosen interrupt is set by the console, is this correct ?

I never did this yet, but it could be a good solution. Actually, I don't see why you would take the risk of doing it in any other way, as this pretty much guarantees that your music/sfx will always be played correctly and don't have to put every X instructions a wait_vblank + PSGFrame. I would suppose that most developers handled their music/sfx this way.

I will probably give it a go in the coming days, because right now my code is riddled with wait_vblank + PSGFrame to ensure music plays correctly.
  View user's profile Send private message
  • Joined: 16 May 2002
  • Posts: 1356
  • Location: italy
Reply with quote
Post Posted: Thu Apr 13, 2023 5:23 pm
cireza wrote
I am guessing that IRQ has something to do with interrupts.
Yes, that's literally what it means.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Thu Apr 13, 2023 7:06 pm
Tom wrote
cireza wrote
I am guessing that IRQ has something to do with interrupts.
Yes, that's literally what it means.

Got that.

So I checked the SMSLib.h functions and think I understood what I am supposed to do. Right now, I set up things like this :

In my main :

//play music as interrupt on line 171 of display (which is right after the visible screen)
SMS_setLineCounter(171);
SMS_setLineInterruptHandler(interrupt_music);
SMS_enableLineInterrupt();


And the corresponding function :

/**
 * Interrupt method to play music at regular pace
 */
void interrupt_music(void) {
   SMS_saveROMBank();
   SMS_mapROMBank(current_music_bank);
   PSGFrame();
   SMS_restoreROMBank();
}


Works like a charm. My music sounds much better than before now, so I know for sure that I was skipping vblanks.

The other positive side-effect is that I have been able to remove all my calls to wait_for_vblank+PSGFrame that I had put everywhere in my code to try to keep the music smooth. This is a huge gain in readability, it generates a bit less code, and it makes things faster.

This is the biggest performance boost I have got since I started, and it makes pretty much everything smoother.

One thing I noted though : SMS_saveROMBank() and SMS_restoreROMBank() do not seem to take into account the SRAM bank. It will crash if the interrupt function is called during the save process. Which means I had to disable then re-enable the interrupt in the saving process.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Fri Apr 14, 2023 7:37 am
Glad you liked this solution!

And, yeah, when the SRAM is enabled, it gets mapped to the same address as the data ROM banks, so no read operation on banked ROM data should happen until SRAM banking is deactivated again.

But if you prepare your savegame in a buffer in RAM you can basically:
- disable the line IRQ
- enable SRAM
- copy the savegame from RAM to SRAM
- disable SRAM
- re-enable line IRQ
and you will just skip one audio frame in the worst case scenario, not even that in most cases.

Instead, if you consistently get the audio frame skip you could put a wait for some specific line that is past your line IRQ trigger (say your trigger is on line 170, you could wait line 175...) and then perform the above operations avoiding skips.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Fri Apr 14, 2023 9:04 am
sverx wrote
But if you prepare your savegame in a buffer in RAM you can basically:
- disable the line IRQ
- enable SRAM
- copy the savegame from RAM to SRAM
- disable SRAM
- re-enable line IRQ
and you will just skip one audio frame in the worst case scenario, not even that in most cases.

This is what I did. My function to save will disable the IRQ then re-enable it. Writing is very fast so if there is a skip it is unnoticeable, so I think this is fine. There probably is one skip though, as otherwise it would not have crashed before.

If I find that for some reason it gets noticeable, I will definitely see to prepare in RAM the SRAM content beforehand, then push it all at once.

Thanks for the advice :)
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Sun May 07, 2023 3:09 pm
Quick update. I don't want to flood the forum, but I work on the game every week. I made some good progress recently.

I implemented the sixth chapter, which means only the final one remains. Also implement the Option screen, as well as the Introduction for the game.

Currently sitting at 92% of code used, I should be okay to complete everything within the 32 KB limit. Only two banks left as well (512 KB), but I have quite a bit of room in some of them. All graphical assets are done, I will use the remaining space to add a few touches here and there, with optional things. Not trying to make an incredibly optimized game in terms of storage, anyway.

See some pictures for the progress...

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon May 08, 2023 8:33 am
you can post an update whenever you feel like, don't worry :)

if I may ask, are you storing uncompressed tilesets and tilemaps in ROM?

not that it really matters much nowadays, and even less so if you're not planning for a physical release, but you might consider some compression - and we can help you pick one compression scheme or another depending on your main goals (save as much ROM as possible or being quick to decompress for instance)

Maxim created a very nice benchmark of many tilesets compression schemes available, check it here (note that only some of them are supported by devkitSMS/SMSlib as of today...)
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Mon May 08, 2023 2:43 pm
sverx wrote
you can post an update whenever you feel like, don't worry :)

if I may ask, are you storing uncompressed tilesets and tilemaps in ROM?

not that it really matters much nowadays, and even less so if you're not planning for a physical release, but you might consider some compression - and we can help you pick one compression scheme or another depending on your main goals (save as much ROM as possible or being quick to decompress for instance)

Maxim created a very nice benchmark of many tilesets compression schemes available, check it here (note that only some of them are supported by devkitSMS/SMSlib as of today...)

Only form of compression I have is using a dictionary of meta-tiles for my huge overworld.

Otherwise, I don't use compression. I don't use tilemaps either. Backgrounds often have only a handful of repeated tiles, so I decided to have a set tilemap and not use specific ones. I also have a lot of text (around 100k letters). However, any compression algorithm might take me above the 32KB space allocated for the program, and I am trying to keep things simple here. My goal is first and foremost to make a good game, not a technical gem.

I don't know if there will be a cartridge release, I suppose someone would have to be interested in doing this first, as I don't have any knowledge about this. I don't even know if I can sell it "digitally", and how... Anyway, I would probably first have to demo it, show a video at least because people probably don't really get the idea of what this is all about.

Is a 512KB rom that expensive ? Now that data has been organized, I am not really looking forward into a mass reorganization of the banks. There is also a backup save feature.
  View user's profile Send private message
  • Joined: 16 May 2002
  • Posts: 1356
  • Location: italy
Reply with quote
Post Posted: Mon May 08, 2023 5:16 pm
When the time comes, feel free to contact me if you want me to record a video for you.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue May 09, 2023 10:35 am
cireza wrote
My goal is first and foremost to make a good game, not a technical gem.


So I wouldn't worry about the ROM at all in this case. If you later *need* compression, it should not be that terrible to add it.
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Tue May 09, 2023 4:54 pm
sverx wrote
So I wouldn't worry about the ROM at all in this case. If you later *need* compression, it should not be that terrible to add it.

I still wanted for everything to fit in 512, so I am glad it does fit. If I ever need help about compression, I will tell you, thanks ;)

And I also accepted Tom's proposal, so he now has a demo the game. Curious to see how someone else will play and discover the game :)
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3827
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue May 09, 2023 6:12 pm
Looking forward to see the video and try the game!
  View user's profile Send private message Visit poster's website
  • Joined: 16 May 2002
  • Posts: 1356
  • Location: italy
Reply with quote
Post Posted: Wed May 10, 2023 2:51 am
It's been an honour for me to record the first video of this very promising game!

https://youtube.com/watch?v=kO0IDCdW5Kk

I didn't edit the footage, look at me taking all the wrong paths at the wrong time, I'm not good at this kind of game 😁
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Wed May 10, 2023 8:04 am
Last edited by cireza on Wed May 10, 2023 8:31 am; edited 1 time in total
Tom wrote
It's been an honour for me to record the first video of this very promising game!

Thanks a lot for doing this :)

The intro explains that the player is walking on the beach and finds a book, then starts reading the book.

The first chapter is an introduction to the world, the story gets more elaborated with the following ones.

I am also planing on adding road-signs at various places to help navigating the world.
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 886
  • Location: Spain
Reply with quote
Post Posted: Wed May 10, 2023 8:12 am
Looks exciting!! Willing to see more!

PD: It's still a pity it's not for SMS.
  View user's profile Send private message
  • Joined: 15 Dec 2015
  • Posts: 15
Reply with quote
Post Posted: Wed May 10, 2023 9:30 am
Looks great, congratulations! It should be on the Master System, but anyway!
  View user's profile Send private message
  • Joined: 16 May 2002
  • Posts: 1356
  • Location: italy
Reply with quote
Post Posted: Wed May 10, 2023 10:06 am
cireza wrote
The intro explains that the player is walking on the beach and finds a book, then starts reading the book.
Yeah, about that, I'm sorry if I skipped it, I didn't do it on purpose, I pressed 1 since I saw "..." in the text, and I assumed I had to make it continue. I was already processing the video when I realised there were more scenes :(

cireza wrote
I am also planing on adding road-signs at various places to help navigating the world.
The one thing that confused me the most, right at the start, were the stoney tiles near the house of the old lady, I thought that they were unpassable obstacles, which is why I initially went all the way back to the top, before I realised I could walk on those tiles (and, in fact, that those stoney tiles actually are indications of a walkable path). Oh well, at least I could show some creatures.
  View user's profile Send private message Visit poster's website
  • Joined: 23 Jan 2010
  • Posts: 436
Reply with quote
Post Posted: Wed May 10, 2023 10:12 am
The music is lovely! Congrats. It would be a marvelous to SMS.
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Wed May 10, 2023 12:50 pm
Tom wrote
The one thing that confused me the most, right at the start, were the stoney tiles near the house of the old lady, I thought that they were unpassable obstacles

I see, thank you for the feedback. Maybe I will change the design a bit.

segarule wrote
The music is lovely! Congrats. It would be a marvelous to SMS.

Thanks ! First musics I have ever composed.
  View user's profile Send private message
  • Joined: 04 Jul 2010
  • Posts: 540
  • Location: Angers, France
Reply with quote
Post Posted: Thu May 11, 2023 11:28 am
Hi French comrade ^^
Congratulations for your game which seems to be pretty complex with a huge story!

Hope you'll consider doing a translation of the game
(French or any other)

For a future physical release/question about it, i'm here ;)
  View user's profile Send private message
  • Joined: 02 Mar 2011
  • Posts: 165
  • Location: Valencia,Spain.
Reply with quote
Post Posted: Thu May 11, 2023 4:37 pm
It would be fantastic to have a physical Master System conversion in other languages in the future.

Very good work, I am very interested.
  View user's profile Send private message
  • Joined: 27 Feb 2023
  • Posts: 134
  • Location: France
Reply with quote
Post Posted: Thu May 11, 2023 5:03 pm
Thank you very much to all for the support. Honestly, you are a great community!

I understand that there is a lot of interest for a MS version, and also multi-lingual. I know French, obviously, but that's it.

I need to complete things properly to have a quality GG game. GG was an entry point, it is a bit easier than MS for various reasons. If the GG game has a little bit of success (not expecting incredible things), then I can consider a MS version. This is the best answer I can provide for now!
  View user's profile Send private message
  • Joined: 16 May 2002
  • Posts: 1356
  • Location: italy
Reply with quote
Post Posted: Thu May 11, 2023 7:09 pm
To be honest, I don't get all this hate for the Game Gear, what's wrong with it? I do apologise in advance for what I'm about to say, but, seriously, instead of being happy that someone is working on a new amazing game, every other post in here is "baw, why isn't it Master System". Like, don't do that, please? It's like you win a car at a lottery, and you say "sure it's a nice car, but I wanted it in a different color, so I'm not going to drive it". You're lucky I'm not the programmer here, because this attitude would lead me to drop the project on the spot, cireza is being WAY too kind to acknowledge all these unwarranted and undeserved complaints.

Again, I'm sorry if this is harsh, but it had to be said.
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 886
  • Location: Spain
Reply with quote
Post Posted: Thu May 11, 2023 8:15 pm
I don't think anyone here has been harsh regarding choosing the GG as the platform. Everyone has been very respectful. If that should be a reason for abandoning a project, then with all the hating trolls out of smspower no project will ever be finished.

That being said, I was mentioning it's a pity as the Hand Helds were really poor choices for RPGs. The small screen makes it difficult to play it correctly, and also very few Game Gears are available compared with Master Systems and Megadrives. But that it's only my opinion, of course.
  View user's profile Send private message
Reply to topic Goto page Previous  1, 2, 3, 4  Next



Back to the top of this page

Back to SMS Power!