
 When you release a port, please include YOUR contact information for users
 to report bugs and other problems.

 I get a ton of e-mails about a color problem in the Nokia P900 port of SMS
 Plus because the author apparently included my e-mail address (please link
 to my webpage instead) and listed NO contact information for him/herself.

 Also, let me know when you release a port, so I can forward these types
 of e-mails appropriately.

 ----------------------------------------------------------------------------

 What's changed for SMS Plus v1.2

 I haven't finished up the porting notes so some things aren't covered yet;
 look at the DOS source for an example.

 After calling system_init(), use the following functions:

 system_poweron()  - Call once, can run game afterwards
 system_reset()    - Can call during gameplay if user wants a hard reset
 system_poweroff() - Call once when done with a game.

 When loading multiple ROMs in a single session, you'd call poweroff() when
 done with a game, then poweron() after the next one was loaded.

 SRAM is loaded when poweron() or reset() is called.
 SRAM is saved when poweroff() is called.

 The SRAM management function has changed:

 void system_manage_sram(uint8 *sram, int slot, int mode);

 'mode' is either SRAM_SAVE or SRAM_LOAD.
 The slot parameter is ignored for now.
 If there was SRAM to load, set sms.save = 1;
 Otherwise, clear SRAM to zero.
 See the DOS code for an implementation of this function.

 Sound emulation

 The following structure holds sound related information:

 struct {

     /* Input parameters */
     int sample_rate;
     int fps;
     uint32 psg_clock;
     uint32 fm_clock;
     int fm_which;
     void (*mixer_callback)(int16 **stream, int16 **output, int length);

     /* Working data */
     int16 *stream[STREAM_MAX];
     int16 *output[2];

     /* Outputs */
     int enabled;
     int buffer_size;
     int sample_count;
 } snd;

 Normally you would set up this structure before calling system_init().
 You can change the input parameters and call sound_init() again to change
 them. Here are how the parameters should be used:

 snd.sample_rate    Set to the desired sample rate, e.g. 22050, 44100.
                    Set to 0 to disable sound emulation.

 snd.fps            Set to 50 (PAL) or 60 (NTSC) to specify the emulated
                    sound replay rate. PAL consoles are not completely
                    supported yet, I would advise leaving this at 60.

 snd.psg_clock      Set to the SN76489 clock speed.
                    Normally this is 3579545. (3.58 MHz)

 snd.fm_clock       Set to the YM2413 clock speed.
                    Normally this is 3579545. (3.58 MHz)

 snd.fm_which       Set to SND_EMU2413 or SND_YM2413 depending on the FM
                    sound chip emulator you want to use. You can change
                    this and call sound_init() again for realtime switching.

 snd.mixer_callback Set to NULL to use the default stream mixing routine,
                    or point it to your own.

 Calling sound_init() will return 0 if sound emulation was disabled or an
 error occured, or 1 if initialization was successful. The following
 variables will be valid for use afterwards:

 snd.enabled        Set to 1 if sound emulation is enabled, 0 if disabled.

 snd.buffer_size    Size of sample buffer in bytes.

 snd.sample_count   Length of sample buffer in samples.

 snd.stream         Sound streams for the built-in mixer function or a user
                    supplied one to use.

 snd.output         Mixed audio generated by the built-in mixer function
                    that can be output to a sound device. Updated after each
                    call to system_frame().

 An example of setup and use is as follows:

    // Init code
    snd.sample_rate    = 44100;
    snd.fps            = 60;
    snd.psg_clock      = 3579545;
    snd.fm_clock       = 3579545;
    snd.fm_which       = SND_EMU2413;
    snd.mixer_callback = NULL;
    system_init();

    // Change some parameter later on
    snd.fm_which       = SND_YM2413;
    sound_init();

    // Update code
    system_frame();
    osd_play_stream_stereo( snd.output, snd.buffer_size );

 Custom mixing

 You can provide your own mixing routine to combine audio streams. Some
 uses might include:

 - Per-stream volume adjustment, filtering, effects.
 - Stereo output of YM2413 sound.
 - Bass-boost on YM2413 rhythm output.
 - Can take advantage of in-hardware playback/mixing (console ports, etc.)

 There are four sound streams available:

 STREAM_PSG_L   SN76489 left channel output
 STREAM_PSG_R   SN76489 right channel output
 STREAM_FM_MO   YM2413 melody channel output
 STREAM_FM_RO   YM2413 rhythm channel output

 The two YM2413 outputs are mixed together, along with the PSG output, for
 a single monoaural channel in all versions of the SMS and related hardware
 that support FM sound.

 Synopsis of audio features by console:

                FM sound    Stereo PSG  Output
 Mark III       No          No          Mono
 Mark III+FM    Yes         No          Mono
 SMS 1          No          No          Mono
 SMS 2          No          No          Mono
 SMS 1 (J)      Yes         No          Mono
 Game Gear      No          Yes         Stereo (headphone jack) Mono (speaker)

 Audio from the YM2413 emulator has a lower volume than EMU2413 and will
 need to be adjusted.

 See the default mixer routine in 'sound.c' for an example.

 ----------------------------------------------------------------------------
 Porting notes for earlier 0.9.x versions
 ----------------------------------------------------------------------------

 You can check out the DOS specific code to get an idea of
 how to port SMS Plus.

 0.) Machine dependant issues
 ----------------------------

 Everything should compile fine for big-endian platforms, however
 I'm not sure the 8-bit pixel to 16-bit pixel conversion function
 in 'render.c' is endian safe.

 You need to either define or not define 'IS_BIG_ENDIAN' in your makefile,
 depending on your needs.

 1.) Graphics
 ------------

 The emulated display can be shown in either 8-bit or 16-bit color.
 The following structure is used by the rendering routines to
 draw the display, and you need to set it up prior to running the
 emulation.

    typedef struct
    {
        uint8 *data;
        int width;
        int height;
        int pitch;
        int depth;
        struct
        {
            uint8 color[PALETTE_MAX][3];
            uint8 dirty[PALETTE_MAX];
            uint8 update;
        }pal;
    }t_bitmap;

 'data'     - Pointer to a linear chunk of memory. This should be at least
              256x192 pixels in size. You can modify this pointer between
              frames for double buffering (if it's pointed into memory mapped
              video RAM), or point it to system memory so further changes
              can be made. (like special effects, or for converting the
              graphics data to 24 or 32-bit format)
 'width'    - Width of the bitmap, in pixels.
 'height'   - Height of the bitmap, in pixels.
 'pitch'    - Width of the bitmap, in *bytes*.
 'depth'    - Color depth. Must be 8 or 16.
 'color'    - An array of 32 RGB values, each scaled up to eight bits.
 'dirty'    - Each entry is nonzero if the color has been modified.
 'update'   - Nonzero if one or more colors have been modified.

 If you are using 8-bit color, please note that each pixel drawn to
 the bitmap uses some extra unused bits during the rendering process.
 You can either mask out these bits using the PIXEL_MASK constant
 from 'system.h', or set palette ranges 20-3F, 40-5F to the same
 values as 00-1F.

 If you are using 16-bit color, you can ignore the members of the 'pal'
 structure. Remember to adjust the MAKE_PIXEL macro in 'render.h' to
 whatever format your display uses. By default it will make a 16-bit
 pixel in RGB 5:6:5 format.

 The macros BMP_X_OFFSET, BMP_Y_OFFSET, give the offset into the
 bitmap. This is because the SMS display takes up the entire bitmap,
 while the GG display is centered in the middle. These macros provide
 a convenient way to get the right offset.

 The PALETTE_MAX constant returns the size of the palette.
 This is currently set to 32 entries.

 2.) Sound
 ---------

 Sound emulation is handled through the following structure:

    typedef struct
    {
        int fps;             /* Set to 50 or 60 FPS for PAL or NTSC games */
        int sample_rate;     /* Set between 8000 and 48000 */
        int enabled;         /* 1= Init OK, 0= Sound disabled or error */
        int sample_count;    /* Length of buffer in samples */
        int buffer_size;     /* Size of buffer in bytes */
        int16 *output[2];    /* Left and right channels */
    } snd_t;

 You must call 'system_init()' and pass the desired sample rate as an
 parameter to enable sound emulation. You can set the sample rate to
 zero if you do not want sound emulation. Remember that 'snd.enabled'
 will be set afterwards to indicate if any errors occured.

 You also must call 'system_shutdown()' when you are done running
 the virtual console emulation, so some memory used by the sound
 emulation code can be freed.

 3.) Input
 ---------

 Input is handled through the following structure:

    typedef struct
    {
        int pad[2];
        int system;
    }t_input;

 'pad[]'    - Corresponds to joystick one and joystick two.
 'system'   - System buttons, specifically pause, start, and reset.

 During each frame, you should clear members of this structure to zero,
 then update each one using the INPUT_* constants in 'system.h'.

 4.) Game Images
 ---------------

 Game images are handled through the following structure:

    typedef struct
    {
        uint8 *rom;
        uint8 pages;
        uint8 type;
    }t_cart;

 'rom'      - Pointer to the ROM image.
 'pages'    - ROM size divided by 16k.
 'type'     - Set to either TYPE_SMS or TYPE_GG.

 Games can be identified by their extension, which is usually '.sms'
 or '.gg'. Some games have an optional 512-byte header which you must
 remove. Remember to adjust the file size accordingly.

 5.) Battery backed RAM
 ----------------------

 Some game cartridges can have up to 32k of battery backed RAM present.
 There are two variables relating to this:

    typedef struct
    {
        uint8 sram[0x8000];
        uint8 save;
    }t_sms;

 'sram'     - This is the data that should be saved and loaded.
 'save'     - This is nonzero if the contents of sram[] should be saved.

 It's impossible to know if a game will use battery backed RAM, so the
 emulation code waits until a game tries to read or write it, and then
 sets the 'save' flag meaning the data needs to be saved.

 The basic way to deal with this is:

 1. Load a game file
 2. If a file with the same name, and the extension .sav exists,
    then load that data into 'sram' and set the 'save' flag.
 3. When exiting, check if the 'save' flag is nonzero, and if so,
    write the contents of sram[] to a file with the extension .sav
    and the same filename as the game file loaded.

 Note that when system_reset() is called, the function 'system_load_sram'
 which has a prototype in 'system.h' will be called. You *must* implement
 this function. All it has to do is see if any saved battery backed RAM
 is present, and update the save/sram[] members accordingly.

 6.) Miscellaneous
 -----------------

 Before running the virtual console emulation, you can set up
 these two variables:

 sms.use_fm         :   0= No YM2413 sound, 1= YM2413 sound
 sms.country        :   Set to TYPE_DOMESTIC (Japan), TYPE_OVERSEAS

 Some games will display different text depending on the country
 setting. The default value is TYPE_OVERSEAS. This is suitable for every
 country but Japan.

 Some games have different music if the YM2413 sound chip is present.
 If the 'fm_enable' value is set to one, then games can detect it.

 If you want to use FM sound, you must ensure that 'use_fm' is nonzero
 before loading a game, since this variable controls if games can detect
 the YM2413 chip as well as actual YM2413 output.

 Some games will only enable YM2413 sound if the country type is
 also set to TYPE_DOMESTIC. One such example is Wonderboy 3.

 Both of these variables are preserved when system_reset() is called.

 You can call load_state/save_state to save and restore the current state
 of the virtual console emulation. You need to pass a file handle as
 a parameter to these functions. Therefore, you are responsible for ensuring
 the file exists, and the file name. The naming convention is that all
 state files are named '.st0' up to '.st9'.

 7.) Function reference
 ----------------------

    void system_init(int sound_rate);

 You must set up the 'bitmap' and 'cart' structures prior to calling this
 function. If you want sound emulation, pass the desired sample rate
 (8000..44100). Afterwards, check the members of the 'snd' structure to see
 if you can use sound emulation. You can now call system_frame() and the like.

    void system_shutdown(void);

 Call this when you're done with the emulation. Not terribly important
 as it only frees some memory allocated by the sound emulation routines...

    void system_reset(void)

 Reset the virtual console emulation. This is called internally when
 the INPUT_HARD_RESET flag for 'input.system' is set.

    void system_load_sram(void);

 Refresh the 'sms.sram[]' and 'sms.save' variables.
 You must impelement this function yourself.

    void system_frame(int skip);

 You need to call this function 60 times a second. Pass zero as the
 parameter to draw the current frame, otherwise pass one to omit
 the drawing process. (ideal for frame skipping) Afterwards,
 the 'bitmap' and 'snd' structures will be updated with the current
 graphics and sound data. You should set up the 'input' structure
 before calling this function.

 8.) Example
 -----------

 Here's a brief overview of how to use all this:

 - do machine dependant initialization (audio, video, init input, etc.)
 - set up bitmap structure
 - set up cart structure (load game)
 - call system_init()
 - if snd.enabled is set, we can use sound
 - load sram data if it exists for the game
 in a loop:
   - update input structure based on gamepad/keyboard
   - call system_frame()
   - play sound using 'snd.buffer'
   - copy 'bitmap.data' to the video display
   - quit if needed
 - save sram data if the game used it
 - call system_shutdown()

 9.) Other notes on porting
 --------------------------

 - Please read the license first.

 - You must release the source code to your port in accordance with the GPL.

   If you have made *no* changes to the main source code, meaning everything
   in the root directory, and the cpu and dos directories, then you
   do not have to include those files. No point in wasting space.

   Otherwise, you must include those files with the changes clearly stated.
   If the changes are the kind that could benefit other ports (like a bug
   fix), then just let me know so I can update the main distribution, and
   don't bother releasing those files. But let me know before you release
   your port, however.

   If you are using some commercial libraries to take care of items like
   audio output, or if you have developed some routines which you do not want
   made public (i.e. an assembly optimized blitter, or some custom joypad
   polling functions), then you do not have to include those files.

   I prefer it where anybody can download a port of SMS Plus and compile it
   themselves, but I realize this isn't always possible.

   It would be nice, and is not required, that you could organize the
   source in the same way I have it set up. For instance, maintaining the
   same directory structure, but adding an '/myport' directory with your
   specific files, and an appropriate makefile.

 - You must clearly state in the executable that you are the porter,
   and that I wrote the program. Include YOUR contact information (e-mail
   address, website URL). This is so users will not ask me questions on how
   to use a specific port, which I know nothing about.

 - You need to provide documentation. Please remember to mention
   the licensing stuff pertaining to SMS Plus and the MAME code that's
   mentioned (for example) in the original 'readme' I wrote. Or just
   include my documentation and make some additions.

   Please link to my website in the documentation, so people will know
   where to get the original source code.
