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 - devkitSMS - develop your homebrew in C

Reply to topic Goto page Previous  1, 2, 3 ... 12, 13, 14, 15, 16, 17  Next
Author Message
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Tue Jan 02, 2024 10:58 am
Cool, a big thank you, it's successful
  View user's profile Send private message
  • Joined: 12 Dec 2021
  • Posts: 43
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Wed Jan 03, 2024 2:01 am
sverx wrote
darkowl wrote
I made a reverse of devkit's subtractive fade that uses additive for fading to/from white which was fun to figure out.


this is interesting - can you provide a PR to the repository? :)


Sure, happy to do so. Although I might need a bit of help with the Game Gear version, as I'm less familiar with its expanded palette options (such a shame, I wish we had these colours in the base Master System!).

At the moment the code is in a file with the suffix of Sub -- would you prefer to have a new file with Add , or to change it to be more generalised and have both in the one file as they're kinda similar?
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Jan 03, 2024 9:41 am
an SMSlib_paletteAdd.c would be perfect.

As for the Game Gear, it's simply 4 bits per channel (R,G,B) instead of two, so the result fits 12 bits and requires an (unsigned) int instead of being 6 bits and fitting into a char.

No rush :)
  View user's profile Send private message Visit poster's website
  • Joined: 12 Dec 2021
  • Posts: 43
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Thu Jan 04, 2024 11:22 am
I've got the rough logic for the palette addition in. The SMS code should work, and I've just hacked the GG based on the differences between the subtractive version. Initial commit is here:
https://github.com/mikehdt/devkitSMS/commit/336ce7ecf864f4f5037169574499bdaa6740...

I just need to figure out the build stuff around it, test the GG logic.

When working in any codebase I always try to follow the style thereof, eg. 2 vs 4 spaces or tabs or whatnot, naming conventions and so-forth.

Intellisense (actually it's probably clang?) is very insistent on styling certain things though, which normally I don't mind, but I thought I'd note it just as a thing it wants to do.

I also did use a lot less brackets, as my brain found it easier to parse.

Once I figure out the build stuff - which I'm guessing is just adding the appropriate .rel file etc., and it looks good, then I'll raise a PR for you :) Happy to make any changes as I'm able to suit your sensibilities.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Jan 04, 2024 1:57 pm
Looks good so far!
Don't worry too much about the style or naming conventions, if something's really off (I doubt that) then I'll just fix it later.
  View user's profile Send private message Visit poster's website
  • Joined: 07 Jan 2024
  • Posts: 3
Reply with quote
Horizontal scrolling
Post Posted: Sun Jan 07, 2024 10:40 pm
Hey guys, this is my first of hopefully many posts. I grew up with Sega and the Master System and always wanted to write games for it. I recently discovered devkitSMS and jumped straight in to see what it can do. The thing I have been struggling with is scrolling big backgrounds. I tried GSLib but could not get it to work. I tried compiling the example that came with it but I only got a glitched display. I did come right with the devkitSMScode example, but the issue I am having there is my image is 1024 x 192 after it scrolls past 512px the background starts to shift down by one line after every 256px it scrolls.

My code and image is attached.


#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "libs\SMSlib.h"
#include "bank1.h"


// 1024px wide / 8px tiles
unsigned int BG_TILE_WIDTH = 128;      // FinalFight = 1024 x 192   i.e. 128 x 8 tiles wide
unsigned int X_TILE_MAX = 32;
unsigned int Y_TILE_MAX = 24;

//static unsigned char delta = 1;
static unsigned int scroll = 0;
static unsigned int scrollDivided8 = 0;
static unsigned int scrollRight = 0;
static unsigned int scrollRightDivided8 = 0;
static unsigned int scrollWidth = 0;

void engine_scroll_manager_load()
{
   unsigned char *src = NULL;
   unsigned char ytile = 0;
   unsigned int index = 0;
   unsigned int size = 0;

   SMS_loadPSGaidencompressedTiles(test_tiles_psgcompr, 0);
   SMS_loadBGPalette(test_palette_bin);

   for( ytile = 0; ytile < Y_TILE_MAX; ytile++ )
   {
      // 32 tiles * 2 bytes each.
      index = BG_TILE_WIDTH * ytile * 2;
      src = ( void * ) &test_tilemap_bin[ index ];
      size = X_TILE_MAX * 2;

      SMS_loadTileMap( 0, ytile, src, size );
   }

   scrollWidth = BG_TILE_WIDTH - X_TILE_MAX;
}

void engine_scroll_manager_update_left( unsigned char delta )
{
   unsigned char *src = NULL;
   unsigned char ytile = 0;
   unsigned int index = 0;
   const unsigned int size = 2;

   unsigned int x = 0;
   unsigned char y = 0;

   if( scrollRight > 0 )
   {
      scroll += delta;
      scrollRight -= delta;
      scrollRightDivided8 = scrollRight / 8;
      SMS_setBGScrollX( scroll );

      if( ( scrollRight % 8 ) == 0 )
      {
         for( ytile = 1; ytile < Y_TILE_MAX; ytile++ )
         {
            // 1 tile * 2 bytes.
            x = X_TILE_MAX + scrollRightDivided8;
            y = ytile - 1;
            index = ( ( BG_TILE_WIDTH*ytile ) + scrollRightDivided8 ) * 2;
            src = ( void * ) &test_tilemap_bin[ index ];

            SMS_loadTileMap( x, y, src, size );
         }
      }
   }
}

