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/SMSlib - missing/requesting features

Reply to topic Goto page 1, 2, 3, 4  Next
Author Message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
devkitSMS/SMSlib - missing/requesting features
Post Posted: Fri Apr 01, 2016 11:15 am
Last edited by sverx on Mon May 16, 2016 11:21 am; edited 3 times in total
I feel like there are still missing features in the devkit/library, so here's a list of what I plan to add, if there's some demand for it.
It would be nice to know which of these feature you would want to see added first, or if there are some features still missing in this list.
It's a sort of small survey where you can actually choose more than one option. Thanks for the feedback! :)


3] SMS II specific functions (to activate 256x224 and 256x240 video modes and handle sprites and tilemaps while in these modes)
4] functions to handle programmable sound generator (PSG) directly
5] support for Genesis/MD pad for second player too
6] support for GameGear link cable
7] support for 32 KB paging
9] Light Phaser support
0] other (please specify)

edit: already implemented:
1] access to VDP status bits (sprite collision and sprite overflow flags)
2] functions to enhance sprite handling
8] SRAM support
  View user's profile Send private message Visit poster's website
  • Joined: 04 Jul 2010
  • Posts: 202
  • Location: Angers, France
Reply with quote
Post Posted: Fri Apr 01, 2016 12:59 pm
Maybe a function which active / read / write SRAM can be interesting (for rpg, status, hi-score...)

(as i'm not using your SDCC lib, i do not know if it's already incorporated or not)
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Fri Apr 01, 2016 1:26 pm
Nice suggestion! I added it to the list! :) Thanks!
  View user's profile Send private message Visit poster's website
  • Joined: 04 Jul 2010
  • Posts: 202
  • Location: Angers, France
Reply with quote
Post Posted: Fri Apr 01, 2016 1:27 pm
You're welcome ;)
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 319
  • Location: Spain
Reply with quote
Post Posted: Sun Apr 03, 2016 2:38 pm
My vote also for SRAM!
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Mon Apr 04, 2016 11:50 am
Last edited by sverx on Mon Apr 04, 2016 12:09 pm; edited 1 time in total
SRAM support is on the way :)
(unfortunately it seems both MEKA and Emulicious doesn't like what I'm doing :| ... or I'm doing something incredibly stupid... )
Are emulators supposed to support RAM at address $8000?

edit: it was me doing stupid things.
But anyway it still doesn't work with MEKA (works as expected on Emulicious).
  View user's profile Send private message Visit poster's website
  • Joined: 17 Sep 2013
  • Posts: 113
  • Location: Gravataí, RS, Brazil
Reply with quote
Post Posted: Mon Apr 04, 2016 12:07 pm
A function that returns witch incarnation of the hardware you are running from (SMS1, SMS2 or Genesis)
  View user's profile Send private message
  • Joined: 14 Apr 2013
  • Posts: 430
Reply with quote
Post Posted: Mon Apr 04, 2016 12:10 pm
sverx wrote
SRAM support is on the way :)
(unfortunately it seems both MEKA and Emulicious doesn't like what I'm doing :| ... or I'm doing something incredibly stupid... )
Are emulators supposed to support RAM at address $8000?

Yes, both support that.
What are you doing that they don't seem to like?
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Mon Apr 04, 2016 12:27 pm
Calindro wrote
Yes, both support that.
What are you doing that they don't seem to like?


Well, can't say. I'm simply writing to $8000 after having set $fffc to $08... and it works with Emulicious (it generates a .sav file in my project folder).
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Mon Apr 04, 2016 12:28 pm
gvx32 wrote
A function that returns witch incarnation of the hardware you are running from (SMS1, SMS2 or Genesis)


Is there really request for that? If so, I might try writing a code snippet...
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Tue Apr 05, 2016 8:45 am
1] VDP status bits (sprite collision and sprite overflow)
and
8] SRAM support
have just been added.

How to query VDP status bits?

Just AND the 'SMS_VDPFlags' (extern) variable with the proper constants as in:
if (SMS_VDPFlags & VDPFLAG_SPRITEOVERFLOW)

