aboutsummaryrefslogtreecommitdiff
path: root/source/doc/porting.txt
diff options
context:
space:
mode:
Diffstat (limited to 'source/doc/porting.txt')
-rw-r--r--source/doc/porting.txt725
1 files changed, 0 insertions, 725 deletions
diff --git a/source/doc/porting.txt b/source/doc/porting.txt
deleted file mode 100644
index 3d28eec..0000000
--- a/source/doc/porting.txt
+++ /dev/null
@@ -1,725 +0,0 @@
- How to Port Snes9x to a New Platform
- ====================================
-
-Version: 1.01
-Date: 23-December-1998
-
-(c) Copyright 1998 Gary Henderson (gary@daniver.demon.co.uk)
-
-Introduction
-============
-
-This is brief description of the steps involved in porting Snes9x, the Super
-Nintendo Entertainment System emulator, to new hardware which is at least
-similar to Workstation or PC. It describes what code you have to write and
-what functions exist that you can make use of. It also gives some insights as
-to how Snes9x actually works, although that will be subject of another
-document yet to be written.
-
-Host System Requirements
-========================
-
-A C++ compiler, so you can compile the emulator! Snes9x really isn't written
-in C++, it just uses the C++ compiler as a 'better C' compiler to get inline
-functions and so on. With some modification, it could be converted to be
-compiled with an ordinary C compiler. Snes9x isn't very C type safe and
-will probably not work on a system who's integers are less than 32-bits wide
-without lots of editing.
-
-If the host system uses a CPU that implements the i386 instruction set then
-you will also want to use the three assembler CPU cores, although I recently
-scrapped the SPC700 assembler code (too many bugs) and replaced it with
-compiler generated assembler code that I haven't got around to optimising
-yet. The 65c816 and SPC700 code needs to be assembled using the GNU
-assembler that comes with gcc and the Super FX code assembled with NASM
-v0.97 or higher. gcc is available from lots of sites. NASM is available from
-http://www.cryogen.com/Nasm
-
-A fast CPU. SNES emulation is very compute intensive: two, or sometimes three
-CPUs to emulate, an 8-channel 16-bit stereo sound digital signal processor
-with real-time sample decompression, filter and echo effects, two custom
-graphics processor chips that can produce transparency, scaling, rotation
-and window effects in 32768 colors, and finally hardware DMA all take their
-toll on the host CPU.
-
-Lots of RAM. The SNES itself has 128k work RAM, 64k V-RAM and 64k sound CPU
-RAM. If a Super FX game is being emulated, that usually comes with another
-64k inside the game pack. Snes9x itself needs 4Mb to load SNES ROM images
-into (or 6Mb if I ever figure out the SNES memory map of the 48Mbit ROM
-images out there), 256k to cache decompressed sound samples in, 512k to
-cache converted SNES tiles in, and another 64k for S-RAM emulation. And
-that's not counting a few large lookup tables that the graphics code needs
-for speeding up transparency effects plus few other tables used by the ZSNES
-Super FX code. It all adds up to 7Mb (ish). Add to that RAM needed to
-store the actual emulator code and RAM required by the host operating system
-and any other process that is running; that's lots of RAM. Well, it is if
-your host system only has a few mega-bytes of RAM available.
-
-An 8-bit, 256 color (one byte per pixel) or deeper display, at least 256x239
-pixels in resolution, or 512x478 if you're going to support the SNES'
-hi-res. background screen modes. Ideally, a 16-bit, 65536 color screen mode
-is required if you want to support transparency at speed, as that is what the
-code renders internally. Any other format screen, with transparency enabled,
-will require picture format conversion before you can place the rendered
-SNES image on to the screen.
-
-Sound output requires spooling 8-bit or 16-bit, mono or stereo digital sound
-data to the host computer's sound hardware. The DOS port uses interrupts
-from the sound card to know when more sound data is required, most other
-ports have to periodically poll the host sound hardware to see if more data
-is required; if it is then the SNES sound mixing code provided by Snes9x is
-called to fill an area of system memory with ready mixed SNES sound data,
-which then can be passed on to the host sound hardware. Sound data is
-generated as an array of bytes (uint8) for 8-bit sound or shorts (int16) for
-16-bit data. Stereo sound data generates twice as many samples, with each
-channel's samples interleaved, first left's then right's.
-
-For the user to be able to control and play SNES games, some form of input
-device is required, a joystick or keyboard, for example. The real SNES can
-have 2 eight-button digital joy-pads connected to it or 5 joy-pads when an
-optional multi-player adaptor was purchased, although most games only require
-a single joy-pad. Access to all eight buttons and the direction pad, of
-course, are usually required by most games. Snes9x does emulate the
-multi-player adaptor hardware, if you were wondering, but its still up to
-you to provide the emulation of the individual joy-pads.
-
-The SNES also had a mouse and light gun available as optional extras,
-Snes9x can emulate both of these using some form of pointing device,
-usually the host system's mouse.
-
-If an accurate, constant SNES play rate is required, then a real-time timer
-will be needed that can time intervals of 16.7ms (NTSC frame time) or 20ms
-(PAL frame time).
-
-Some SNES game packs contained a small amount of extra RAM and a battery so
-ROMs could save a player's progress through a game for games that takes many
-hours to play from start to finish. Snes9x simulates this S-RAM by saving
-the contents of the area of memory normally occupied by the S-RAM into file
-then automatically restoring it again the next time the user plays the same
-game. If the hardware you're porting to doesn't have a hard disk available
-then you could be in trouble.
-
-Snes9x also implements freeze-game files which can record the state of the
-SNES hardware and RAM at a particular point in time and can restore it to
-that exact state at a later date - the result is that users can save a game
-at any point, not just at save-game or password points provided by the
-original game coders. Each freeze file is over 400k in size. To help save
-disk space, Snes9x can be compiled with zlib, which is used to compress the
-freeze files, reducing the size to typically below 100k. Download zlib from
-its homepage at http://www.cdrom.com/pub/infozip/zlib/, compile Snes9x with
-ZLIB defined and link with zlib. zlib is also used to load any compressed
-ROM images Snes9x my encounter, compressed with gzip or compress.
-
-Porting
-=======
-
-In theory you will only need to edit port.h, then in a separate file write
-all the initialisation code and interface routines that Snes9x expects the
-you to implement. You, no doubt, will discover otherwise....
-
-There are several compile-time only options available:
-
-DEBUGGER
---------
-
-Enables extra code to assist me in debugging SNES ROMs. The debugger has only
-ever been a quick-hack by me and user-interface to debugger facilities is
-virtually non-existent. Most of the debugger information is output via
-stdout and enabling the compile-time options slows the whole emulator down
-slightly. However, the debugger options available are very powerful; you
-could use it to help get your port working. You probably still want to ship
-the finished version with the debugger disabled, it will only confuse
-non-technical users.
-
-VAR_CYCLES
-----------
-
-I recommend you define this. The main CPU in the SNES actually varies in
-speed depending on what area of memory its accessing and the ROM access
-speed of the game pack; defining VAR_CYCLES causes Snes9x to emulate this,
-using a good approximation, rather than fixed cycle length as ZSNES does. The
-resultant code is slightly slower. Leaving it undefined results in many more
-emulation timing errors appearing while playing games.
-
-CPU_SHUTDOWN and SPC700_SHUTDOWN
---------------------------------
-
-Again I recommend defining both of these. They are both speed up hacks.
-When defined, Snes9x starts watching for when either the main or sound CPUs
-are in simply loops waiting for a known event to happen - like the end of
-the current scan-line, and interrupt or a sound timer to reach a particular
-value. If Snes9x spots either CPU in such a loop it uses its insider
-knowledge to simply skip the emulation of that CPU's instructions until the
-event happens. It can be a big win with lots of SNES games.
-
-I'm constantly amazed at the ingenuity of some programmers who are able to
-produce complex code to do simple things: some ROM's wait loops are so
-complex Snes9x fails to spot the CPU is in such a loop and the shutdown
-speed up hacks don't work.
-
-You might be wondering why VAR_CYCLES, and the two SHUTDOWN options have to
-be enabled with defines, well, in the past they sometimes introduced
-problems with some ROMs, so I kept them as options. I think I've fixed all
-the problems now, but you never know...
-
-SPC700_C
---------
-
-Define this if you are using the C/C++ version of the SPC700 CPU core. It
-enables a ROM compatibility feature that executes SPC700 instructions during
-SNES DMA, it allows several games to start that would otherwise lock up and
-fixes music pauses when ROMs do lots of DMA, usually when switching between
-game screens.
-
-ZLIB
-----
-
-Define this if you have the zlib library available and you want it to
-compress freeze-game files to save disk space. The library is also used to
-support compressed ROM images.
-
-NO_INLINE_SET_GET
------------------
-
-Define this to stop several of the memory access routines from being
-defined in-line. Whether the C++ compiler actually in-lines when this symbol
-is not defined is up to the compiler itself. In-lines functions can speed up
-the C++ CPU emulations on some architectures at the cost of increased code
-size. Try fiddling with this option once you've got port working to see if
-it helps the speed of your port.
-
-EXECUTE_SUPERFX_PER_LINE and ZSNES_FX
--------------------------------------
-
-Define these if you're going to be using the ZSNES Super FX i386 assembler
-code, otherwise leave them both undefined. In theory,
-EXECUTE_SUPERFX_PER_LINE can also be defined when using the C++ Super FX
-emulation code, but the code is still buggy and enabling the option
-introduces more problems than it fixes. Any takers for fixing the C++ code?
-
-JOYSTICK_SUPPORT, SIDEWINDER_SUPPORT and GRIP_SUPPORT
------------------------------------------------------
-
-These options enable support for various input devices in the UNIX and MS-DOS
-port code. They're only of interest if you're able to use the existing UNIX
-or MS-DOS port specific code.
-
-port.h
-======
-
-If the byte ordering of the target system is least significant byte first,
-make sure LSB_FIRST is defined in this header, otherwise, make sure its not
-defined.
-
-If you're going to support 16-bit screen rendering (required if you want
-transparency effects) and your system doesn't use RGB 565 - 5 bits for red,
-6 bits for green and 5 bits for blue - then you'll need make sure RGB555,
-BGR565 or BGR555 is defined instead. You might want to take a look at the
-*_LOW_BIT_MASKs, *_HI_BIT_MASKs and BUILD_PIXEL macros to make sure they're
-correct, because I've only every tested the RGB565 version, though the Mac
-port uses the RGB555 option. If your system is 24 or 32-bit only, then
-don't define anything; instead write a conversion routine that will take a
-complete rendered 16-bit SNES screen in RGB565 format and convert to the
-format required to be displayed on your hardware.
-
-port.h also typedefs some types, uint8 for an unsigned, 8-bit quantity,
-uint16 for an unsigned, 16-bit quantity, uint32 for a 32-bit, unsigned
-quantity and bool8 for a true/false type. Signed versions are also
-typedef'ed.
-
-The CHECK_SOUND macro can be defined to invoke some code that polls the
-host system's sound hardware to see if it can accept any more sound data.
-Snes9x makes calls to this macro several times when it is rendering the SNES
-screen, during large SNES DMAs and after every emulated CPU instruction.
-
-Since this CHECK_SOUND macro is invoked often, the code should only take a
-very small amount of time to execute or it will slow down the emulator's
-performance. The Linux and UNIX ports use a system timer and set a variable
-when it has expired; the CHECK_SOUND only has to check to see if the
-variable is set. On the MS-DOS and Mac ports, the sound hardware is not
-polled at all, instead it is driven by interrupts or callbacks and the
-CHECK_SOUND macro is defined to be empty.
-
-Initialisation Code
--------------------
-
-This is what the Linux, UNIX and MS-DOS ports do, I suspect your code
-might be similar:
-
-- The Settings structure is initialised to some sensible default values -
- check the main function in unix.cpp for the values it uses.
-
-- The command line is parsed, options specified override default values in
- the Settings structure and specify a ROM image filename that the user
- wants loaded. Your port could load user preferences from a file or some
- other source at this point. Most values, with a little care, can be changed
- via a GUI once the emulator is running.
-
-- Some Settings structure value validation takes place, for example if
- transparency effects are requested the code also makes sure 16-bit
- screen rendering is turned on as well.
-
-- Memory.Init() and S9xInitAPU() are called, checking neither failed. The
- only reason they would fail is if memory allocation failed.
-
-- Memory.LoadROM (filename) is called to load the specified ROM image into
- memory. If that worked Memory.LoadSRAM (sram_filename) is called to load
- the ROM's S-RAM file, if one exists. The all current ports base the
- sram_filename on the filename of the ROM image, changing the file's
- extension (the .smc or whatever bit) and changing the directory where its
- located - you won't be able to save S-RAM files onto a CD if that's where
- the ROM image is located!
-
- If your port has a GUI, you can delay this step until the user picks an
- image to load.
-
- SNES roms images come in all shapes and sizes, some with headers, some
- without, some have been mangled by the copier device in one of two ways, and
- some split into several pieces; plus the SNES itself has several different
- memory map models. The code tries to auto-detect all these various types,
- but sometimes the SNES ROM header information has been manually edited by
- someone at some stage and the code guesses wrong. To help it out it these
- situations, the Settings structure contains several options to force a
- particular ROM image format; these values must be initialised prior to each
- call to Memory.LoadROM(filename).
-
-- The Linux and UNIX ports now do some more operating system initialisation
- ready for a system timer to be started.
-
-- The host display hardware is now initialised. The actual screen depth and
- resolution should be picked based on the user preferences if possible.
- The X Window System port can't control the screen depth or resolution, if
- the user requests transparency effects but the display hardware is only
- set to 8-bit, it has to invoke an extra step of converting the 16-bit SNES
- rendered screen to a fixed palette 8-bit display just before the SNES
- screen is copied to the display hardware.
-
- The GFX.Screen pointer needs to be initialised to point to an array of
- uint8 for 8-bit screen rendering or uint16 for 16-bit rendering, cast to
- an array of uint8. The array needs to be at least 256x239 bytes or shorts
- in size for lo-res only support (Settings.SupportHiRes = FALSE) or
- 512x478 for lo-res and hi-res support. If transparency effects are
- required, the GFX.SubScreen array also needs to be initialised to another
- identically sized array of the same type, otherwise it can be just
- initialised to NULL.
-
- The GFX.Pitch variable needs to be set to the number of bytes on each line
- of the arrays, e.g. 256 for lo-res only support, up to 1024 for 16-bit
- hi-res support. If GFX.Screen is pointing into an existing array, one
- created by the library function rather than just calling malloc or new,
- then set GFX.Pitch to the number of bytes per line of that array,
- including any padding the library function may have added.
-
- If the target hardware supports fast access to video RAM, the screen is in
- 16-bit format supported by the SNES rendering code and you can double
- buffer the display, you might want to point GFX.Screen directly at the
- video buffer RAM. You will need to recompute the GFX.Delta value every
- time you change the GFX.Screen value to double-buffer the rendering and
- display.
-
-- A call to S9xGraphicsInit() is made; make sure all your graphics rendering
- options are setup correctly by now. If later, you want to change some
- settings, for example 16-bit to 8-bit rendering, call S9xGraphicsDeinit()
- first, change your settings, GFX.Screen and GFX.SubScreen arrays, etc.,
- then call S9xGraphicsInit() again.
-
-- S9xInitSound(int playbackrate, bool8 stereo, int sound_buffer_size)
- is now called, which in turn will call your S9xOpenSoundDevice function -
- see below.
-
-- The display is switched to graphics mode using a call to S9xGraphicsMode().
-
-- The system timer is started; its used for keeping the emulator speed
- relatively constant on the MS-DOS port and noting when the sound hardware
- sound should be able to accept more sound data on the Linux and UNIX ports.
-
-- A main loop is entered which is just a loop constantly calling
- S9xMainLoop() then polling the operating system for any pending events
- such as key presses and releases, joystick updates, mouse position
- updates, GUI user interaction, etc.
-
- Pause functionality can be implemented by skipping the call to S9xMainLoop
- and muting the sound output by calling S9xSetSoundMute (TRUE).
-
- Don't enter the main loop until a SNES ROM image has been loaded, or at
- least skip calling S9xMainLoop inside the loop until one is and make sure
- S9xReset is called instead before entering the main loop. The Mac port
- implements this technique by starting in pause mode and refusing to unpause
- until a ROM image is loaded.
-
- S9xMainLoop processes SNES CPU emulation, SNES screen rendering, DMA and
- H-DMA emulation, until emulated scan-line 0 is reached, then it returns.
- Now is your chance to process any system events pending, scan the
- keyboard, read joystick values, etc.
-
- If DEBUGGER compile-time support is enabled and the CPU emulation has hit
- a break point or single-stepping is switched on, or the DEBUG_MODE_FLAG is
- set in the CPU.Flags variable, then the S9xMainLoop routine returns early,
- allowing you to act on the event in some way. The Linux, DOS and UNIX ports
- respond to the DEBUG_MODE_FLAG being set by calling S9xDoDebug(), which in
- turn outputs the current instruction and loops reading commands from stdin
- and outputting debug information, currently via stdout. The debugger
- desperately needs rewriting to support a GUI interface, more descriptive
- commands and better error handling; maybe one day...
-
-Existing Interface Routines
----------------------------
-
-These are routines already written that you will either need to call or
-might find useful.
-
--> bool8 Memory.Init ()
-
-Allocates and initialises several major lumps of memory, for example
-the SNES ROM and RAM arrays, tile cache arrays, etc. Returns FALSE if
-memory allocation fails.
-
--> void Memory.Deinit ()
-
-Undoes the memory allocations made by Memory.Init.
-
--> bool8 S9xGraphicsInit ()
-
-Allocated and initialises several lookup tables used to speed up SNES
-graphics rendering. Call after you have initialised the GFX.Screen,
-GFX.SubScreen and GFX.Pitch values. If Settings.Transparency is false it
-does not allocate tables used to speed up transparency effects. If you
-want to provide the user with option to turn the effects on and off during
-game play, make sure Settings.Transparency is true when this function is
-called, it can later be set to FALSE.
-
-Returns FALSE if memory allocation fails.
-
--> void S9xGraphicsDeinit ()
-
-Undoes the memory allocations made by S9xGraphicsInit.
-
--> bool8 S9xInitAPU ()
-
-Allocates and initialises several arrays used by the sound CPU and sound
-generation code.
-
--> void S9xDeinitAPU ()
-
-Undoes the allocations made by S9xInitAPU.
-
--> bool8 S9xInitSound (int mode, bool8 stereo, int buffer_size)
-
-Does more sound code initialisation and opens the host system's sound hardware
-by calling the S9xOpenSoundDevice function provided by you.
-
--> void S9xReset ()
-
-Resets the SNES emulated hardware back to the state it was in at 'switch-on'
-except the S-RAM area is presevered. The effect is it resets the current game
-back to the start. This function is automatically called by Memory.LoROM.
-
--> bool8 Memory.LoadROM (const char *filename)
-
-Attempts to load the specified ROM image filename into the emulated ROM area.
-There are many different SNES ROM image formats and the code attempts to
-auto-detect as many different types as it can and in a vast majority of the
-cases gets it right. However, some ROM images have been edited by someone at
-some stage or have been mangled by the ROM copier that produced them and
-LoadROM needs help. Inparticular, it can't auto-detect the odd way in which
-some Super FX games have been mangled and needs to be told, via
-Settings.Interleaved2, that the ROM image is in that format, or that
-odd-sized ROM images have a 512 byte copier header.
-
-There are several other ROM image options in the Settings structure;
-allow the user to set them before calling LoadROM, or make sure they all
-reset to default values before each call to LoadROM.
-
--> bool8 Memory.LoadSRAM (const char *filename)
-
-Call this routine to load the associated S-RAM save file (if any). The
-filename should be based on the ROM image name to allow easy linkage.
-The current ports change the directory and the filename extension of the ROM
-filename to derive the S-RAM filename.
-
--> bool8 Memory.SaveSRAM (const char *filename)
-
-Call this routine to save the emulated S-RAM area into a file so it can
-be restored again the next time the user wants to play the game. Remember
-to call this when just before the emulator exits or when the user has been
-playing a game and is about to load another one.
-
--> void S9xMainLoop()
-
-The emulator main loop. Call this from your own main loop that calls this
-function (if a ROM image is loaded and the game is not paused), processes
-any pending host system events, then goes back around the loop again until
-the emulator exits.
-
-S9xMainLoop normally returns control to your main loop once every emulated
-frame, when it reaches the start of scan-line zero. However, the routine
-can return more often if the DEBUGGER compile-time flag is defined and the
-CPU has hit a break point, or the DEBUG_MODE_FLAG bit is set in CPU.Flags
-or instruction single-stepping is enabled.
-
--> void S9xMixSamples (uint8 *buffer, int sample_count)
-
-Call this routine from your host sound hardware handling code to fill the
-specified buffer with ready mixed SNES sound data. If 16-bit sound mode is
-choosen, then the buffer will be filled with an array of sample_count int16,
-otherwise an array of sample_count uint8. If stereo sound generation is
-selected the buffer is filled with the same number of samples, but in pairs,
-first a left channel sample followed by the right channel sample.
-
-There is a limit on how much data S9xMixSamples can deal with in one go and
-hence a limit on the sample_count value; the limit is the value of the
-MAX_BUFFER_SIZE symbol, normally 4096 bytes.
-
--> bool8 S9xSetSoundMute (bool8 mute)
-
-Call with a TRUE parmeter to prevent S9xMixSamples from processing SNES
-sample data and instead just filling the return buffer with silent sound
-data. Useful if your sound system is interrupt or callback driven and the
-game has been paused either directly or indirectly because the user
-interacting with the emulator's user interface in some way.
-
--> bool8 S9xFreezeGame (const char *filename)
-
-Call this routine to record the current SNES hardware state into a file,
-the file can be loaded back using S9xUnfreezeGame at a later date effectively
-restoring the current game to exact same spot. Call this routine while
-you're processing any pending system events when S9xMainLoop has returned
-control to you in your main loop.
-
--> bool8 S9xUnfreezeGame (const char *filename)
-
-Restore the SNES hardware back to the exactly the state it was in when
-S9xFreezeGame was used to generate the file specified. You have to arrange
-the correct ROM is already loaded using Memory.LoadROM, an easy way to
-arrange this is to base freeze-game filenames on the ROM image name. The
-Linux, UNIX and DOS ports load freeze-game files when the user presses a
-function key, with the names romfilename.000 for F1, romfilename.001 for F2,
-etc. Games are frozen in the first place when the user presses Shift-function
-key. You could choose some other scheme.
-
--> void S9xNextController ()
-
-The real SNES allows several different types of devices to be plugged into
-the game controller ports. The devices Snes9x emulates are a joy-pad,
-multi-player adaptor (allowing a further 4 joy-pads to be plugged in),
-a 2-button mouse and a light gun known as the SuperScope.
-
-Each call to S9xNextController will step the current emulated device on to
-the next device in the sequence multi-player, joy-pad, mouse on port 1,
-mouse on port 2, light gun then back to multi-player again. Defines
-allocating a number of each device type are in snes9x.h. The currently
-selected device is stored in IPPU.Controller if you want to give some
-feedback to the user. The initial value of IPPU.Controller (set when
-S9xReset is called) is obtained from Settings.ControllerOption based on
-currently enabled options.
-
-Some ROMs object to certain non-joy-pad devices being plugged into the real
-SNES while they are running, all Super FX games should only allow joy-pads to
-be plugged in because the Super FX chip and any other device would overload
-the SNES power supply. Tetris and Dr. Mario also objects for reasons best
-known to itself. For this reason there are switches in the Settings
-structure to enable and display the emulation of the various devices.
-
-const char *S9xGameGenieToRaw (const char *code, uint32 &address, uint8 &byte)
-
-const char *S9xProActionReplayToRaw (const char *code, uint32 &address,
- uint8 &byte)
-
-const char *S9xGoldFingerToRaw (const char *code, uint32 &address, bool8 &sram,
- uint8 &num_bytes, uint8 bytes[3])
-
-void S9xApplyCheats (bool8 apply)
-
-void S9xRemoveCheats ()
-
-void S9xAddCheat (uint32 address, bool8 cpu_address, bool8 sram, uint8 num_bytes,
- uint8 byte1, uint8 byte2, uint8 byte3)
-
-void S9xDeleteCheats ()
-
-void S9xDoDebug ()
-
-Interface Routines You Need to Implement
-----------------------------------------
-
-bool8 S9xOpenSnapshotFile (const char *base, bool8 read_only, STREAM *file)
-***************************************************************************
-void S9xCloseSnapshotFile (STREAM file)
-***************************************
-
-Routines to open and close freeze-game files. STREAM is defined as a
-gzFile if ZLIB is defined else its defined as FILE *. The read_only parameter
-is set to TRUE when reading a freeze-game file and FALSE when writing a
-freeze-game file.
-
-void S9xExit ()
-***************
-
-Called when some fatal error situation arises or when the 'q' debugger
-command is used. The Mac port just beeps and drops back to the GUI when
-S9xExit is called, the MS-DOS, Linux and Solaris ports all call exit () to
-terminate the emulator process.
-
-void S9xParseArg (char **argv, int &index, int argc)
-****************************************************
-
-void S9xExtraUsage ()
-*********************
-
-If you're going to be using the simple command line parser, when it
-encounters an unknown option it calls S9xUsage which is supposed to report
-all options the generic parse knows about (I haven't been keeping it up to
-date of late). S9xUsage then, in turn calls S9xExtraUsage which you
-implement to report any port-specific options available.
-
-void S9xGraphicsMode ()
-***********************
-void S9xTextMode ()
-*******************
-
-The SNES debugger calls these routines to switch from a graphics screen
-mode used to display the SNES game to a debugger screen used to display
-debugger output. If the SNES screen can be displayed at the same time as
-a text display, as would be the case when the host system implements a
-graphical window system, or you're not going to support the SNES debugger,
-then these routines should do nothing.
-
-On the X Window System UNIX/Linux port, these routines do nothing where as
-on the MS-DOS port they switch between a graphics screen mode and a text-only
-screen mode.
-
-bool8 S9xInitUpdate ()
-**********************
-
-Called just before Snes9x starts to render a SNES screen. The Windows port
-uses this call to lock Direct X screen area to allow exclusive access; on
-other existing ports its implemented as an empty function.
-
-bool8 S9xDeinitDisplay (int width, int height, bool8 sixteen_bit)
-*****************************************************************
-
-Called once a complete SNES screen has been rendered into the GFX.Screen
-memory buffer, now is your chance to copy the SNES rendered screen to the
-host computer's screen memory. The problem is that you have to cope with
-different sized SNES rendered screens. Width is always 256, unless you're
-supporting SNES hi-res. screen modes (Settings.SupportHiRes is TRUE), in
-which case it can be 256 or 512. The height parameter can be either 224 or
-239 if you're only supporting SNES lo-res. screen modes, or 224, 239, 448 or
-478 if hi-res. SNES screen modes are being supported.
-
-All current ports support scaling the SNES screen to fill the host system's
-screen, the many ports even supports interpolation - blending the colours of
-adjacent pixels to help hide the fact they've been scaled - and scan-line
-simulation - slightly darkening every other horizontal line.
-
-Don't forget that if you're just placing the SNES image centerally in the
-screen then you might need to clear areas of the screen if the SNES image
-changes size between calls to S9xDeinitDisplay. The MS-DOS and UNIX ports
-currently don't do this which results in junk being left on the screen if
-the ROM changes SNES screen modes.
-
-The sixteen_bit is just a copy of the Settings.SixteenBit setting and if
-TRUE indicates a 16-bit SNES screen image has been rendered, 8-bit otherwise.
-
-void S9xMessage (int type, int number, const char *message)
-***********************************************************
-
-I've started work on converting all the old printfs into calls to this
-routine. When Snes9x wants to display an error, information or warning
-message, it calls this routine. Check in messages.h for the types and
-individual message numbers that Snes9x currently passes as parameters.
-
-The idea is display the message string so the user can see it, but you
-choose not to display anything at all, or change the message based on the
-message number or message type.
-
-Eventually all debug output will also go via this function, trace information
-already does.
-
-bool8 S9xOpenSoundDevice(int mode, bool8 stereo, int buffer_size)
-*****************************************************************
-
-S9xInitSound calls this function to actually open the host operating system's
-sound device, or initialise the sound card in MS-DOS port.
-
-The mode parameter is the value passed in on the command line with the -r
-command line flag, assuming you're using the Snes9x parser. Its meant to
-indicate what playback the sound hardware should be set to, value 1 to 7.
-I think the real SNES sound chip playback rate is 30kHz, but such high
-playback rates take a lot of native CPU power to emulate. The default
-playback rate is 22kHz for the MS-DOS and UNIX ports.
-
-The stereo flag indicates if the user wants stereo sound. Again, stereo
-sound takes more CPU to power to emulate compared to mono sound.
-
-The buffer_size value indicates what sample buffer size the user wants,
-usually zero, meaning you should pick the value best suited to the current
-playback rate. Sound data is normally passed to the sound hardware in
-blocks, the smaller the block the less latency between the SNES game playing
-a sound and it being heard by the user. But if you pick a too smaller value,
-and you're having to periodically poll the operating system to see if it can
-accept more sound data, then the sound output will break up because other
-actions such as rendering the SNES screen can prevent you from polling the
-hardware often enough and the operating system runs out of sound data to
-play.
-
-The MS-DOS port uses a buffer size of 128 samples since the sound card
-sends an interrupt when more data is required which is acted upon promptly,
-where as the Linux and Solaris ports use a buffer size of 512 samples or
-more depending on the playback rate. Stereo and 16-bit sound both double the
-actual size of the buffer in bytes.
-
-uint32 S9xReadJoypad (int which1_0_to_4)
-****************************************
-
-This function is called to return a bit-wise mask of the state of one of the
-five emulated SNES controllers. Return 0 if you're not supporting controllers
-past a certain number or return the mask representing the current state of
-the controller number passed as a parameter or'ed with 0x80000000.
-
-Symbolic constants are defined in snes9x.h indicating the bit positions of
-the various SNES buttons and direction indicators; they're all in the form
-SNES_X_MASK where X is the SNES controller button name.
-
-The MS-DOS and X Window System ports record what keys are currently pressed
-and use that to build up a mask, the Windows port polls the operating system
-when S9xReadJoypad is called to find out what keys are pressed. All ports
-also implement host joysticks and joy-pads via this interface.
-
-bool8 S9xReadMousePosition (int which1_0_to_1, int &x, int &y, uint32 &buttons)
-*******************************************************************************
-
-Used by Snes9x to get the current position of the host pointing device,
-usually a mouse, used to emulated the SNES mouse. Snes9x converts the x and
-y values to delta values required by the SNES mouse, so the actual x and y
-values are unimportant, only the change in value since the last call to
-this function is used.
-
-Graphical windowing systems normally restrict the movement of the pointer on
-the screen, if you're porting to such an environment you might want to make
-a note of the change in position in the mouse since the last time you asked
-the operating system the mouse position, add this change in value to some
-saved x and y value, the reposition the pointer back to the centre of the
-SNES display window. The saved x and y values will be the values returned
-by this function.
-
-The buttons return value is a bit-wise mask of the two SNES mouse buttons,
-bit 0 for button 1 (left) and bit 1 for button 2 (right).
-
-bool8 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons)
-*****************************************************************
-
-void S9xSetPalette ()
-*********************
-
-void S9xSyncSpeed ()
-S9xUnixProcessSound
-void _makepath(char *, char const *, char const *, char const *, char const *)
-void _splitpath(char const *, char *, char *, char *, char *)
-
-
-Sound Generation
-----------------
-
-Settings
---------