void engine_scroll_manager_update_right( unsigned char delta )
{
   unsigned char *src = NULL;
   unsigned char ytile = 0;
   unsigned int index = 0;
   const unsigned int size = 2;

   unsigned int x = 0;
   unsigned char y = 0;

   if( scrollRightDivided8 < scrollWidth )
   {
      scroll -= delta;
      scrollRight += delta;
      scrollRightDivided8 = scrollRight / 8;
      SMS_setBGScrollX( scroll );

      if( ( scrollRight % 8 ) == delta )
      {
         for( ytile = 0; ytile < Y_TILE_MAX; ytile++ )
         {
           
            x = X_TILE_MAX + scrollRightDivided8;

            y = ytile - 1;
            index = ( ( BG_TILE_WIDTH*ytile ) + ( X_TILE_MAX + scrollRightDivided8 ) ) * 2;
            src = ( void * ) &test_tilemap_bin[ index ];

            SMS_loadTileMap( x, y, src, size );
         }
      }
   }
}

void main() {

   engine_scroll_manager_load();
   SMS_displayOn();

   for (;;) {

        SMS_waitForVBlank();
       
        engine_scroll_manager_update_right(2);

    }

}

level_test.png (7.42 KB)
level_test.png

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon Jan 08, 2024 8:36 am
dedPixel wrote
I did come right with the devkitSMScode example, but the issue I am having there is my image is 1024 x 192 after it scrolls past 512px the background starts to shift down by one line after every 256px it scrolls.


I suspect the issue could be that you should use only values 0-31 as x coordinate for SMS_loadTileMap(). You could quickly try with
x%=32;


Anyway instead of having a loop to update a single tile in the column, you could update a whole column using SMS_loadTileMapColumn() provided your map is stored in a column-major order instead of the common row-major order.

For instance you could use the BMP2Tile plugin I posted here.

Let me know :)
  View user's profile Send private message Visit poster's website
  • Joined: 07 Jan 2024
  • Posts: 3
Reply with quote
Post Posted: Mon Jan 08, 2024 5:36 pm
Thanks @sverx, I tried changing x to 31 but that did not work. I updated the tile map loading to column loading, it simplified the math needed, but still gave me the effect of the map being draw 1 row lower after the first 512 pixels. I added 2 if statements to reset the y position, this seems to work, but seems a bit hacky.

Updated Code:


#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "libs\SMSlib.h"
#include "bank1.h"


// 1024px wide / 8px tiles
unsigned int BG_TILE_WIDTH = 128;      // FinalFight = 1024 x 192   i.e. 128 x 8 tiles wide
unsigned int X_TILE_MAX = 32;
unsigned int Y_TILE_MAX = 23;

//static unsigned char delta = 1;
static unsigned int scroll = 0;
static unsigned int scrollDivided8 = 0;
static unsigned int scrollRight = 0;
static unsigned int scrollRightDivided8 = 0;
static unsigned int scrollWidth = 0;

void engine_scroll_manager_load()
{
   unsigned int column;

   SMS_VRAMmemsetW(0, 0x0000, 16384);
   SMS_VDPturnOnFeature(VDPFEATURE_LEFTCOLBLANK);
      
   SMS_loadPSGaidencompressedTiles(test_tiles_psgcompr, 0);
      SMS_loadBGPalette(test_palette_bin);


   for (column=0; column < X_TILE_MAX; column++) {
      SMS_loadTileMapColumn(column, 0, &test_tilemap_cmraw[column * 48], 24);
   }

   scrollWidth = BG_TILE_WIDTH - X_TILE_MAX;
}

void engine_scroll_manager_update_left( unsigned char delta )
{
   unsigned char ytile = 0;
   unsigned int y_offset = -1;
   unsigned int x = 0;
   unsigned char y = 0;

   if( scrollRight > 0 )
   {
      scroll += delta;
      scrollRight -= delta;
      scrollRightDivided8 = scrollRight / 8;
      SMS_setBGScrollX( scroll );

      if( ( scrollRight % 8 ) == delta)
      {
         x = X_TILE_MAX + scrollRightDivided8;
         if (x > 63) { y_offset = ytile-2; }
         if (x > 95) { y_offset = ytile-3; }

         SMS_loadTileMapColumn(x,y_offset, &test_tilemap_cmraw[scrollRightDivided8 * 48], 24);
      }

   }
}