and
if (SMS_VDPFlags & VDPFLAG_SPRITECOLLISION)

the variable will be updated at each vblank.

How to use SRAM?

Before you can access SRAM, you should enable it using either the macro:
SMS_enableSRAM()

or if you've got more than 16KB SRAM you can use the macro:
SMS_enableSRAMBank(n)

(you'd access bank 0 and bank 1, of 16KB each)


Then, you'll read/write to SRAM as if it was just a plain unsigned char array, through the provided SMS_SRAM[ ] (or you can build your structs on top of it, as I did in my example... see below).

After that, you should disable access to SRAM, so that 'regular' ROM mapping could work again, using:
SMS_disableSRAM()


Here's a small example on how to define a struct in SRAM and query/read/write it:

#include "SMSlib.h"
#include <stdbool.h>

#define MAGIC  0xACE0B001
// define your own unique MAGIC!

// 'savegame' struct
struct my_savegame {
  unsigned long Magic;   // this is here to check if the SRAM contains a savegame or not
  unsigned char lives;   // your hero lives counter
  unsigned int points;   // your hero points

  // add your own variables here

};

// here's declaring that my_savegame struct will go into SRAM
struct my_savegame *savegame = (struct my_savegame*)(&SMS_SRAM);

// your regular vars
unsigned char lives = 3;
unsigned int  points = 0;

// read SRAM and check if MAGIC is present
bool isSaveGamePresent (void) {
  bool foundMagic;
  SMS_enableSRAM();
  foundMagic=(savegame->Magic==MAGIC);
  SMS_disableSRAM();
  return(foundMagic);
}

// read SRAM and load regular vars from values stored in SRAM
void readSaveGame (void) {
  SMS_enableSRAM();
  lives=savegame->lives;
  points=savegame->points;
  // etc...
  SMS_disableSRAM();
}

// store your values into SRAM
void writeSaveGame (void) {
  SMS_enableSRAM();
  savegame->Magic=MAGIC;
  savegame->lives=lives;
  savegame->points=points;
  // etc...
  SMS_disableSRAM();
}

void main (void) {
  if (isSaveGamePresent()) {
    readSaveGame();
    points++;           // here's just to change some value
  }
  writeSaveGame();

  for (;;);
}
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Wed Apr 06, 2016 2:49 pm
Last edited by sverx on Thu Apr 07, 2016 12:32 pm; edited 3 times in total
gvx32 wrote
A function that returns witch incarnation of the hardware you are running from (SMS1, SMS2 or Genesis)


I just wrote a function that checks if you're running on a SMS 'II' or not, exploiting the famous 'zoomed sprites' bug which affects the first SMS and the fact that SMS sprite zooming is not supported on Genesis.

I'm not adding this into the library, at least for now, but everyone's free to use it, if he finds it useful :)

so here's the code (untested, also because I don't own a Genesis or a first revision SMS...), with an example usage (turns the screen green or red according to result):

#include "SMSlib.h"
#include <stdbool.h>

bool isSMSII (void) {
  unsigned char i;
  SMS_VRAMmemset (0x0000, 0xFF, 32);         // a 'full' tile
  SMS_useFirstHalfTilesforSprites(true);
  SMS_setSpriteMode (SPRITEMODE_ZOOMED);
  SMS_initSprites();
  for (i=0;i<5;i++)
    SMS_addSprite (16*i, 0, 0);  // first 5 sprites, evenly spaced horizontally
  SMS_addSprite (16*i-1, 0, 0);  // 6th sprite, one pixel 'too' to the left
  SMS_finalizeSprites();
  SMS_waitForVBlank();           // wait VBlank
  SMS_copySpritestoSAT();        // copy sprites to SAT
  SMS_waitForVBlank();           // wait next VBlank...
  // ... and if it's a SMSII the collision flag will be ON
  return (SMS_VDPFlags & VDPFLAG_SPRITECOLLISION);
}

void main (void) {
  if (isSMSII()) {
    SMS_setBGPaletteColor(15,RGB8(0x00,0xFF,0x00));
    SMS_setSpritePaletteColor(15,RGB8(0x00,0xFF,0x00));
  } else {
    SMS_setBGPaletteColor(15,RGB8(0xFF,0x00,0x00));
    SMS_setSpritePaletteColor(15,RGB8(0xFF,0x00,0x00));
  }
  SMS_displayOn();
  for (;;);
}


and here's a compiled ROM of this (updated this too):
isSMSII.zip (969 B)
check if it's an SMS II

  View user's profile Send private message Visit poster's website
  • Joined: 17 Sep 2013
  • Posts: 113
  • Location: Gravataí, RS, Brazil
Reply with quote
Post Posted: Wed Apr 06, 2016 3:15 pm
Nice, I believe that checking for the first line of vblank is a little more compatible with emulators, but using sprites can also be used to diferentiate SMS1 from a GENESIS. I wonder if there is a way to diferentiate a Game Gear from a SMS2.
  View user's profile Send private message
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11902
  • Location: London
Reply with quote
Post Posted: Wed Apr 06, 2016 8:40 pm
It's really a test for doubled sprite capability, and that's what any users ought to strive for: detect the features, not the system. Some features are not detectable in code, though, so you might infer from the ones you can detect when all else fails.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu Apr 07, 2016 8:48 am
Yeah, doing the same collision test using just two 'zoomed' sprites you can detect if the hardware has zoom capabilities or not, e.g. if it's a Genesis.
Personally, I think one would more probably just see if 256x224 is available, and thus detect if it's a SMS II or not. But everyone's free to change the code to suit his needs :)
  View user's profile Send private message Visit poster's website
  • Joined: 23 Mar 2013
  • Posts: 525
  • Location: Copenhagen, Denmark
Reply with quote
Post Posted: Thu Apr 07, 2016 10:40 am
gvx32 wrote
I wonder if there is a way to diferentiate a Game Gear from a SMS2.

I'm in a little over my head here, so excuse me if this is a bad suggestion. But since the SMS BIOS sets up the paging registers at power on, and the Game Gear doesn't, could testing $ffff to see if it is not zero then not be used to determine if program is on a Game Gear or an SMS? (and then the zoomed sprites to differentiate between SMS1 and SMS2)...?
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu Apr 07, 2016 11:00 am
hang-on wrote
[...] since the SMS BIOS sets up the paging registers at power on, and the Game Gear doesn't [...]


I'm not really sure it's always so, as I remember resetting the mapper at start-up (on SMS) was suggested as a good practice... but, well, I really don't know TBH.
  View user's profile Send private message Visit poster's website
  • Joined: 17 Sep 2013
  • Posts: 113
  • Location: Gravataí, RS, Brazil
Reply with quote
Post Posted: Thu Apr 07, 2016 11:13 am
Not all bioses initialize the mapper, and some mappers initialize thenselfes. But the Bios does leave some signature on RAM, this I believe could be used. I just don know if all japanese systems have bios.

Edit.:A better to detect a bios is problably do the same thing that the bios does to detect a cartdrige, just run code from Ram that tries to map the bios to the address space, if that works, than you know you are in a system with Bios.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu Apr 07, 2016 12:29 pm
I just fixed the isSMSII() function code, it was plain wrong. I was placing the 5th sprite on the 4th instead of placing the 6th sprite on the 5th (which is the first that won't be horizontally zoomed on a SMS 'I').
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Wed Apr 13, 2016 10:02 am
I just added
Quote
9] Light Phaser support

to the list.
I'm wondering if I should start from scratch or if there's someone willing to share some tested ASM code so that I can integrate it directly...
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 68
Reply with quote
Post Posted: Fri Apr 15, 2016 9:07 pm
A TV mode function, would be great. To detect NTSC or PAL.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Fri Apr 15, 2016 9:10 pm
It's already there. Example code:

if (SMS_VDPType() & VDP_NTSC)
    SMS_setBGPaletteColor(0,0x03);    // red
  else if (SMS_VDPType() & VDP_PAL)
    SMS_setBGPaletteColor(0,0x30);    // blue
  View user's profile Send private message Visit poster's website
  • Joined: 28 May 2015
  • Posts: 68
Reply with quote
Post Posted: Fri Apr 15, 2016 9:17 pm
sverx wrote
It's already there. Example code:

if (SMS_VDPType() & VDP_NTSC)
    SMS_setBGPaletteColor(0,0x03);    // red
  else if (SMS_VDPType() & VDP_PAL)
    SMS_setBGPaletteColor(0,0x30);    // blue


Oh okay, thanks!

By the way, i release the game in main section. 8)
  View user's profile Send private message
  • Joined: 29 Mar 2012
  • Posts: 319
  • Location: Spain
Reply with quote
Post Posted: Thu May 12, 2016 10:37 am
Today i was thinking on that:
A function to directly decompress STM compressed tilemaps to RAM (Instead of loading them to VRAM). It could be useful to check contents of the tilemap without loading it on VRAM.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu May 12, 2016 11:10 am
Surely it can be done, but if you need to uncompress to RAM you could use other (stronger) compression techniques... STM has been expressly crafted with VRAM in mind and, honestly, it's quite limited as it works only with fullscreen (or at least fullwidth) images. :|
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 319
  • Location: Spain
Reply with quote
Post Posted: Thu May 12, 2016 12:08 pm
well know i'm loading the tilemap on VRAM and later copying from VRAM to RAM in order to generate the collision map
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu May 12, 2016 12:42 pm
void SMS_unpackSTMcompressedTileMap (unsigned char *dst, unsigned char *src) {
  unsigned int HH=0x0000;
  unsigned int oldHH=0x0000;
  unsigned char cur;
  unsigned char cnt;
  bool needRestore=false;

  while (true) {
    cur=*src++;
    if (cur & 0x01) {
      if (cur & 0x02) {
        /* RLE of successive words */
        HH=(HH & 0xFF00)|*src++;
        cnt=(cur>>2)+2;
        while (cnt>0) {
          *dst++=HH % 256;
          *dst++=HH / 256;
          if (cnt>1)
            HH++;
          cnt--;
        }
      } else {
        /* RLE of same words */
        HH=(HH & 0xFF00)|*src++;
        cnt=(cur>>2)+2;
        while (cnt>0) {
          *dst++=HH % 256;
          *dst++=HH / 256;
          cnt--;
        }
      }
    } else {
      if (cur & 0x02) {
        /* new HH */
        if (cur & 0x04) {
          /* temporary, thus save HH into oldHH */
          oldHH=HH;
          needRestore=true;
        }
        HH=((cur>>3)<<8);
        continue;         /* to skip the restore check at the end of the while block */
      } else {
        /* RAW */
        cnt=(cur>>2);
        if (cnt==0)
          break;          /* done, thus exit the while block */
        while (cnt>0) {
          *dst++*src++;
          *dst++=HH / 256;
          cnt--;
        }
      }
    }
    if (needRestore) {
      HH=oldHH;
      needRestore=false;
    }
  } /* end while */
}


still untested...
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 319
  • Location: Spain
Reply with quote
Post Posted: Thu May 12, 2016 1:47 pm
Oh!! great!

actually, i reimplemented the compressor, because i'm converting from rle compressed NES tilemaps to SMS STMcompressed tilemaps :-p

PD: A first glimpse on what i'm trying to do.... Extremely buggy and unplayable, but it's a direct conversion from neslib C code...
alterego.zip (20.27 KB)

  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu May 12, 2016 5:24 pm
STMcompression is based on RLE, and compresses runs of tiles with successive index too. Also, it is exploiting the fact that the 3 msb of the tile entry are unused. If you need to achieve better compression, anyway, I still suggest you to use stronger compressors such as aPlib and decompress it to RAM using
void aPLib_depack (void *dest, void *src);