void engine_scroll_manager_update_right( unsigned char delta )
{
   unsigned int ytile = 0;
   unsigned int y_offset = -1;
   unsigned int x = 0;
   unsigned char y = 0;

   if( scrollRightDivided8 < scrollWidth )
   {
      scroll -= delta;
      scrollRight += delta;
      scrollRightDivided8 = scrollRight / 8;
      SMS_setBGScrollX( scroll );

      if( ( scrollRight % 8 ) == delta)
      {
         x = X_TILE_MAX + scrollRightDivided8;
         if (x > 63) { y_offset = ytile-2; }
         if (x > 95) { y_offset = ytile-3; }

         SMS_loadTileMapColumn(x,y_offset, &test_tilemap_cmraw[x * 48], 24);
      }
   }
}

void main() {

   engine_scroll_manager_load();
   SMS_displayOn();
   unsigned int ks;
 
   for (;;) {

        SMS_waitForVBlank();

      ks=SMS_getKeysStatus();

      if (ks & PORT_A_KEY_RIGHT) {
         engine_scroll_manager_update_right(2);
      }else if (ks & PORT_A_KEY_LEFT) {
         engine_scroll_manager_update_left(2);
      }

    }
}

output.png (3.35 KB)
Without If statements
output.png
output-1.png (3.33 KB)
With If statements
output-1.png

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon Jan 08, 2024 6:43 pm
you probably want to replace this

         x = X_TILE_MAX + scrollRightDivided8;
         if (x > 63) { y_offset = ytile-2; }
         if (x > 95) { y_offset = ytile-3; }


with
         x = scrollRightDivided8 % 32;


because x needs to be 0 to 31 in

SMS_loadTileMapColumn(x,y_offset, &test_tilemap_cmraw[scrollRightDivided8 * 48], 24);


also y_offset is actually just 0 so you could just do

SMS_loadTileMapColumn(x, 0, &test_tilemap_cmraw[scrollRightDivided8 * 48], 24);
  View user's profile Send private message Visit poster's website
  • Joined: 07 Jan 2024
  • Posts: 3
Reply with quote
Post Posted: Mon Jan 08, 2024 8:20 pm
Thanks sverx that fixed the issue.
  View user's profile Send private message
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Wed Jan 10, 2024 11:55 am
Hello Svrex, since the scrolling worked well but I want to trigger an animation of my ship (sprite) 1 frame out of 2, it makes me glitches: sprites appear on the tile decor, if I delete the animation of my sprite everything works correctly. I just have a variable to make a counter if I'm at 20 I load image 1 of my sprite if I'm at 40 I load image 2 and I reset the counter to zero,
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Jan 10, 2024 2:40 pm
I suppose you are loading the two images into VRAM beforehand.

so your code would be something like:
if (++counter<20) {
  SMS_addSprite (ship_x, ship_y, SHIP_IMAGE_1);
} else {
  SMS_addSprite (ship_x, ship_y, SHIP_IMAGE_2);
  if (counter==40)
    counter=0;
}
  View user's profile Send private message Visit poster's website
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Wed Jan 10, 2024 6:30 pm
Ah, but when I put Add sprite my sprite no longer appears on the screen, I send you a screenshot of my error...
IMG_7605.jpeg (1.42 MB)
IMG_7605.jpeg

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Jan 10, 2024 7:39 pm
oh so you're loading PSGaiden compressed tiles - you probably want to load them in place of the previous ones, so the second parameter should be the same in the two calls
  View user's profile Send private message Visit poster's website
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Wed Jan 10, 2024 8:46 pm
I do have the animation of the ship but as soon as I trigger sms_enableLineInterrupt() I have glitches on the screen of the sprites this glue on the tiles would you have any idea where it can come from? As soon as I remove my animation from the ship with the counter the scrolling does the parallax to the line 128 sms_setLineCounter(128)
But I no longer have an animation of the ship, here is the photo of the glitch...in the emulator I see that sprites are inserted into the tile party, from 0 to 256
IMG_7606.jpeg (1.83 MB)
IMG_7606.jpeg

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Jan 11, 2024 7:57 am
I see - decompressing the tiles probably takes too much.

So I can see two options: first is to store all the spaceship tiles in VRAM beforehand, and use either alternatively.

Second option is to use uncompressed tiles, and load them using
UNSAFE_SMS_load4Tiles(src,tilefrom)


of course I don't know how many tiles your spaceship is, let's pretend is 12 tiles, so you need to call that transfer 3 times. This would be fast enough to be completed before the screen starts drawing again.

If your spaceship is bigger I would suspect there's no way to transfer its tiles during vblank.
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
Post Posted: Sat Jan 13, 2024 10:15 am
If you are going to load tiles each frame (offscreen time) do not use compressed tiles. It's the deepest possible, headached, experience who is talking you :D

For an shmup (you are not going to have many different frames for the player....) i would not load the animation tiles at runtime. I would load all them at the beggining, i found difficult you are going to have to use all the 256 tiles for sprites at once. Always you can load enemy tilesets when you need it along a stage.

If you were doing a platformer wich 150 sprites for all the player animations I would load the tiles at runtime, yes, but this is not the case.

... also, do not discard the safe functions by default. A more or less elaborated shmup (with player, enemies, scripting, bullets, player shoots, bonus elements, scrolling, effects, music, collisions between al l elements, collisions with background, and everything at once) in "C" will run at 30 fps, you can be sure of that, and you will have enough time to use safe functions to load tiles each frame without risk of slowing down the things.
  View user's profile Send private message
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Sat Jan 13, 2024 6:02 pm
Hello and thank you for your help, I tried to use

UNSAFE_SMS_load4Tiles(src,tilefrom) but the image is broken down, I don't understand, I use bmp2tiles then I save 2 files in a 3bpp format and the palette, so when I use my sprite I have a mixture of colored pixels... I have questions about formats with Bmp2tiles, what's the difference with the Gaiden compressed format? And another question what is the limit to display an image on master system, if I understood correctly I can't perform my animation of the ship because I send too much information during the scan?

Is it better to make a sprite board with the animation of the vessel and bullets ? Or to make several images for each animation and bullets sprite ? Thank you 🙏🏽
  View user's profile Send private message
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
Post Posted: Sat Jan 13, 2024 6:19 pm
Let's see, I only talk about my own way to do the things.

If you want to update tiles on off screen time area (right after the waitvblank) and you need to do scrolling, also (updating row/col of tiles) I can assure (someone else can give you the exact number, which should be around the double) you are safe with about 8-10 tiles data each frame, plus the scrolling function (if it is something somewhat optimized).

But an shmup will need as much time to compute things (collisions, enemy logic, etc.)as you can find, and I would not use time to update tiles data if I can avoid that waste of time. (Are you sure you are going to need the 448 tiles at once?) (cannot optimize the background to count down the total of tiles used?)

Astroforce (hey, one of my first games, one shmup, like yours) is full of background effects, parallaxes and palette changes, and I was updating background tiles almost every frame of the game, but I did only updates for 4 or 8 tiles each frame. It's code is included in z88dk distribution, If you are curious.

In astroforce I loaded all the needed sprites&background tiles at the beggining of each stage, rewriting only the tiles to do such effects. You can debug the vram under emulicious to check it.

Regards
  View user's profile Send private message
  • Joined: 01 Feb 2014
  • Posts: 878
Reply with quote
Post Posted: Sun Jan 14, 2024 8:01 am
Leopardcookies wrote
I use bmp2tiles then I save 2 files in a 3bpp format and the palette, so when I use my sprite I have a mixture of colored pixels... I have questions about formats with Bmp2tiles, what's the difference with the Gaiden compressed format?

I can’t comment on the C-specific questions as I only have experience coding in assembly.

If your player ship doesn’t use more than 7 colors, the 3bpp format is actually a good format for loading tiles on the fly. It’s not compressed, so you can transfer them to the VDP at the quickest pace possible, but it’s still just 75% the size of a regular tile. Just don’t forget to skip writing the empty bitplane when transferring to VDP and make sure all the colors used (including the transparent one) are within the first 8 palette entries.

The Gaiden format is one of the many compressed ones BMP2Tile offers. All of those are great for saving ROM space, but even the fastest ones are quite slow, so I wouldn't use any of them to load tiles in the middle of a level. Use them to pre-load background and sprite graphics between levels instead.

Leopardcookies wrote
Is it better to make a sprite board with the animation of the vessel and bullets ? Or to make several images for each animation and bullets sprite ? Thank you 🙏🏽

Depending on the compression used, this can make a difference and it is a good idea to put all of the tiles you want to load in one chunk into the same image.

If you’re using uncompressed tiles, that doesn't make any difference. A sprite sheet is probably still more convenient than separate images, though.
  View user's profile Send private message
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Sun Jan 14, 2024 7:58 pm
thank you for your answer, I have just understood one error among many others: you tell me a sprite must have 8 colors maximum, I have my spaceship sprite which has 16 colors, so that must be my error for the pixel mush , my decor also has 16 colors, so if I understood correctly, do you advise me to use the tile plan to make my sprite? but when I load my background image which takes 248 tiles, how to include the sprites without displaying them with the decorations (how to separate the sprites from the background image) and used them to make my animation? I thought of the SMS_setTileatXY();
Can C users confirm that we can manage tiles in sprite?Gaiden compression I don't know if that's really the problem?
IMG_7658.jpg (2.54 MB)
IMG_7658.jpg

  View user's profile Send private message
  • Joined: 01 Feb 2014
  • Posts: 878
Reply with quote
Post Posted: Sun Jan 14, 2024 8:53 pm
All graphics displayed by the VDP consists of 8x8 pixels big tiles. Background tiles can be placed by entering their numbers in the name table, sprites are tiles that can be placed anywhere, not adhering to the name table grid.

The video RAM in the VDP is divided into two parts. One holds up to 256 tiles, the other one holds just 192 of them, because the name table and the sprite table are also located within, and they eat away some of the memory. You can choose, depending on the specifics of your game, which of the two parts you want to use for sprite tiles and which one for background tiles. You usually don’t mix them, even though it’s possible to display tiles assigned to the sprite part as part of the background (but not the other way around). Also, each part has its own palette of 16 colors.