and then set your tilemap from the data you've got in RAM.
(see devkitSMS/aPlib for the above mentioned function)

... and I'll test your ROM ASAP :)
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Fri May 13, 2016 7:56 am
I just gave a quick look at the ROM... it's cool!!! I never heard that game before (never been reading about ZX or NES news...) but it seems a nice puzzler, and indeed it seems to pan out well on our SMS. So, please, do complete the work and release a polished product, as we need so much to have 100% finished products to showcase, both for my lib and for the SMS homebrew scene. So, thanks! :D
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 319
  • Location: Spain
Reply with quote
Post Posted: Fri May 13, 2016 8:29 am
Of course i'll finish it :-) . These is one month work on commuting train (10-15 minutes every day), and it needs a lot of polish, but most of the hard work is already done :-)
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Mon May 16, 2016 11:18 am
I just added the functions for enhanced sprite handling. The idea behind that (which came from the GBAdv library for the GameBoy Advance I wrote few years ago...) is that you could reserve sprites that you will define (and move/redefine) at a later stage. This also changed slightly the way the usual functions worked, as now the SMS_addSprite will return a signed char which is the sprite 'handle' (or -1 if it fails) instead of returning a boolean.
The new functions are:
signed char SMS_reserveSprite (void);
void SMS_updateSpritePosition (signed char sprite, unsigned char x, unsigned char y);
void SMS_updateSpriteImage (signed char sprite, unsigned char image);
void SMS_hideSprite (signed char sprite);


SMS_reserveSprite defines an offscreen sprite, that you will define later, and returns it handle, SMS_updateSpritePosition and SMS_updateSpriteImage are used to change sprite position / image, and SMS_hideSprite hides (moves offscreen) an already defined sprite.

Also, a few days ago, I added a few small functions to update palette entries, which is especially useful for palette cycle effects:
SMS_setNextBGColoratIndex(i);                       /* macro - sets which BG color to set next */
SMS_setNextSpriteColoratIndex(i);                   /* macro - sets which sprite color to set next */
void SMS_setColor (unsigned char color);            /* set color */


the idea behind these is that if you need to change a (small) number of successive entries of either palette you just 'set' the number of the first entry you want to update and then issue as many SMS_setColor as the number of colors you need to update.

I hope you find both these added features useful. Please, let me know if something doesn't work as expected.
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 319
  • Location: Spain
Reply with quote
Post Posted: Mon May 16, 2016 11:28 am
Oh!!it looks wonderful!

Just waiting to try both functionalitys!
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu Jun 02, 2016 5:00 pm
kusfo wrote
A first glimpse on what i'm trying to do.... Extremely buggy and unplayable, but it's a direct conversion from neslib C code...


Any update on this? My EverDrive is eager to play it :D
  View user's profile Send private message Visit poster's website
  • Joined: 29 Mar 2012
  • Posts: 319
  • Location: Spain