My rental about only using the first 8 colors in the palette only applies to the special case of using 3bpp tiles. Note that these still have 4 bitplanes in the VRAM, so you need to transfer them accordingly from ROM.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon Jan 15, 2024 8:25 am
Leopardcookies wrote
I have just understood one error among many others: you tell me a sprite must have 8 colors maximum


no, wait - both the background and the sprites are made of 8×8 pixels 16 colors tiles, and you have two separate palettes: one is for the tiles you'll use in the background and one is for the tiles you use for the sprites

anyway, from the image you posted it looks like you're using all the available tiles in VRAM for the background image.

Can you check how many tiles are you using there?

Also you can read the basics regarding devkitSMS and the way the graphic chip works here. I hope it's explained well enough.
  View user's profile Send private message Visit poster's website
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Tue Jan 16, 2024 5:21 pm
Thanks to you and for the link of the DevkitSMS "How devkitSMS/SMSlib works "I will try to progress on my game, I will abandon for the moment the scrolling parallax I think because as soon as I remove it everything works well my animations of the spaceship works well and my scrolling without parallax runs well without glitch, first of all I will try to understand the machine well because I am starting, if there is another example on the DevkitSMS on the uses of the functions I am interested, I translate to make myself understood sorry if it is not correct.[
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Wed Jan 17, 2024 8:19 am
Leopardcookies wrote
I will abandon for the moment the scrolling parallax I think because as soon as I remove it everything works well my animations of the spaceship works well and my scrolling without parallax runs well without glitch


this confirms that your issue is that the line interrupt runs while your spaceship tiles are being transferred, which is something you will be able to avoid only by making sure that the transfer happens *completely* during vblank.

How many tiles do you load for the spaceship animation? During vblank you can push as many as 20 tiles to VRAM provided you use the UNSAFE (quick) functions.
  View user's profile Send private message Visit poster's website
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Wed Jan 17, 2024 5:53 pm
I think that must be the problem, I load 2 images on the sprite board for the animation of my spaceship, I attached an image of the sprite board, that's 16 colors... I can load this image with Gaiden compression but not the other uncompressed formats, what should I do if you have examples? thanks thanks
IMG_7675.jpeg (2.17 MB)
IMG_7675.jpeg

  View user's profile Send private message
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Wed Jan 17, 2024 8:36 pm
I saved under bmp2tiles with the extension .3bpp this time with 8 colors but I still have the pixel boiled... I call my sprite with:UNSAFE_SMS_load4TIles(sprite_3bpp,256) my decor takes about 247 tiles
IMG_7678.jpeg (2.05 MB)
IMG_7678.jpeg

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Jan 18, 2024 8:37 am
There's currently not direct support for 3bpp tiles. Save your sprite tiles in raw binary format. Also the UNSAFE functions should be used only during vblank.
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
SRAM + PSGLIB
Post Posted: Sat Jan 20, 2024 6:38 pm
Hi Sverx, found a trouble between libraries !!!! Let's see if you can help...

I explain, I have a records table saved in the SRAM. Currently I have a conditional compilation (to save the records in ram variables, or use the SRAM bank to save those records).

The fact is that, using ram variables, everything works perfect.

And if I use SRAM, every works the same (my unit is well tested, it just work the same picking&updating from ram or sram the values).

What is the trouble???

In my games, I have a line interrupt to play the music, something like this:


// Init audio
void InitAudio(void)
{
   // Set the interrupt
   SMS_setLineInterruptHandler(&UpdatePSG);
   SMS_setLineCounter (160);
   SMS_enableLineInterrupt();
}

// Update el PSG
void UpdatePSG(void)
{
   // Push the bank
   unsigned char oldbank=ROM_bank_to_be_mapped_on_slot2;
   
   // Update music
   if(musicbank)
   {
      SMS_mapROMBank(musicbank);
      PSGFrame();
   }

   // Update sounds
   if(PSGSFXGetStatus())
   {
      SMS_mapROMBank(soundbank);
      PSGSFXFrame();
   }

   // Return to old bank
   SMS_mapROMBank(oldbank);
}


If I am playing music, when I enter to the records table, the game locks when I use SMS_enableSRAM(); the music stops.... and after a bunch (about 20-30segs) of time the game continue without errors, but with that big lag... it is like everything goes way slower with the interrupt function switching between the sram bank and the music one... is this the cause???

As this is for the competition, can send you privately the rom, & code if you think this can be solved and it is of help for you.

Regards!
  View user's profile Send private message
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
Post Posted: Sat Jan 20, 2024 6:40 pm
Other thing, is that, although everything else works with SDCC 4.4, I found that the SRAM code does not work with that sdcc version, but does with 4.3 (the same code updated from github, and the same code of my game).

Regards.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Jan 20, 2024 8:03 pm
eruiz00 wrote
If I am playing music, when I enter to the records table, the game locks when I use SMS_enableSRAM(); the music stops...


Yes, unfortunately the SRAM is mapped at the same address as the ROM banks, so you can't access ROM data when SRAM is enabled.

I think you should pause the music, get the highscores on screen, disable SRAM again and resume playing.

As for your issue with SDCC 4.4, does it happen even with some trivial code?
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
Post Posted: Sat Jan 20, 2024 8:17 pm
Yeah, I realized that was the trouble. The game works, do not fail, but it seems that switching between a conventional ROM bank and the SRAM one is way (way!!!) slower that between the usual ROM Banks.

I have put the records table in a "musicless" context and it works without trouble at all.

About the SDCC 4.4 issue, I will send you (maybe this evening, maybe tomorrow) a little sample with the error.

Regards
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sun Jan 21, 2024 3:29 pm
eruiz00 wrote
it seems that switching between a conventional ROM bank and the SRAM one is way (way!!!) slower that between the usual ROM Banks


I'm not sure what you mean here, as these operations actually just write a single byte at a specific address in both cases.

For instance to map ROM bank 3 you do
SMS_mapROMBank(3);

which turns into this single operation
load into memory at address 0xffff the value 3


and to enable SRAM you do
SMS_enableSRAM();

which turns into this single operation
load into memory at address 0xfffc the value 8


also SRAM R/W access is just as fast as RAM or ROM access... so maybe you meant something else?
  View user's profile Send private message Visit poster's website
  • Joined: 12 Dec 2021
  • Posts: 43
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Mon Jan 22, 2024 12:00 am
eruiz00 wrote

In my games, I have a line interrupt to play the music, something like this:


// Init audio
void InitAudio(void)
{
   // Set the interrupt
   SMS_setLineInterruptHandler(&UpdatePSG);
   SMS_setLineCounter (160);
   SMS_enableLineInterrupt();
}



I was doing a similar thing for a while, but you might want to try a better option for dealing with PSGs specifically. Something like this:


#define PSGLIB_MULTIBANK 1

void psgHandler(void)
{
    SMS_saveROMBank();
    PSGFrame();
    SMS_restoreROMBank();
}

// Hook to play the PSG frame even if the CPU is held up doing other stuff
SMS_setFrameInterruptHandler(&psgHandler);
PSGPlay(your_music_psg, your_music_psg_bank);


Note that I'm using the banked version of PSGPlay with the define at the top, so that the PSGPlay function call stores and remembers the bank that the PSG file is in; this way, I can easily use the ROM save/restore around the PSGFrame and not need to remember what ROM the music is in as it'll auto-map it itself.

The Frame Interrupt Handler, from what I understand, will suspend whatever the CPU is doing at the time to run its code, every frame, then return. This was really helpful because I had some CPU-intensive code that was slowing down the music, and this allows the music to play without issue.

One thing to remember, do not under any circumstances try to mess with the VDP or other stuff in the frame interrupt because you'll likely experience a crash :)
  View user's profile Send private message
  • Joined: 12 Dec 2021
  • Posts: 43
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Mon Jan 22, 2024 1:47 am
Random question about SMS_loadSTMcompressedTileMap... would there be an "easy" way to provide an offset to this function to tell it where to start in the tiles?

At the moment, the BMP2tile tool needs to be told where it starts, but this is a bit of a pain. If you're making a scene and moving things around a bit, then having to load the tiles, determine where they should be loaded from, then go back to the assets, update the config there, recompile the assets, test it... it's a bit of back-and-forth.

I had a look at the asm code, just briefly, looks like it might kinda tricky to do. Hmm...
  View user's profile Send private message
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Mon Jan 22, 2024 8:46 am
sverx wrote
I see - decompressing the tiles probably takes too much.

So I can see two options: first is to store all the spaceship tiles in VRAM beforehand, and use either alternatively.

Second option is to use uncompressed tiles, and load them using
UNSAFE_SMS_load4Tiles(src,tilefrom)


of course I don't know how many tiles your spaceship is, let's pretend is 12 tiles, so you need to call that transfer 3 times. This would be fast enough to be completed before the screen starts drawing again.

If your spaceship is bigger I would suspect there's no way to transfer its tiles during vblank.

Finally after hours and hours of looking for everything was said in your post and it finally worked, I loaded my uncompressed sprites and the result is surprising thank you.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon Jan 22, 2024 9:31 am
darkowl wrote
Random question about SMS_loadSTMcompressedTileMap... would there be an "easy" way to provide an offset to this function to tell it where to start in the tiles?


Unfortunately, no. I see your struggle but we're still lacking a (compressed) data format that can be 'moved' following a relocation of the tiles it points too. I suspect the faster approach could be to use uncompressed data that you offset to your liking during loading (or during compilation if you use assets2banks' :modify feature) and when you've got to a satisfactory solution you switch to compressed STMs.
Far from being optimal, though...