Reply with quote
Post Posted: Fri Jun 03, 2016 6:21 am
Doing it, i need to adjust a bit of every map, as the tilemaps are thought for the 32x30 nes tilemap (Also, they're RLE compressed, so i have to decompress them, touch a bit the flat tilemap, and the encode them on STM).

I hope to finish sometime around mid-summer :-D
  View user's profile Send private message
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Tue Jun 07, 2016 10:39 am
A couple of rand8 / rand16 funcions which are fast and tight would be great. The rand implementation in sdcc just plainly sucks big time.

Or just wait until I need rand16 in my current project as I'll be porting the one I use with z88dk for the ZX Spectrum and CPC. I'll share.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Tue Jun 07, 2016 12:05 pm
Do share, please, as I think I won't add any random generator into SMSlib.
Anyway as I posted (here in the other thread) I'm using a very simple approach in Weka Invaders (w.i.p.): I've got a 256 bytes LUT filled with numbers I generated using an online generator (this one) and a simple macro to get a number from the table:
#define FAKE_RAND()  (LUT_fake_rand[fake_rand_index++])

(fake_rand_index is an unsigned char, of course).
That's very fast and the data wastes only 256 bytes in ROM, and looks random enough for my needs.
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Fri Jun 10, 2016 11:22 am
Also very useful in game development: palette functions, all working over a specified palette range:

- Fade in, fade out, variable rate.
- Adjust brightness, let's you dim or saturate to white.
- Palette rotation left & right.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Fri Jun 10, 2016 12:05 pm
I believe that even if it would be very useful and common code, a programmer should handle palette the way he loves, as there is more than one single way to palette fade/cycle. Then it all boils down to call

void SMS_loadBGPalette (void *palette);
void SMS_loadSpritePalette (void *palette);

when you need to change a whole palette, or

void SMS_setBGPaletteColor (unsigned char entry, unsigned char color);
void SMS_setSpritePaletteColor (unsigned char entry, unsigned char color);

when you just want to change a single color, or even

SMS_setNextBGColoratIndex(i);                       /* macro - sets which BG color to set next */
SMS_setNextSpriteColoratIndex(i);                   /* macro - sets which sprite color to set next */
void SMS_setColor (unsigned char color);            /* set color */

when you want to change a variable amount of colors in either the BG or the sprite palette.

There are also handy macros for generating a color from its RGB components, either separate or packed:

RGB(r,g,b)  /* values 0-3 */
RGB8(r,g,b)   /* values 0-255 */
RGBHTML(RGB24bit)  /* HTML-like int value, as in 0xrrggbb */
  View user's profile Send private message Visit poster's website
  • Joined: 07 Oct 2015
  • Posts: 105
Reply with quote
Post Posted: Fri Jun 10, 2016 12:51 pm
I was aware of such functions, just thought that adding the stuff inside the lib would make such operations way faster.

For my current project I'm putting all these things inside a module I compile alongside the library, so I have access to all the inner assets and arrays directly. Time is tight in a 8 bits system, every clock tick you can save is a win. I will share when I'm done. I'm sure more will find this routines of use.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Fri Jun 10, 2016 1:12 pm
Yes, again, please do share! I think we can have a collection of useful snippets kept in the local wiki here :)

(as for the specific palette fading topic, I personally prefer having the palettes pre-calculated and stored in ROM. Wasting a few ROM bytes that's saving CPU cycles :D )
  View user's profile Send private message Visit poster's website
  • Joined: 16 May 2002
  • Posts: 1088
  • Location: italy
Reply with quote
Post Posted: Mon Jun 27, 2016 11:30 am
I was wondering how hard it would be to integrate support for other sound engines into your development kit, for example the smps engine used in Sonic games.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Mon Jun 27, 2016 11:40 am
I don't really know how the smps engine works, but it's quite easy to write a C wrapper for ASM functions.
Said that, how would you then create music and sound effects? Are there tools around for that?
  View user's profile Send private message Visit poster's website
  • Joined: 16 May 2002
  • Posts: 1088
  • Location: italy
Reply with quote
Post Posted: Mon Jun 27, 2016 2:56 pm
sverx wrote
Are there tools around for that?
Almost.

There are many tools for the "16-bit" version of the smps engine, I started the trend myself in 2007 with the first "xm to smps" converter which basically opened the flood gates of music editing for the Mega Drive / Genesis version of Sonic 1. Other programmers followed suit with other converters (ValleyBell, for example, wrote a "midi to smps" converter) and miscellaneous tools.

There are significant differences between the "8-bit" and the "16-bit" smps flavours, though most of the existing tools can be easily improved and/or adapted for the new task.

I'm not saying that it would be better or worse than the psglib you use now, just that it would be an alternative. For one, it would require less ROM space since I seem to understand that psglib songs can be quite demanding in terms of size.

Perhaps ValleyBell himself would be able to provide useful details about the smps engine, since he knows everything about it. Seriously, he's awesome like that.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Mon Jun 27, 2016 7:08 pm
Very interesting! I guess some of you who know this thing well may work on creating an ASM library and enhance the needed tools, then we can make a C wrapper together, thus giving the homebrewers both the chance to use that library in their projects either if they use ASM or if they prefer C.

As for better/worse, I guess it depends on the specific case. I myself would love to have an alternative choice :)
  View user's profile Send private message Visit poster's website
  • Joined: 15 Sep 2009
  • Posts: 368