Regarding your frame interrupt post, above... the only downside of using that instead of what eruiz00 is using, is that the frame interrupt triggers when vblank starts and -usually- you don't want to spend that time for anything that is not *fast* VRAM transfers. So using a line interrupt way before vblank to make sure your music runs regularly is indeed a good approach to save your vblank cycles :)
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon Jan 22, 2024 9:39 am
Leopardcookies wrote
Finally after hours and hours of looking for everything was said in your post and it finally worked, I loaded my uncompressed sprites and the result is surprising thank you.


Great!
You see, nobody said it would be easy to write a game for the SMS ;)
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14745
  • Location: London
Reply with quote
Post Posted: Mon Jan 22, 2024 10:13 am
Quote
We do this not because it is easy, but because we thought it would be easy
  View user's profile Send private message Visit poster's website
  • Joined: 15 Mar 2021
  • Posts: 31
Reply with quote
Post Posted: Mon Jan 22, 2024 1:14 pm
I do it mainly because I am passionate about the master system of its architecture and its graphic possibilities... we can do beautiful things despite its limitations here and there...
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Mon Jan 22, 2024 2:00 pm
Leopardcookies wrote
we can do beautiful things despite its limitations here and there...


I agree!

Maxim wrote
Quote
We do this not because it is easy, but because we thought it would be easy


This could indeed be a good tagline for devkitSMS :rotflmao:
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
Post Posted: Mon Jan 22, 2024 9:33 pm
A question with a (i think) known response... but It would be great for the new game....

Could be possible to pause/stop a song in psglib.... play other song.... and then return to the first song when the second finished???

Currently, I am replaying the first song from the beggining, but It would be great... maybe an uncompressed psg does save the channels instructions each frame and this is possible?

Regards
  View user's profile Send private message
  • Joined: 12 Dec 2021
  • Posts: 43
  • Location: Melbourne, Australia
Reply with quote
Post Posted: Tue Jan 23, 2024 7:48 am
sverx wrote
Unfortunately, no. I see your struggle but we're still lacking a (compressed) data format that can be 'moved' following a relocation of the tiles it points too. I suspect the faster approach could be to use uncompressed data that you offset to your liking during loading (or during compilation if you use assets2banks' :modify feature) and when you've got to a satisfactory solution you switch to compressed STMs.
Far from being optimal, though...

Regarding your frame interrupt post, above... the only downside of using that instead of what eruiz00 is using, is that the frame interrupt triggers when vblank starts and -usually- you don't want to spend that time for anything that is not *fast* VRAM transfers. So using a line interrupt way before vblank to make sure your music runs regularly is indeed a good approach to save your vblank cycles :)


Yeah, I figured as much. Is there any way to... I dunno, read in compressed tilemaps and somehow store them to working memory? That seems like a probably terrible idea. I guess my experience is only working with STM-compressed tilemaps from ROM so I wouldn't even know where to start with assembling an uncompressed version, except for small things where I can measure the tiles myself. I could do like a "loading" thing at the start, dump them with a black palette and store them for later use but I feel that's bordering on pushing the SMS' hardware memory limits too far? Something I need to learn!

As for the music, that's really interesting! I've found that the line interrupt has been a bit finnicky for me, often crashing on an outi (usually my own bad ideas haha). A more learned friend said "why don't you use the frame interrupt?" and it was revelatory to me, so this method of using line interrupts as an alternative is helpful. Knowing multiple approaches are always good, along with their pros and cons. I guess because I only found out about the frame interrupt very recently, I'm kinda excited about it :D
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Tue Jan 23, 2024 8:28 am
eruiz00 wrote
Could be possible to pause/stop a song in psglib.... play other song.... and then return to the first song when the second finished???
Currently, I am replaying the first song from the beggining, but It would be great... maybe an uncompressed psg does save the channels instructions each frame and this is possible?


Not currently possible, but you can probably *hack* something that works.
I mean, the PSGlib engine status is held in all these variables so if you backup all these and then start a new tune, then when later this is over you can restore the variables from your backup and call PSGRestoreVolumes() you'll have the previous song resumed from the moment you call PSGFrame() again.
edit: sorry, I just realized this won't work completely, as the library is not saving the frequency for some of the channels. So it may work just partially...

darkowl wrote
Is there any way to... I dunno, read in compressed tilemaps and somehow store them to working memory?


You can compress your tilemaps using ZX7 or aPLib, decompress to RAM using SMS_decompressZX7 or SMS_decompressaPLib but keep in mind these are quite slow to decompress - then you have to go through the data to update them if you need to point to tiles that are moved to some different location. But it might work, depending on what you need.

The other approach, as said, is to use uncompressed tilemaps and using the assets2banks :modify attribute, add a constant to each unsigned int value at compile time. More info can be found here - scroll down to where it says:

Also, by using:
:modify <action> <value>
all the array elements will be modified using the provided action and value.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Thu Jan 25, 2024 5:23 pm
I just pushed an update to assets2banks - I hope I didn't break anything but I had to refactor quite a bit of code to make it possible to add the new features I wanted.