Reply with quote
Post Posted: Wed Jun 29, 2016 6:50 pm
If you want to include SMPS songs for one of the SMS/GG variants in a ROM, the only proper way is to use ASM'ed songs.
However, you can use xm#smps/mid2smps to create MD-SMPS songs that use only the drum channel + all 3 PSG channels and convert those to ASM using one of the smps2asm tools.
ASM is required, because the songs use absolute CPU space pointers.

In order to include an SMPS driver in the ROM, it would be optimal to have a disasm of an existing driver. I have disassemblies of:
Dragon Crystal [preSMPS], Phantasy Star [preSMPS with FM], Sonic 2 Auto Demo (GG), Sonic 2 (MS) and Sonic Triple Trouble
My disasms use the Intel number format though, so they probably aren't compatible with WLA DX.
Including the drivers as a binary blob should be possible, as they usually have their own ROM bank, but you need to find the music/SFX pointer tables and patch them.


Using SMPS drivers is very easy - everything is controlled by memory triggers in the sound RAM area.

SoundRAM+$03: play a song/sound effect or execute a command
  • $00 is used to initialize the SMPS driver (because the memory usually is cleared with that value)
  • $81-$FF play/execute something - the order is music, sfx, commands
    The exact ID ranges differ per game. Using $FF to stop everything should be safe though, because all drivers seem to catch invalid IDs.
  • The order of the "commands" is usually: fade music out, stop all music/SFX, stop SFX, stop special SFX? (have to investigate the last one).

SoundRAM+$08: pause trigger
  • It's set to $00 when music is playing and to $7F when paused.
  • set to $80 to pause the music, $00 resumes


Using the sound driver from Sonic 1 is a bit more difficult, as it involves calling certain ASM routines. There's a jump table for them right at the beginning of the sound bank though. And the songs can be precompiled, as they use only relative offsets.
  View user's profile Send private message
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Wed Jun 29, 2016 9:20 pm
Do you think it's possible to modify the engine to make it play songs with relative pointers? This way we could have the engine play the tunes/SFXs anywhere in ROM, and should be quite easy to manage them then.
Having something that can handle FM music too would be very nice :)
  View user's profile Send private message Visit poster's website
  • Site Admin
  • Joined: 19 Oct 1999
  • Posts: 11902
  • Location: London
Reply with quote
Post Posted: Wed Jun 29, 2016 10:00 pm
Most games have the songs and engine in the same bank, and the CPU address space pointers would "just work" provided it was mapped to the expected slot. It might be easier if you could generate that bank (packing the engine and data) and then incorporate it as a blob.

Otherwise you need to be messing with paging, and that would probably lead you to needing to put the engine in the lower 32KB, which seems bad.
  View user's profile Send private message Visit poster's website
  • Joined: 05 Sep 2013
  • Posts: 1958
Reply with quote
Post Posted: Thu Jun 30, 2016 7:39 am
I got your point, but having code paged-out isn't really a nice idea IMHO.
I also believe the SMPS engine isn't much bigger than PSGlib engine, so it's probably not going to bloat the code anyway.
  View user's profile Send private message Visit poster's website
  • Joined: 15 Sep 2009
  • Posts: 368
Reply with quote
Post Posted: Thu Jun 30, 2016 2:14 pm
Paging sound code out seems pretty common, actually.
All SMPS-based games do that and Sonic 1 does it, too. (Even though it requires bank switching for every sound call in the latter case.)

The average size of an SMPS engine is about $900 bytes (PSG only) or $E00 bytes (PSG+FM).That excludes modulation/volume envelopes, which shared by all songs/sfx and have to be banked in while updating the sound.
  View user's profile Send private message
Reply to topic Goto page 1, 2, 3, 4  Next



Back to the top of this page

Back to SMS Power!