I hope you'll enjoy the new features! And let me know if your workflow breaks...
  View user's profile Send private message Visit poster's website
  • Joined: 27 Feb 2023
  • Posts: 136
  • Location: France
Reply with quote
Post Posted: Sat Jan 27, 2024 10:43 am
eruiz00 wrote
A question with a (i think) known response... but It would be great for the new game....

Could be possible to pause/stop a song in psglib.... play other song.... and then return to the first song when the second finished???

Currently, I am replaying the first song from the beggining, but It would be great... maybe an uncompressed psg does save the channels instructions each frame and this is possible?

Regards

I was reading the topic to ask the same thing, as it would be a very good feature in games where the music changes often (in a RPG, where you go in a battle then resume the worldmap music for example). Having a nice fade-in effect from where the music left would help a lot in making the music not too repetitive.

Definitely interested in (a way to achieve) such a feature for the future, if possible :)

In the meantime, I might do two versions of the music, one that starts in the beginning and one in the middle, and will do a fade-in effect and alternate between both.
  View user's profile Send private message
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
Post Posted: Sat Jan 27, 2024 2:57 pm
cireza wrote
eruiz00 wrote
A question with a (i think) known response... but It would be great for the new game....

Could be possible to pause/stop a song in psglib.... play other song.... and then return to the first song when the second finished???

Currently, I am replaying the first song from the beggining, but It would be great... maybe an uncompressed psg does save the channels instructions each frame and this is possible?

Regards

I was reading the topic to ask the same thing, as it would be a very good feature in games where the music changes often (in a RPG, where you go in a battle then resume the worldmap music for example). Having a nice fade-in effect from where the music left would help a lot in making the music not too repetitive.

Definitely interested in (a way to achieve) such a feature for the future, if possible :)

In the meantime, I might do two versions of the music, one that starts in the beginning and one in the middle, and will do a fade-in effect and alternate between both.


Yeah, I though the same.... to have several tracks of the same song, each with a different start (and it is not a bad a idea, as, in this case, they are short, and do not take too much rom memory)... I think it would be nice (if possible and has sense from a hardware point of view) to have a psg format which have the info for all the channels in each frame.... (I think sverx & company should be definitely tired of us... always asking for features, maybe we should investigate and learn how the things work and try to do the code, instead of bugging so much :D )

LITTLE QUESTION: Those who play the roms in their Master System / Genesis (I suppose they have a cartridge with a memory card or something like....) have SRAM support with those cartridges? the game for this year relies on save status to advance.

Regards
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 3828
  • Location: Stockholm, Sweden
Reply with quote
Post Posted: Sat Jan 27, 2024 4:57 pm
A possible workaround could be the following.
Say you have a *quite long* tune and you want to restart it from some specific point(s) after an interruption: what you could do is to break this tune into N parts and save them as if they were N separate tunes.
Then you start with the first one and when you detect it's done (using PSGGetStatus() ) you start the next one, and so on.
When you need to restart, you just restart the one you were playing.
Of course the higher is the number of parts the better, but you can probably get a good result even with just 4 or 5 parts in most cases.

eruiz00 wrote
Those who play the roms in their Master System / Genesis (I suppose they have a cartridge with a memory card or something like....) have SRAM support with those cartridges?


The Master EverDrive and similar do support SRAM. But not *all* the existing cartridges do, so you should check if SRAM is available.
  View user's profile Send private message Visit poster's website
  • Joined: 28 Jan 2017
  • Posts: 556
  • Location: Málaga, Spain
Reply with quote
Post Posted: Sat Jan 27, 2024 5:24 pm
Nice... in smsdevkit I found that SRAM related info:

/* macro for SRAM access */
volatile __at (0xfffc) unsigned char SRAM_bank_to_be_mapped_on_slot2;
#define SMS_enableSRAM()        SRAM_bank_to_be_mapped_on_slot2=0x08
#define SMS_enableSRAMBank(n)   SRAM_bank_to_be_mapped_on_slot2=((((n)<<2)|0x08)&0x0C)
#define SMS_disableSRAM()       SRAM_bank_to_be_mapped_on_slot2=0x00

/* SRAM access is as easy as accessing an array of char */
__at (0x8000) unsigned char SMS_SRAM[];


It lacks a function to check SRAM availibity.... or I am wrong?

Currently I have a preprocessor based RAM/SRAM utility, so I do not have trouble in compiling two roms (one RAM based and other SRAM based... Green Beret remake has two roms, by example), so no rush. It is only curiosity...

PD. Very good Idea splitting music and wait for its end... have to test it ;)
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 14745
  • Location: London
Reply with quote
Post Posted: Sat Jan 27, 2024 6:46 pm
Most games check SRAM is not blank by reading some marker data (eg “My awesome game save RAM”) and writing it if not present. If it’s still not there after that then there’s no SRAM.
  View user's profile Send private message Visit poster's website
Reply to topic Goto page Previous  1, 2, 3 ... 12, 13, 14, 15, 16, 17  Next



Back to the top of this page

Back to SMS Power!