mednafen/include/blargg_source.h000664 001750 001750 00000004574 12733066400 020104 0ustar00sergiosergio000000 000000 // Included at the beginning of library source files, after all other #include lines #ifndef BLARGG_SOURCE_H #define BLARGG_SOURCE_H // If debugging is enabled, abort program if expr is false. Meant for checking // internal state and consistency. A failed assertion indicates a bug in the module. // void assert( bool expr ); #include // If debugging is enabled and expr is false, abort program. Meant for checking // caller-supplied parameters and operations that are outside the control of the // module. A failed requirement indicates a bug outside the module. // void require( bool expr ); #undef require #define require( expr ) assert( expr ) // Like printf() except output goes to debug log file. Might be defined to do // nothing (not even evaluate its arguments). // void dprintf( const char* format, ... ); inline void blargg_dprintf_( const char*, ... ) { } #undef dprintf #define dprintf (1) ? (void) 0 : blargg_dprintf_ // If enabled, evaluate expr and if false, make debug log entry with source file // and line. Meant for finding situations that should be examined further, but that // don't indicate a problem. In all cases, execution continues normally. #undef check #define check( expr ) ((void) 0) // If expr yields error string, return it from current function, otherwise continue. #undef RETURN_ERR #define RETURN_ERR( expr ) do { \ blargg_err_t blargg_return_err_ = (expr); \ if ( blargg_return_err_ ) return blargg_return_err_; \ } while ( 0 ) // If ptr is 0, return out of memory error string. #undef CHECK_ALLOC #define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 ) // Avoid any macros which evaluate their arguments multiple times #undef min #undef max // using const references generates crappy code, and I am currenly only using these // for built-in types, so they take arguments by value template inline T min( T x, T y ) { if ( x < y ) return x; return y; } template inline T max( T x, T y ) { if ( x < y ) return y; return x; } // TODO: good idea? bad idea? #undef byte #define byte byte_ typedef unsigned char byte; // deprecated #define BLARGG_CHECK_ALLOC CHECK_ALLOC #define BLARGG_RETURN_ERR RETURN_ERR // BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check #ifdef BLARGG_SOURCE_BEGIN #include BLARGG_SOURCE_BEGIN #endif #endif mednafen/mednafen.h000664 001750 001750 00000001651 12733066400 015411 0ustar00sergiosergio000000 000000 #ifndef _MEDNAFEN_H #define _MEDNAFEN_H #include "mednafen-types.h" #include #include #include #define _(String) (String) #include "math_ops.h" #include "git.h" #ifdef _WIN32 #define strcasecmp _stricmp #endif #define GET_FDATA(fp) (fp.f_data) #define GET_FSIZE(fp) (fp.f_size) #define GET_FEXTS(fp) (fp.f_ext) #define GET_FDATA_PTR(fp) (fp->f_data) #define GET_FSIZE_PTR(fp) (fp->f_size) #define GET_FEXTS_PTR(fp) (fp->f_ext) #define gzopen(a, b) fopen(a, b) #define gzread(a, b, c) fread(b, c, 1, a) #define gzclose(a) fclose(a) #define gzgetc(a) fgetc(a) #define gzseek(a,b,c) fseek(a,b,c) extern MDFNGI *MDFNGameInfo; #include "settings.h" void MDFN_LoadGameCheats(void *override); void MDFN_FlushGameCheats(int nosave); void MDFN_MidSync(EmulateSpecStruct *espec); void MDFN_MidLineUpdate(EmulateSpecStruct *espec, int y); #include "mednafen-driver.h" #include "mednafen-endian.h" #endif libretro-common/include/compat/msvc.h000664 001750 001750 00000006467 12733066400 021057 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (msvc_compat.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_COMPAT_MSVC_H #define __LIBRETRO_SDK_COMPAT_MSVC_H #ifdef _MSC_VER #ifdef __cplusplus extern "C" { #endif /* Pre-MSVC 2015 compilers don't implement snprintf in a cross-platform manner. */ #if _MSC_VER < 1900 #include #include #define snprintf c99_snprintf #define vsnprintf c99_vsnprintf _inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int count = -1; if (size != 0) count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap); if (count == -1) count = _vscprintf(format, ap); return count; } _inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...) { int count; va_list ap; va_start(ap, format); count = c99_vsnprintf(outBuf, size, format, ap); va_end(ap); return count; } #endif #ifdef __cplusplus } #endif #undef UNICODE /* Do not bother with UNICODE at this time. */ #include #include #include /* Python headers defines ssize_t and sets HAVE_SSIZE_T. * Cannot duplicate these efforts. */ #ifndef HAVE_SSIZE_T #if defined(_WIN64) typedef __int64 ssize_t; #elif defined(_WIN32) typedef int ssize_t; #endif #endif #define mkdir(dirname, unused) _mkdir(dirname) #define strtoull _strtoui64 #undef strcasecmp #define strcasecmp _stricmp #undef strncasecmp #define strncasecmp _strnicmp /* Disable some of the annoying warnings. */ #pragma warning(disable : 4800) #pragma warning(disable : 4805) #pragma warning(disable : 4244) #pragma warning(disable : 4305) #pragma warning(disable : 4146) #pragma warning(disable : 4267) #pragma warning(disable : 4723) #pragma warning(disable : 4996) /* roundf is available since MSVC 2013 */ #if _MSC_VER < 1800 #define roundf(in) (in >= 0.0f ? floorf(in + 0.5f) : ceilf(in - 0.5f)) #endif #ifndef PATH_MAX #define PATH_MAX _MAX_PATH #endif #ifndef SIZE_MAX #define SIZE_MAX _UI32_MAX #endif #endif #endif mednafen/file.h000664 001750 001750 00000004374 12733066400 014560 0ustar00sergiosergio000000 000000 #ifndef MDFN_FILE_H #define MDFN_FILE_H #include #include #define MDFNFILE_EC_NOTFOUND 1 #define MDFNFILE_EC_OTHER 2 class MDFNFILE { public: MDFNFILE(); // WIP constructors: MDFNFILE(const char *path, const void *known_ext, const char *purpose = NULL); ~MDFNFILE(); bool Open(const char *path, const void *known_ext, const char *purpose = NULL, const bool suppress_notfound_pe = false); INLINE bool Open(const std::string &path, const void *known_ext, const char *purpose = NULL, const bool suppress_notfound_pe = false) { return(Open(path.c_str(), known_ext, purpose, suppress_notfound_pe)); } bool ApplyIPS(void*); bool Close(void); uint64 fread(void *ptr, size_t size, size_t nmemb); int fseek(int64 offset, int whence); inline uint64 ftell(void) { return(location); } inline void rewind(void) { location = 0; } int read32le(uint32 *Bufo); int read16le(uint16 *Bufo); inline int _fgetc(void) { if(location < f_size) return f_data[location++]; return EOF; } inline int fisarchive(void) { return(0); } uint8 *f_data; int64 f_size; char *f_ext; private: int64 location; bool MakeMemWrapAndClose(void *tz); }; class PtrLengthPair { public: inline PtrLengthPair(const void *new_data, const uint64 new_length) { data = new_data; length = new_length; } ~PtrLengthPair() { } INLINE const void *GetData(void) const { return(data); } INLINE uint64 GetLength(void) const { return(length); } private: const void *data; uint64 length; }; #include // These functions should be used for data like save states and non-volatile backup memory. // Until(if, even) we add LoadFromFile functions, for reading the files these functions generate, just use gzopen(), gzread(), etc. // "compress" is set to the zlib compression level. 0 disables compression entirely, and dumps the file without a gzip header or footer. // (Note: There is a setting that will force compress to 0 in the internal DumpToFile logic, for hackers who don't want to ungzip save files.) bool MDFN_DumpToFile(const char *filename, int compress, const void *data, const uint64 length); bool MDFN_DumpToFile(const char *filename, int compress, const std::vector &pearpairs); #endif mednafen/git.h000664 001750 001750 00000034045 12733066400 014422 0ustar00sergiosergio000000 000000 #ifndef _GIT_H #define _GIT_H #include #include "video.h" typedef struct { const char *extension; // Example ".nes" const char *description; // Example "iNES Format ROM Image" } FileExtensionSpecStruct; #include "file.h" enum { MDFN_ROTATE0 = 0, MDFN_ROTATE90, MDFN_ROTATE180, MDFN_ROTATE270 }; typedef enum { VIDSYS_NONE, // Can be used internally in system emulation code, but it is an error condition to let it continue to be // after the Load() or LoadCD() function returns! VIDSYS_PAL, VIDSYS_PAL_M, // Same timing as NTSC, but uses PAL-style colour encoding VIDSYS_NTSC, VIDSYS_SECAM } VideoSystems; typedef enum { GMT_CART, // Self-explanatory! GMT_ARCADE, // VS Unisystem, PC-10... GMT_DISK, // Famicom Disk System, mostly GMT_CDROM, // PC Engine CD, PC-FX GMT_PLAYER // Music player(NSF, HES, GSF) } GameMediumTypes; #include "state.h" #include "settings-common.h" typedef enum { IDIT_BUTTON, // 1-bit IDIT_BUTTON_CAN_RAPID, // 1-bit IDIT_BUTTON_BYTE, // 8-bits, Button as a byte instead of a bit. IDIT_X_AXIS, // (mouse) 32-bits, signed, fixed-point: 1.15.16 - in-screen/window range: [0.0, nominal_width) IDIT_Y_AXIS, // (mouse) 32-bits, signed, fixed-point: 1.15.16 - in-screen/window range: [0.0, nominal_height) IDIT_X_AXIS_REL, // (mouse) 32-bits, signed IDIT_Y_AXIS_REL, // (mouse) 32-bits, signed IDIT_BYTE_SPECIAL, IDIT_BUTTON_ANALOG, // 32-bits, 0 - 32767 IDIT_RUMBLE, // 32-bits, lower 8 bits are weak rumble(0-255), next 8 bits are strong rumble(0-255), 0=no rumble, 255=max rumble. Somewhat subjective, too... // May extend to 16-bit each in the future. // It's also rather a special case of game module->driver code communication. } InputDeviceInputType; typedef struct { const char *SettingName; // No spaces, shouldbe all a-z0-9 and _. Definitely no ~! const char *Name; /*const InputDeviceInputVB VirtButton;*/ const int ConfigOrder; // Configuration order during in-game config process, -1 for no config. const InputDeviceInputType Type; const char *ExcludeName; // SettingName of a button that can't be pressed at the same time as this button // due to physical limitations. const char *RotateName[3]; // 90, 180, 270 //const char *Rotate180Name; //const char *Rotate270Name; } InputDeviceInputInfoStruct; typedef struct { const char *ShortName; const char *FullName; const char *Description; //struct InputPortInfoStruct *PortExpanderDeviceInfo; const void *PortExpanderDeviceInfo; // DON'T USE, IT'S NOT IMPLEMENTED PROPERLY CURRENTLY. int NumInputs; // Usually just the number of buttons....OR if PortExpanderDeviceInfo is non-NULL, it's the number of input // ports this port expander device provides. const InputDeviceInputInfoStruct *IDII; } InputDeviceInfoStruct; typedef struct { const char *ShortName; const char *FullName; int NumTypes; // Number of unique input devices available for this input port InputDeviceInfoStruct *DeviceInfo; const char *DefaultDevice; // Default device for this port. } InputPortInfoStruct; typedef struct { int InputPorts; const InputPortInfoStruct *Types; } InputInfoStruct; struct MemoryPatch; struct CheatFormatStruct { const char *FullName; //"Game Genie", "GameShark", "Pro Action Catplay", etc. const char *Description; // Whatever? bool (*DecodeCheat)(const std::string& cheat_string, MemoryPatch* patch); // *patch should be left as initialized by MemoryPatch::MemoryPatch(), unless this is the // second(or third or whatever) part of a multipart cheat. // // Will throw an std::exception(or derivative) on format error. // // Will return true if this is part of a multipart cheat. }; struct CheatFormatInfoStruct { unsigned NumFormats; CheatFormatStruct *Formats; }; // Miscellaneous system/simple commands(power, reset, dip switch toggles, coin insert, etc.) // (for DoSimpleCommand() ) enum { MDFN_MSC_RESET = 0x01, MDFN_MSC_POWER = 0x02, MDFN_MSC_INSERT_COIN = 0x07, // If we ever support arcade systems, we'll abstract DIP switches differently...maybe. MDFN_MSC_TOGGLE_DIP0 = 0x10, MDFN_MSC_TOGGLE_DIP1, MDFN_MSC_TOGGLE_DIP2, MDFN_MSC_TOGGLE_DIP3, MDFN_MSC_TOGGLE_DIP4, MDFN_MSC_TOGGLE_DIP5, MDFN_MSC_TOGGLE_DIP6, MDFN_MSC_TOGGLE_DIP7, MDFN_MSC_TOGGLE_DIP8, MDFN_MSC_TOGGLE_DIP9, MDFN_MSC_TOGGLE_DIP10, MDFN_MSC_TOGGLE_DIP11, MDFN_MSC_TOGGLE_DIP12, MDFN_MSC_TOGGLE_DIP13, MDFN_MSC_TOGGLE_DIP14, MDFN_MSC_TOGGLE_DIP15, // n of DISKn translates to is emulation module specific. MDFN_MSC_INSERT_DISK0 = 0x20, MDFN_MSC_INSERT_DISK1, MDFN_MSC_INSERT_DISK2, MDFN_MSC_INSERT_DISK3, MDFN_MSC_INSERT_DISK4, MDFN_MSC_INSERT_DISK5, MDFN_MSC_INSERT_DISK6, MDFN_MSC_INSERT_DISK7, MDFN_MSC_INSERT_DISK8, MDFN_MSC_INSERT_DISK9, MDFN_MSC_INSERT_DISK10, MDFN_MSC_INSERT_DISK11, MDFN_MSC_INSERT_DISK12, MDFN_MSC_INSERT_DISK13, MDFN_MSC_INSERT_DISK14, MDFN_MSC_INSERT_DISK15, MDFN_MSC_INSERT_DISK = 0x30, MDFN_MSC_EJECT_DISK = 0x31, // This command should select the next disk or disk side in the set and use MDFN_DispMessage() to show which disk is selected. // (If it's only allowed while a disk is ejected, or not, is emulation module specific. MDFN_MSC_SELECT_DISK = 0x32, MDFN_MSC__LAST = 0x3F // WARNING: Increasing(or having the enum'd value of a command greater than this :b) this will necessitate a change to the netplay protocol. }; typedef struct { // Pitch(32-bit) must be equal to width and >= the "fb_width" specified in the MDFNGI struct for the emulated system. // Height must be >= to the "fb_height" specified in the MDFNGI struct for the emulated system. // The framebuffer pointed to by surface->pixels is written to by the system emulation code. MDFN_Surface *surface; // Will be set to TRUE if the video pixel format has changed since the last call to Emulate(), FALSE otherwise. // Will be set to TRUE on the first call to the Emulate() function/method bool VideoFormatChanged; // Set by the system emulation code every frame, to denote the horizontal and vertical offsets of the image, and the size // of the image. If the emulated system sets the elements of LineWidths, then the horizontal offset(x) and width(w) of this structure // are ignored while drawing the image. MDFN_Rect DisplayRect; // Pointer to an array of MDFN_Rect, number of elements = fb_height, set by the driver code. Individual MDFN_Rect structs written // to by system emulation code. If the emulated system doesn't support multiple screen widths per frame, or if you handle // such a situation by outputting at a constant width-per-frame that is the least-common-multiple of the screen widths, then // you can ignore this. If you do wish to use this, you must set all elements every frame. MDFN_Rect *LineWidths; // TODO bool *IsFMV; // Set(optionally) by emulation code. If InterlaceOn is true, then assume field height is 1/2 DisplayRect.h, and // only every other line in surface (with the start line defined by InterlacedField) has valid data // (it's up to internal Mednafen code to deinterlace it). bool InterlaceOn; bool InterlaceField; // Skip rendering this frame if true. Set by the driver code. int skip; // // If sound is disabled, the driver code must set SoundRate to false, SoundBuf to NULL, SoundBufMaxSize to 0. // Will be set to TRUE if the sound format(only rate for now, at least) has changed since the last call to Emulate(), FALSE otherwise. // Will be set to TRUE on the first call to the Emulate() function/method bool SoundFormatChanged; // Sound rate. Set by driver side. double SoundRate; // Pointer to sound buffer, set by the driver code, that the emulation code should render sound to. // Guaranteed to be at least 500ms in length, but emulation code really shouldn't exceed 40ms or so. Additionally, if emulation code // generates >= 100ms, // DEPRECATED: Emulation code may set this pointer to a sound buffer internal to the emulation module. int16 *SoundBuf; // Maximum size of the sound buffer, in frames. Set by the driver code. int32 SoundBufMaxSize; // Number of frames currently in internal sound buffer. Set by the system emulation code, to be read by the driver code. int32 SoundBufSize; int32 SoundBufSizeALMS; // SoundBufSize value at last MidSync(), 0 // if mid sync isn't implemented for the emulation module in use. // Number of cycles that this frame consumed, using MDFNGI::MasterClock as a time base. // Set by emulation code. int64 MasterCycles; int64 MasterCyclesALMS; // MasterCycles value at last MidSync(), 0 // if mid sync isn't implemented for the emulation module in use. // Current sound volume(0.000...<=volume<=1.000...). If, after calling Emulate(), it is still != 1, Mednafen will handle it internally. // Emulation modules can handle volume themselves if they like, for speed reasons. If they do, afterwards, they should set its value to 1. double SoundVolume; // Current sound speed multiplier. Set by the driver code. If, after calling Emulate(), it is still != 1, Mednafen will handle it internally // by resampling the audio. This means that emulation modules can handle(and set the value to 1 after handling it) it if they want to get the most // performance possible. HOWEVER, emulation modules must make sure the value is in a range(with minimum and maximum) that their code can handle // before they try to handle it. double soundmultiplier; // True if we want to rewind one frame. Set by the driver code. bool NeedRewind; // Sound reversal during state rewinding is normally done in mednafen.cpp, but // individual system emulation code can also do it if this is set, and clear it after it's done. // (Also, the driver code shouldn't touch this variable) bool NeedSoundReverse; } EmulateSpecStruct; typedef enum { MODPRIO_INTERNAL_EXTRA_LOW = 0, // For "cdplay" module, mostly. MODPRIO_INTERNAL_LOW = 10, MODPRIO_EXTERNAL_LOW = 20, MODPRIO_INTERNAL_HIGH = 30, MODPRIO_EXTERNAL_HIGH = 40 } ModPrio; class CDIF; typedef struct { /* Private functions to Mednafen. Do not call directly from the driver code, or else bad things shall happen. Maybe. Probably not, but don't do it(yet)! */ // Short system name, lowercase a-z, 0-9, and _ are the only allowable characters! const char *shortname; // Full system name. Preferably English letters, but can be UTF8 const char *fullname; // Pointer to an array of FileExtensionSpecStruct, with the last entry being { NULL, NULL } to terminate the list. // This list is used to make best-guess choices, when calling the TestMagic*() functions would be unreasonable, such // as when scanning a ZIP archive for a file to load. The list may also be used in the future for GUI file open windows. const FileExtensionSpecStruct *FileExtensions; ModPrio ModulePriority; void *Debugger; InputInfoStruct *InputInfo; // Returns 1 on successful load, 0 on fatal error(deprecated: -1 on unrecognized format) int (*Load)(const char *name, MDFNFILE *fp); // Return TRUE if the file is a recognized type, FALSE if not. bool (*TestMagic)(const char *name, MDFNFILE *fp); // // (*CDInterfaces).size() is guaranteed to be >= 1. int (*LoadCD)(std::vector *CDInterfaces); bool (*TestMagicCD)(std::vector *CDInterfaces); void (*CloseGame)(void); void (*SetLayerEnableMask)(uint64 mask); // Video const char *LayerNames; void (*SetChanEnableMask)(uint64 mask); // Audio(TODO, placeholder) const char *ChanNames; void (*InstallReadPatch)(uint32 address); void (*RemoveReadPatches)(void); uint8 (*MemRead)(uint32 addr); #ifdef WANT_NEW_API CheatFormatInfoStruct *CheatFormatInfo; #endif bool SaveStateAltersState; // true for bsnes and some libco-style emulators, false otherwise. // Main save state routine, called by the save state code in state.cpp. // When saving, load is set to 0. When loading, load is set to the version field of the save state being loaded. // data_only is true when the save state data is temporary, such as being saved into memory for state rewinding. int (*StateAction)(StateMem *sm, int load, int data_only); void (*Emulate)(EmulateSpecStruct *espec); void (*SetInput)(int port, const char *type, void *ptr); void (*DoSimpleCommand)(int cmd); const MDFNSetting *Settings; // Time base for EmulateSpecStruct::MasterCycles #define MDFN_MASTERCLOCK_FIXED(n) ((int64)((double)(n) * (1LL << 32))) int64 MasterClock; uint32 fps; // frames per second * 65536 * 256, truncated // multires is a hint that, if set, indicates that the system has fairly programmable video modes(particularly, the ability // to display multiple horizontal resolutions, such as the PCE, PC-FX, or Genesis). In practice, it will cause the driver // code to set the linear interpolation on by default. // // lcm_width and lcm_height are the least common multiples of all possible // resolutions in the frame buffer as specified by DisplayRect/LineWidths(Ex for PCE: widths of 256, 341.333333, 512, // lcm = 1024) // // nominal_width and nominal_height specify the resolution that Mednafen should display // the framebuffer image in at 1x scaling, scaled from the dimensions of DisplayRect, and optionally the LineWidths array // passed through espec to the Emulate() function. // bool multires; int lcm_width; int lcm_height; void *dummy_separator; // int nominal_width; int nominal_height; int fb_width; // Width of the framebuffer(not necessarily width of the image). MDFN_Surface width should be >= this. int fb_height; // Height of the framebuffer passed to the Emulate() function(not necessarily height of the image) int soundchan; // Number of output sound channels. int rotated; uint8 *name; /* Game name, UTF8 encoding */ int soundrate; /* For Ogg Vorbis expansion sound wacky support. 0 for default. */ VideoSystems VideoSystem; GameMediumTypes GameType; //int DiskLogicalCount; // A single double-sided disk would be 2 here. //const char *DiskNames; // Null-terminated. const char *cspecial; /* Special cart expansion: DIP switches, barcode reader, etc. */ std::vectorDesiredInput; // Desired input device for the input ports, NULL for don't care double mouse_sensitivity; } MDFNGI; #endif libretro-common/include/compat/000700 001750 001750 00000000000 12733077034 017712 5ustar00sergiosergio000000 000000 mednafen/wswan/eeprom.cpp000664 001750 001750 00000021262 12733066400 016615 0ustar00sergiosergio000000 000000 /* Cygne * * Copyright notice for this file: * Copyright (C) 2002 Dox dox@space.pl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "wswan.h" #include "eeprom.h" #include "wswan-memory.h" #include uint8_t wsEEPROM[2048]; static uint8_t iEEPROM[0x400]; static const uint8_t iEEPROM_Init[0x400] = { 255,255,255,255,255,255,192,255,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,127,0,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 0,252,255,1,255,253,255,253,255,253,255,253, 255,253,255,253,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 0,0,3,3,0,0,0,64,128,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 135,5,140,9,5,12,139,12,144,0,0,2, 0,76,165,0,128,0,0,0,255,127,255,127, 255,127,255,127,255,127,255,127,255,127,255,127, 255,127,255,127,255,127,255,127,255,127,255,127, 255,127,255,127,255,127,255,127,255,127,255,127, 255,127,255,127,255,127,255,127,255,127,255,127, 255,127,255,127,255,127,255,127,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 0,0,6,6,6,6,6,0,0,0,0,0, 1,128,15,0,1,1,1,15,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0, 'C'-54,'Y'-54,'G'-54,'N'-54,'E'-54,0,0,0,0,0,0,0,0,0,0, 0,32,1,1,33,1,4,0,1, 0,152,60,127,74,1,53,1,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255,255,255,255,255,255,255,255,255, 255,255,255,255 }; static uint8_t iEEPROM_Command, EEPROM_Command; static uint16_t iEEPROM_Address, EEPROM_Address; uint8_t WSwan_EEPROMRead(uint32_t A) { switch(A) { default: break; case 0xBA: return(iEEPROM[(iEEPROM_Address << 1) & 0x3FF]); case 0xBB: return(iEEPROM[((iEEPROM_Address << 1) | 1) & 0x3FF]); case 0xBC: return(iEEPROM_Address >> 0); case 0xBD: return(iEEPROM_Address >> 8); case 0xBE: if(iEEPROM_Command & 0x20) return iEEPROM_Command|2; if(iEEPROM_Command & 0x10) return iEEPROM_Command|1; return iEEPROM_Command | 3; case 0xC4: return(wsEEPROM[(EEPROM_Address << 1) & (eeprom_size - 1)]); case 0xC5: return(wsEEPROM[((EEPROM_Address << 1) | 1) & (eeprom_size - 1)]); case 0xC6: return(EEPROM_Address >> 0); case 0xC7: return(EEPROM_Address >> 8); case 0xC8: if(EEPROM_Command & 0x20) return EEPROM_Command|2; if(EEPROM_Command & 0x10) return EEPROM_Command|1; return EEPROM_Command | 3; } return 0; } void WSwan_EEPROMWrite(uint32_t A, uint8_t V) { switch(A) { case 0xBA: iEEPROM[(iEEPROM_Address << 1) & 0x3FF] = V; break; case 0xBB: iEEPROM[((iEEPROM_Address << 1) | 1) & 0x3FF] = V; break; case 0xBC: iEEPROM_Address &= 0xFF00; iEEPROM_Address |= (V << 0); break; case 0xBD: iEEPROM_Address &= 0x00FF; iEEPROM_Address |= (V << 8); break; case 0xBE: iEEPROM_Command = V; break; case 0xC4: wsEEPROM[(EEPROM_Address << 1) & (eeprom_size - 1)] = V; break; case 0xC5: wsEEPROM[((EEPROM_Address << 1) | 1) & (eeprom_size - 1)] = V; break; case 0xC6: EEPROM_Address &= 0xFF00; EEPROM_Address |= (V << 0); break; case 0xC7: EEPROM_Address &= 0x00FF; EEPROM_Address |= (V << 8); break; case 0xC8: EEPROM_Command = V; break; } } void WSwan_EEPROMReset(void) { iEEPROM_Command = EEPROM_Command = 0; iEEPROM_Address = EEPROM_Address = 0; } #define mBCD16(value) ( (((((value)%100) / 10) <<4)|((value)%10)) | ((((((value / 100)%100) / 10) <<4)|((value / 100)%10))<<8) ) #define INT16_TO_BCD(A) ((((((A) % 100) / 10) * 16 + ((A) % 10))) | (((((((A) / 100) % 100) / 10) * 16 + (((A) / 100) % 10))) << 8)) void WSwan_EEPROMInit(const char *Name, const uint16_t BYear, const uint8_t BMonth, const uint8_t BDay, const uint8_t Sex, const uint8_t Blood) { unsigned x; uint16_t bcd_BYear; memset(wsEEPROM, 0, 2048); memcpy(iEEPROM, iEEPROM_Init, 0x400); for(x = 0; x < 16; x++) { uint8_t zechar = 0; if(x < strlen(Name)) { char tc = toupper(Name[x]); if(tc == ' ') zechar = 0; else if(tc >= '0' && tc <= '9') zechar = tc - '0' + 0x1; else if(tc >= 'A' && tc <= 'Z') zechar = tc - 'A' + 0xB; else if(tc >= 'a' && tc <= 'z') zechar = tc - 'a' + 0xB + 26; } iEEPROM[0x360 + x] = zechar; } bcd_BYear = INT16_TO_BCD(BYear); iEEPROM[0x370] = (bcd_BYear >> 8) & 0xFF; iEEPROM[0x371] = (bcd_BYear >> 0) & 0xFF; iEEPROM[0x372] = mBCD(BMonth); iEEPROM[0x373] = mBCD(BDay); iEEPROM[0x374] = Sex; iEEPROM[0x375] = Blood; } int WSwan_EEPROMStateAction(StateMem *sm, int load, int data_only) { SFORMAT StateRegs[] = { SFVAR(iEEPROM_Command), SFVAR(iEEPROM_Address), SFVAR(EEPROM_Command), SFVAR(EEPROM_Address), SFARRAY(iEEPROM, sizeof(iEEPROM)), SFARRAYN(eeprom_size ? wsEEPROM : NULL, eeprom_size, "EEPROM"), SFEND }; if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, "EEPR")) return(0); return(1); } Makefile000664 001750 001750 00000021100 12733066400 013335 0ustar00sergiosergio000000 000000 DEBUG = 0 FRONTEND_SUPPORTS_RGB565 = 1 CORE_DIR := . ifneq ($(EMSCRIPTEN),) platform = emscripten endif ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) platform = win else ifneq ($(findstring MINGW,$(shell uname -a)),) platform = win else ifneq ($(findstring Darwin,$(shell uname -a)),) platform = osx else ifneq ($(findstring win,$(shell uname -a)),) platform = win endif endif # system platform system_platform = unix ifeq ($(shell uname -a),) EXE_EXT = .exe system_platform = win else ifneq ($(findstring Darwin,$(shell uname -a)),) system_platform = osx ifeq ($(shell uname -p),powerpc) arch = ppc else arch = intel endif else ifneq ($(findstring MINGW,$(shell uname -a)),) system_platform = win endif # If you have a system with 1GB RAM or more - cache the whole # CD for CD-based systems in order to prevent file access delays/hiccups CACHE_CD = 0 core = wswan NEED_BPP = 16 NEED_BLIP = 1 NEED_STEREO_SOUND = 1 WANT_NEW_API = 1 CORE_DEFINE := -DWANT_WSWAN_EMU TARGET_NAME := mednafen_wswan_libretro ifeq ($(platform), unix) TARGET := $(TARGET_NAME).so fpic := -fPIC SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T ifneq ($(shell uname -p | grep -E '((i.|x)86|amd64)'),) IS_X86 = 1 endif LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR else ifeq ($(platform), osx) TARGET := $(TARGET_NAME).dylib fpic := -fPIC SHARED := -dynamiclib LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR ifeq ($(arch),ppc) ENDIANNESS_DEFINES := -DMSB_FIRST -DBYTE_ORDER=BIG_ENDIAN OLD_GCC := 1 endif OSXVER = `sw_vers -productVersion | cut -d. -f 2` OSX_LT_MAVERICKS = `(( $(OSXVER) <= 9)) && echo "YES"` fpic += -mmacosx-version-min=10.1 # iOS else ifneq (,$(findstring ios,$(platform))) TARGET := $(TARGET_NAME)_ios.dylib fpic := -fPIC SHARED := -dynamiclib LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) ifeq ($(IOSSDK),) IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path) endif CC = cc -arch armv7 -isysroot $(IOSSDK) CXX = c++ -arch armv7 -isysroot $(IOSSDK) IPHONEMINVER := ifeq ($(platform),ios9) IPHONEMINVER = -miphoneos-version-min=8.0 else IPHONEMINVER = -miphoneos-version-min=5.0 endif LDFLAGS += $(IPHONEMINVER) FLAGS += $(IPHONEMINVER) CC += $(IPHONEMINVER) CXX += $(IPHONEMINVER) else ifeq ($(platform), qnx) TARGET := $(TARGET_NAME)_qnx.so fpic := -fPIC SHARED := -lcpp -lm -shared -Wl,--no-undefined -Wl,--version-script=link.T #LDFLAGS += $(PTHREAD_FLAGS) #FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR FLAGS += -DHAVE_MKDIR CC = qcc -Vgcc_ntoarmv7le CXX = QCC -Vgcc_ntoarmv7le_cpp AR = QCC -Vgcc_ntoarmv7le FLAGS += -D__BLACKBERRY_QNX__ -marm -mcpu=cortex-a9 -mfpu=neon -mfloat-abi=softfp else ifeq ($(platform), ps3) TARGET := $(TARGET_NAME)_ps3.a CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe ENDIANNESS_DEFINES := -DMSB_FIRST -DBYTE_ORDER=BIG_ENDIAN OLD_GCC := 1 FLAGS += -DHAVE_MKDIR -DARCH_POWERPC_ALTIVEC STATIC_LINKING = 1 else ifeq ($(platform), sncps3) TARGET := $(TARGET_NAME)_ps3.a CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe ENDIANNESS_DEFINES := -DMSB_FIRST -DBYTE_ORDER=BIG_ENDIAN CXXFLAGS += -Xc+=exceptions OLD_GCC := 1 NO_GCC := 1 FLAGS += -DHAVE_MKDIR -DARCH_POWERPC_ALTIVEC STATIC_LINKING = 1 else ifeq ($(platform), psl1ght) TARGET := $(TARGET_NAME)_psl1ght.a CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) CXX = $(PS3DEV)/ppu/bin/ppu-g++$(EXE_EXT) AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) ENDIANNESS_DEFINES := -DMSB_FIRST -DBYTE_ORDER=BIG_ENDIAN FLAGS += -DHAVE_MKDIR -DBYTE_ORDER=BIG_ENDIAN STATIC_LINKING = 1 # PSP else ifeq ($(platform), psp1) TARGET := $(TARGET_NAME)_psp1.a CC = psp-gcc$(EXE_EXT) CXX = psp-g++$(EXE_EXT) AR = psp-ar$(EXE_EXT) FLAGS += -DPSP -G0 FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 # Vita else ifeq ($(platform), vita) TARGET := $(TARGET_NAME)_vita.a CC = arm-vita-eabi-gcc$(EXE_EXT) CXX = arm-vita-eabi-g++$(EXE_EXT) AR = arm-vita-eabi-ar$(EXE_EXT) FLAGS += -DVITA -DHAVE_MKDIR STATIC_LINKING = 1 # CTR (3DS) else ifeq ($(platform), ctr) TARGET := $(TARGET_NAME)_ctr.a CC = $(DEVKITARM)/bin/arm-none-eabi-gcc$(EXE_EXT) CXX = $(DEVKITARM)/bin/arm-none-eabi-g++$(EXE_EXT) AR = $(DEVKITARM)/bin/arm-none-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES := -DLSB_FIRST FLAGS += -DARM11 -D_3DS FLAGS += -DHAVE_MKDIR FLAGS += -march=armv6k -mtune=mpcore -mfloat-abi=hard FLAGS += -mword-relocations FLAGS += -fomit-frame-pointer -fstrict-aliasing -ffast-math FLAGS += -fno-rtti FLAGS += -fno-exceptions -DDISABLE_EXCEPTIONS STATIC_LINKING = 1 IS_X86 := 0 else ifeq ($(platform), xenon) TARGET := $(TARGET_NAME)_xenon360.a CC = xenon-gcc$(EXE_EXT) CXX = xenon-g++$(EXE_EXT) AR = xenon-ar$(EXE_EXT) ENDIANNESS_DEFINES += -D__LIBXENON__ -m32 -D__ppc__ -DMSB_FIRST -DBYTE_ORDER=BIG_ENDIAN LIBS := $(PTHREAD_FLAGS) FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 else ifeq ($(platform), ngc) TARGET := $(TARGET_NAME)_ngc.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES += -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float -DMSB_FIRST -DBYTE_ORDER=BIG_ENDIAN EXTRA_INCLUDES := -I$(DEVKITPRO)/libogc/include FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 else ifeq ($(platform), wii) TARGET := $(TARGET_NAME)_wii.a CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) ENDIANNESS_DEFINES += -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float -DMSB_FIRST -DBYTE_ORDER=BIG_ENDIAN EXTRA_INCLUDES := -I$(DEVKITPRO)/libogc/include FLAGS += -DHAVE_MKDIR STATIC_LINKING = 1 else ifneq (,$(findstring armv,$(platform))) TARGET := $(TARGET_NAME).so fpic := -fPIC SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T CC = gcc LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR IS_X86 = 0 ifneq (,$(findstring cortexa8,$(platform))) FLAGS += -marm -mcpu=cortex-a8 ASFLAGS += -mcpu=cortex-a8 else ifneq (,$(findstring cortexa9,$(platform))) FLAGS += -marm -mcpu=cortex-a9 ASFLAGS += -mcpu=cortex-a9 endif FLAGS += -marm ifneq (,$(findstring neon,$(platform))) FLAGS += -mfpu=neon ASFLAGS += -mfpu=neon HAVE_NEON = 1 endif ifneq (,$(findstring softfloat,$(platform))) FLAGS += -mfloat-abi=softfp else ifneq (,$(findstring hardfloat,$(platform))) FLAGS += -mfloat-abi=hard endif FLAGS += -DARM else ifeq ($(platform), gcw0) TARGET := $(TARGET_NAME).so CC = /opt/gcw0-toolchain/usr/bin/mipsel-linux-gcc CXX = /opt/gcw0-toolchain/usr/bin/mipsel-linux-g++ AR = /opt/gcw0-toolchain/usr/bin/mipsel-linux-ar fpic := -fPIC SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T LDFLAGS += $(PTHREAD_FLAGS) FLAGS += $(PTHREAD_FLAGS) -DHAVE_MKDIR FLAGS += -ffast-math -march=mips32 -mtune=mips32r2 -mhard-float else TARGET := $(TARGET_NAME).dll CC = gcc CXX = g++ IS_X86 = 1 SHARED := -shared -Wl,--no-undefined -Wl,--version-script=link.T LDFLAGS += -static-libgcc -static-libstdc++ -lwinmm FLAGS += -DHAVE__MKDIR endif include Makefile.common WARNINGS := -Wall \ -Wno-sign-compare \ -Wno-unused-variable \ -Wno-unused-function \ -Wno-uninitialized \ $(NEW_GCC_WARNING_FLAGS) \ -Wno-strict-aliasing EXTRA_GCC_FLAGS := -funroll-loops ifeq ($(NO_GCC),1) EXTRA_GCC_FLAGS := WARNINGS := else EXTRA_GCC_FLAGS := -g endif OBJECTS := $(SOURCES_CXX:.cpp=.o) $(SOURCES_C:.c=.o) all: $(TARGET) ifeq ($(DEBUG),0) FLAGS += -O2 $(EXTRA_GCC_FLAGS) else FLAGS += -O0 endif LDFLAGS += $(fpic) $(SHARED) FLAGS += $(fpic) $(NEW_GCC_FLAGS) FLAGS += $(INCFLAGS) FLAGS += $(ENDIANNESS_DEFINES) -DSIZEOF_DOUBLE=8 $(WARNINGS) -DMEDNAFEN_VERSION=\"0.9.31\" -DPACKAGE=\"mednafen\" -DMEDNAFEN_VERSION_NUMERIC=931 -DPSS_STYLE=1 -DMPC_FIXED_POINT $(CORE_DEFINE) -DSTDC_HEADERS -D__STDC_LIMIT_MACROS -D__LIBRETRO__ -D_LOW_ACCURACY_ $(EXTRA_INCLUDES) $(SOUND_DEFINE) CXXFLAGS += $(FLAGS) CFLAGS += $(FLAGS) $(TARGET): $(OBJECTS) ifeq ($(STATIC_LINKING), 1) $(AR) rcs $@ $(OBJECTS) else $(CXX) -o $@ $^ $(LDFLAGS) endif %.o: %.cpp $(CXX) -c -o $@ $< $(CXXFLAGS) %.o: %.c $(CC) -c -o $@ $< $(CFLAGS) clean: rm -f $(TARGET) $(OBJECTS) .PHONY: clean mednafen/wswan/eeprom.h000664 001750 001750 00000000630 12733066400 016256 0ustar00sergiosergio000000 000000 #ifndef __WSWAN_EEPROM_H #define __WSWAN_EEPROM_H #include uint8_t WSwan_EEPROMRead(uint32_t A); void WSwan_EEPROMWrite(uint32_t A, uint8_t V); int WSwan_EEPROMStateAction(StateMem *sm, int load, int data_only); void WSwan_EEPROMReset(void); void WSwan_EEPROMInit(const char *Name, const uint16_t BYear, const uint8_t BMonth, const uint8_t BDay, const uint8_t Sex, const uint8_t Blood); #endif mednafen/wswan/v30mz-modrm.inc000664 001750 001750 00000004470 12733066400 017412 0ustar00sergiosergio000000 000000 static struct { struct { WREGS w[256]; BREGS b[256]; } reg; struct { WREGS w[256]; BREGS b[256]; } RM; } Mod_RM; #define RegWord(ModRM) I.regs.w[Mod_RM.reg.w[ModRM]] #define RegByte(ModRM) I.regs.b[Mod_RM.reg.b[ModRM]] #define GetRMWord(ModRM) \ ((ModRM) >= 0xc0 ? I.regs.w[Mod_RM.RM.w[ModRM]] : ( (*GetEA[ModRM])(), ReadWord( EA ) )) #define PutbackRMWord(ModRM,val) \ { \ if (ModRM >= 0xc0) I.regs.w[Mod_RM.RM.w[ModRM]]=val; \ else WriteWord(EA,val); \ } #define GetnextRMWord ReadWord((EA&0xf0000)|((EA+2)&0xffff)) #define PutRMWord(ModRM,val) \ { \ if (ModRM >= 0xc0) \ I.regs.w[Mod_RM.RM.w[ModRM]]=val; \ else { \ (*GetEA[ModRM])(); \ WriteWord( EA ,val); \ } \ } #define PutImmRMWord(ModRM) \ { \ uint16 val; \ if (ModRM >= 0xc0) \ FETCHuint16(I.regs.w[Mod_RM.RM.w[ModRM]]) \ else { \ (*GetEA[ModRM])(); \ FETCHuint16(val) \ WriteWord( EA , val); \ } \ } #define GetRMByte(ModRM) \ ((ModRM) >= 0xc0 ? I.regs.b[Mod_RM.RM.b[ModRM]] : ReadByte( (*GetEA[ModRM])() )) #define PutRMByte(ModRM,val) \ { \ if (ModRM >= 0xc0) \ I.regs.b[Mod_RM.RM.b[ModRM]]=val; \ else \ WriteByte( (*GetEA[ModRM])() ,val); \ } #define PutImmRMByte(ModRM) \ { \ if (ModRM >= 0xc0) \ I.regs.b[Mod_RM.RM.b[ModRM]]=FETCH; \ else { \ (*GetEA[ModRM])(); \ WriteByte( EA , FETCH ); \ } \ } #define PutbackRMByte(ModRM,val) \ { \ if (ModRM >= 0xc0) \ I.regs.b[Mod_RM.RM.b[ModRM]]=val; \ else \ WriteByte(EA,val); \ } #define DEF_br8 \ uint32 ModRM = FETCH,src,dst; \ src = RegByte(ModRM); \ dst = GetRMByte(ModRM) #define DEF_wr16 \ uint32 ModRM = FETCH,src,dst; \ src = RegWord(ModRM); \ dst = GetRMWord(ModRM) #define DEF_r8b \ uint32 ModRM = FETCH,src,dst; \ dst = RegByte(ModRM); \ src = GetRMByte(ModRM) #define DEF_r16w \ uint32 ModRM = FETCH,src,dst; \ dst = RegWord(ModRM); \ src = GetRMWord(ModRM) #define DEF_ald8 \ uint32 src = FETCH; \ uint32 dst = I.regs.b[AL] #define DEF_axd16 \ uint32 src = FETCH; \ uint32 dst = I.regs.w[AW]; \ src += (FETCH << 8) mednafen/include/blargg_common.h000664 001750 001750 00000011103 12733066400 020056 0ustar00sergiosergio000000 000000 // Sets up common environment for Shay Green's libraries. // To change configuration options, modify blargg_config.h, not this file. #ifndef BLARGG_COMMON_H #define BLARGG_COMMON_H #include #include #include #include #undef BLARGG_COMMON_H // allow blargg_config.h to #include blargg_common.h #include "blargg_config.h" #ifndef BLARGG_COMMON_H #define BLARGG_COMMON_H // STATIC_CAST(T,expr): Used in place of static_cast (expr) #ifndef STATIC_CAST #define STATIC_CAST(T,expr) ((T) (expr)) #endif // blargg_err_t (0 on success, otherwise error string) #ifndef blargg_err_t typedef const char* blargg_err_t; #endif // blargg_vector - very lightweight vector of POD types (no constructor/destructor) template class blargg_vector { T* begin_; size_t size_; public: blargg_vector() : begin_( 0 ), size_( 0 ) { } ~blargg_vector() { free( begin_ ); } size_t size() const { return size_; } T* begin() const { return begin_; } T* end() const { return begin_ + size_; } blargg_err_t resize( size_t n ) { void* p = realloc( begin_, n * sizeof (T) ); if ( !p && n ) return "Out of memory"; begin_ = (T*) p; size_ = n; return 0; } void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); } T& operator [] ( size_t n ) const { assert( n <= size_ ); // <= to allow past-the-end value return begin_ [n]; } }; #ifndef BLARGG_DISABLE_NOTHROW #if __cplusplus < 199711 #define BLARGG_THROWS( spec ) #else #define BLARGG_THROWS( spec ) throw spec #endif #define BLARGG_DISABLE_NOTHROW \ void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\ void operator delete ( void* p ) { free( p ); } #define BLARGG_NEW new #else #include #define BLARGG_NEW new (std::nothrow) #endif #define BLARGG_4CHAR( a, b, c, d ) \ ((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF)) // BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. #ifndef BOOST_STATIC_ASSERT #ifdef _MSC_VER // MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified #define BOOST_STATIC_ASSERT( expr ) \ void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) #else // Some other compilers fail when declaring same function multiple times in class, // so differentiate them by line #define BOOST_STATIC_ASSERT( expr ) \ void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) #endif #endif // BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1, // compiler is assumed to support bool. If undefined, availability is determined. #ifndef BLARGG_COMPILER_HAS_BOOL #if defined (__MWERKS__) #if !__option(bool) #define BLARGG_COMPILER_HAS_BOOL 0 #endif #elif defined (_MSC_VER) #if _MSC_VER < 1100 #define BLARGG_COMPILER_HAS_BOOL 0 #endif #elif defined (__GNUC__) // supports bool #elif __cplusplus < 199711 #define BLARGG_COMPILER_HAS_BOOL 0 #endif #endif #if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL // If you get errors here, modify your blargg_config.h file typedef int bool; const bool true = 1; const bool false = 0; #endif // blargg_long/blargg_ulong = at least 32 bits, int if it's big enough #include #if INT_MAX >= 0x7FFFFFFF typedef int blargg_long; #else typedef long blargg_long; #endif #if UINT_MAX >= 0xFFFFFFFF typedef unsigned blargg_ulong; #else typedef unsigned long blargg_ulong; #endif // BOOST::int8_t etc. // HAVE_STDINT_H: If defined, use for int8_t etc. #if defined (HAVE_STDINT_H) #include #define BOOST // HAVE_INTTYPES_H: If defined, use for int8_t etc. #elif defined (HAVE_INTTYPES_H) #include #define BOOST #else struct BOOST { #if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F typedef signed char int8_t; typedef unsigned char uint8_t; #else // No suitable 8-bit type available typedef struct see_blargg_common_h int8_t; typedef struct see_blargg_common_h uint8_t; #endif #if USHRT_MAX == 0xFFFF typedef short int16_t; typedef unsigned short uint16_t; #else // No suitable 16-bit type available typedef struct see_blargg_common_h int16_t; typedef struct see_blargg_common_h uint16_t; #endif #if ULONG_MAX == 0xFFFFFFFF typedef long int32_t; typedef unsigned long uint32_t; #elif UINT_MAX == 0xFFFFFFFF typedef int int32_t; typedef unsigned int uint32_t; #else // No suitable 32-bit type available typedef struct see_blargg_common_h int32_t; typedef struct see_blargg_common_h uint32_t; #endif }; #endif #endif #endif libretro-common/include/compat/getopt.h000664 001750 001750 00000005233 12733066400 021377 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (compat_getopt.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __LIBRETRO_SDK_COMPAT_GETOPT_H #define __LIBRETRO_SDK_COMPAT_GETOPT_H #if defined(RARCH_INTERNAL) && defined(HAVE_CONFIG_H) #include "../../../config.h" #endif /* Custom implementation of the GNU getopt_long for portability. * Not designed to be fully compatible, but compatible with * the features RetroArch uses. */ #ifdef HAVE_GETOPT_LONG #include #else /* Avoid possible naming collisions during link since we * prefer to use the actual name. */ #define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_retro(argc, argv, optstring, longopts, longindex) #ifdef __cplusplus extern "C" { #endif struct option { const char *name; int has_arg; int *flag; int val; }; /* argv[] is declared with char * const argv[] in GNU, * but this makes no sense, as non-POSIX getopt_long * mutates argv (non-opts are moved to the end). */ int getopt_long(int argc, char *argv[], const char *optstring, const struct option *longopts, int *longindex); extern char *optarg; extern int optind, opterr, optopt; #ifdef __cplusplus } #endif /* If these are variously #defined, then we have bigger problems */ #ifndef no_argument #define no_argument 0 #define required_argument 1 #define optional_argument 2 #endif /* HAVE_GETOPT_LONG */ #endif /* pragma once */ #endif mednafen/wswan/wswan.h000664 001750 001750 00000000631 12733066400 016127 0ustar00sergiosergio000000 000000 #ifndef __WSWAN_H #define __WSWAN_H #include "../mednafen.h" #include "../state.h" #include "../general.h" #include "interrupt.h" #define mBCD(value) (((value)/10)<<4)|((value)%10) extern uint32 rom_size; extern int wsc; enum { WSWAN_SEX_MALE = 1, WSWAN_SEX_FEMALE = 2 }; enum { WSWAN_BLOOD_A = 1, WSWAN_BLOOD_B = 2, WSWAN_BLOOD_O = 3, WSWAN_BLOOD_AB = 4 }; #endif mednafen/wswan/start.inc000664 001750 001750 00000006353 12733066400 016456 0ustar00sergiosergio000000 000000 /* =================================================================================== Cygne WIN v 2.1a (c) Dox 2002 dox@space.pl =================================================================================== NEC cpu core by Bryan McPhail,Oliver Bergmann, Fabrice Frances and David Hedley Zlib by Jean-loup Gailly and Mark Adler =================================================================================== */ const uint8 startio[256]={ 0x00,//0 0x00,//1 0x9d,//2 0xbb,//3 0x00,//4 0x00,//5 0x00,//6 0x26,//7 0xfe,//8 0xde,//9 0xf9,//a 0xfb,//b 0xdb,//c 0xd7,//d 0x7f,//e 0xf5,//f 0x00,//10 0x00,//11 0x00,//12 0x00,//13 0x01,//14 0x00,//15 0x9e,//16 0x9b,//17 0x00,//18 0x00,//19 0x00,//1a 0x00,//1b 0x99,//1c 0xfd,//1d 0xb7,//1e 0xdf,//1f 0x30,//20 0x57,//21 0x75,//22 0x76,//23 0x15,//24 0x73,//25 0x77,//26 0x77,//27 0x20,//28 0x75,//29 0x50,//2a 0x36,//2b 0x70,//2c 0x67,//2d 0x50,//2e 0x77,//2f 0x57,//30 0x54,//31 0x75,//32 0x77,//33 0x75,//34 0x17,//35 0x37,//36 0x73,//37 0x50,//38 0x57,//39 0x60,//3a 0x77,//3b 0x70,//3c 0x77,//3d 0x10,//3e 0x73,//3f 0x00,//40 0x00,//41 0x00,//42 0x00,//43 0x00,//44 0x00,//45 0x00,//46 0x00,//47 0x00,//48 0x00,//49 0x00,//4a 0x00,//4b 0x00,//4c 0x00,//4d 0x00,//4e 0x00,//4f 0x00,//50 0x00,//51 0x00,//52 0x00,//53 0x00,//54 0x00,//55 0x00,//56 0x00,//57 0x00,//58 0x00,//59 0x00,//5a 0x00,//5b 0x00,//5c 0x00,//5d 0x00,//5e 0x00,//5f 0x0a,//60 0x00,//61 0x00,//62 0x00,//63 0x00,//64 0x00,//65 0x00,//66 0x00,//67 0x00,//68 0x00,//69 0x00,//6a 0x0f,//6b 0x00,//6c 0x00,//6d 0x00,//6e 0x00,//6f 0x00,//70 0x00,//71 0x00,//72 0x00,//73 0x00,//74 0x00,//75 0x00,//76 0x00,//77 0x00,//78 0x00,//79 0x00,//7a 0x00,//7b 0x00,//7c 0x00,//7d 0x00,//7e 0x00,//7f 0x00,//80 0x00,//81 0x00,//82 0x00,//83 0x00,//84 0x00,//85 0x00,//86 0x00,//87 0x00,//88 0x00,//89 0x00,//8a 0x00,//8b 0x00,//8c 0x1f,//8d 1d ? 0x00,//8e 0x00,//8f 0x00,//90 0x00,//91 0x00,//92 0x00,//93 0x00,//94 0x00,//95 0x00,//96 0x00,//97 0x00,//98 0x00,//99 0x00,//9a 0x00,//9b 0x00,//9c 0x00,//9d 0x03,//9e 0x00,//9f 0x87-2,//a0 0x00,//a1 0x00,//a2 0x00,//a3 0x0,//a4 2b 0x0,//a5 7f 0x4f,//a6 0xff,//a7 cf ? 0x00,//a8 0x00,//a9 0x00,//aa 0x00,//ab 0x00,//ac 0x00,//ad 0x00,//ae 0x00,//af 0x00,//b0 0xdb,//b1 0x00,//b2 0x00,//b3 0x00,//b4 0x40,//b5 0x00,//b6 0x00,//b7 0x00,//b8 0x00,//b9 0x01,//ba 0x00,//bb 0x42,//bc 0x00,//bd 0x83,//be 0x00,//bf 0x2f,//c0 0x3f,//c1 0xff,//c2 0xff,//c3 0x00,//c4 0x00,//c5 0x00,//c6 0x00,//c7 0xd1,//c8? 0xd1,//c9 0xd1,//ca 0xd1,//cb 0xd1,//cc 0xd1,//cd 0xd1,//ce 0xd1,//cf 0xd1,//d0 0xd1,//d1 0xd1,//d2 0xd1,//d3 0xd1,//d4 0xd1,//d5 0xd1,//d6 0xd1,//d7 0xd1,//d8 0xd1,//d9 0xd1,//da 0xd1,//db 0xd1,//dc 0xd1,//dd 0xd1,//de 0xd1,//df 0xd1,//e0 0xd1,//e1 0xd1,//e2 0xd1,//e3 0xd1,//e4 0xd1,//e5 0xd1,//e6 0xd1,//e7 0xd1,//e8 0xd1,//e9 0xd1,//ea 0xd1,//eb 0xd1,//ec 0xd1,//ed 0xd1,//ee 0xd1,//ef 0xd1,//f0 0xd1,//f1 0xd1,//f2 0xd1,//f3 0xd1,//f4 0xd1,//f5 0xd1,//f6 0xd1,//f7 0xd1,//f8 0xd1,//f9 0xd1,//fa 0xd1,//fb 0xd1,//fc 0xd1,//fd 0xd1,//fe 0xd1};//ff mednafen/wswan/wstech24.txt000664 001750 001750 00000066524 12733066400 017040 0ustar00sergiosergio000000 000000 ___ ___ _ / | \ ___ __/ \__ ___ ___ /\__ \ / \ // __>\_ _// __|/ __\/ \ \_____/_\__ \ \_/ \___|\___/\_/\_/ \____/ 2.4 - 26.12.2003 1. ABOUT WStech doc v2.4 made by Judge and Dox Special thanks to -anonymous- contributor for some usefull info. For more info please visit http://www.pocketdomain.net Comments/updates/infos please send to dox@space.pl What's new in version 2.4: - corect info about Sprite Table, BG Map and FG Map locations (ports $04 and $07 - section 10) Special thanks to mika-n 2. CPU Bandai SPGY-1001 ASWAN 9850KK003 NEC V30 MZ - fast version of V30 with internal pipeline (16 bytes prefatch buffer) running at 3.072 MHz. V30 MZ is aprox 4 times faster than V30. The V30MZ performs pipeline processing internally, performing instruction fetch (prefetch), instruction decode, and instruction execution in parallel. For this reason, it is difficult to determine what part of the program is currently being executed by monitoring the output of the address bus for the instruction code fetch. If there are conditional branch instructions, even in case branching does not occur, the address of the branch destination is prefetched (only one time), so that further monitoring of the program is difficult. The V30MZ has 8 prefetch queues (16 bytes). There are a few other differences between V30MZ and V30 cpu (unsupported opcodes , different flag handling after mul/div). Timing: Hblank : 256 CPU cycles Vblank : 159 Hblank = 159*256/3072000 = 75.47Hz 3. MEMORY 20 bit addressing space = 1 Megabyte. Memory is splitted into 64KB blocks (segments/banks). Segments: 0 - RAM - 16 KB (WS) / 64 KB (WSC) internal RAM (see below) 1 - SRAM (cart) SRAM is BSI device BS62LV256TC - 256K(32Kx8) Static RAM - TSOP 0 - 70 c, 70 ns (http://www.bsi.com.tw/product/bs62lv256.pdf) 2 - ROM Bank (initial bank = last) 3 - ROM Bank (lnitial bank = last) 4 - ROM Bank (initial bank = last - 11) 5 - ROM Bank (initial bank = last - 10) 6 - ROM Bank (initial bank = last - 9) 7 - ROM Bank (initial bank = last - 8) 8 - ROM Bank (initial bank = last - 7) 9 - ROM Bank (initial bank = last - 6) A - ROM Bank (initial bank = last - 5) B - ROM Bank (initial bank = last - 4) C - ROM Bank (initial bank = last - 3) D - ROM Bank (initial bank = last - 2) E - ROM Bank (initial bank = last - 1) F - ROM Bank (initial bank = last) Segments 2-$F are switchable using ports : $C2 - Segment 2 (value written to port is ROM Bank number ($FF means last ROM bank (last 64 kbytes of ROM file) , $FE = last - 1 .. etc) $C3 - Segment 3 (same as above) $C0 - Segments 4-$F - bits 0,1,2 and 3 of port $C0 are bits 4,5,6 and 7 of ROM bank number in segments 4-$F . Bits 0-3 are taken form segment number ( for example , IO[$C0]=$4E -> segment 9 contains ROM bank $E9). RAM Map : $0000 - $1FFF WS/WSC $2000 - $3FFF 4 Col Tiles WS/WSC ------------- $4000 - $7FFF 16 Col Tiles Bank 0 WSC only $8000 - $BFFF 16 Col Tiles Bank 1 WSC only $C000 - $FDFF WSC only $FE00 - $FFFF Palettes (WSC) WSC only Some games required initialized (?) part of RAM, for example: $75AC = $41 = "A" $75AD = $5F = "_" $75AE = $43 = "C" $75AF = $31 = "1" $75B0 = $6E = "n" $75B1 = $5F = "_" $75B2 = $63 = "c" $75B3 = $31 = "1" 4. VIDEO Screen size - 224 x 144 pixels (28 x 18 tiles) Tile size - 8 x 8 dots , 16 bytes/tile (4 col modes) or 32 bytes/tile (16 col modes) Map size - 256 x 256 pixels (32 x 32 tiles) Layers - Two layers - Background and Foreground (top layer) Maps locations - Selectable using port $07 Tiles locations - Fixed, two banks - one at $4000 , second at $8000 Map format - Each position in the map is defined by one word: bits 0 - 8 - Tile number (0-511) bits 9 - 12 - Palette number (0-15) bit 13 - WS = unused / WSC = tile bank bit 14 - Horizontal flip bit 15 - Vertical flip Tile formats - Depends on video mode (port $60) Sprites - Max 128 sprites , limited to max 32 on scanline sprite format: byte 0,1 - bits 0 - 8 - Tile number (0-511) 9 - 11 - Palette number (0-7) + 8 -> (8-15) 12 - Sprite window clipping on/off 13 - Priority with respect to the layers 0 - appear between the 2 background and foreground layers 1 - appear on top of both layers 14 - Horizontal flip 15 - Vertical flip byte 2 - Y position on the screen byte 3 - X position on the screen Sprite table is buffered durning frame display. Probably up to scanline 140 (1238-144?) Colors - Wonderswan (Mono) is capable of showing 16 shades of gray(only 8 can be selected at any one time) These 8 shades form a pool from which the palette definition can select shades. There are 16 palettes. All 16 palettes are used by BG and FG layers , the last 8 are used also by sprites. Which 8 colors are used for palette generation is defined by ports 1C and 1E- port 1C defines palette colors 0 - 3, port 1E defines 4 - 7. Each palette selection is 4 bits in size: 1C : 11110000 1D : 33332222 1E : 55554444 1F : 77776666 (where color 15 is the darkest one) Ports 20 - 3E are used to define the palettes themselves. 20 : x111x000 - palette #0 21 : x333x222 In color video modes each color is defined using one word, where bits: 0 - 3 Blue 4 - 7 Green 8 - 11 Red 12 - 14 unused Color palettes are stored in the RAM (segment 0) , at address $FE00 Scrolling - Each of layers can be scrolled horizontal or vertical using ports $10 - $13 Transparency - Wonderswan - if bit 3 on palette number is set - color 0 of that palette is transparent Wonderswan color - color 0 of each palette is transparent Windows - There are two windows - rectangular areas for disabling /enabling FG layer (FG window) or sprites(Sprite window) 5. SOUND 4 Audio channels. Each channel can play short samples ( 4 bit , 16 bytes ( 32 sampels = 2 samples in byte (bits 0-3 and 4-7)) with selectable frequency = 3,072 *10e6 / ((2048 - N) x 32 ) Hz , where N = 11 bit value. Location of that samples is unknown. Volume of each audio channle is controlled by writing two 4 bit values ( for left/right output channel) into ports $88 - $8B. Master volume is controlled by port $91 (2 bit value = first 'used' bit in master volume output (11 bit wide) , D/A converter can read only 8 bits , starting from bit set in port $91 , for example if first 'used' bit is set to 2 , D/A using bits 2,3,4,5,6,7,8,9 for audio output) Additional (selectable) functions : - channel 2 - voice - can play 8 bit samples writing frequently data to ch2 volume I/O port - channel 3 - sweep - two parameters: - step = 2.667 x (N + 1) ms , where N = 5 bit value - value - signed byte (-128 - 127) - channel 4 - noise - 7 selectable noise generators (probably I/O port $8E) For detailed info please check ports $80 - $91 in section I/O Ports. There's also Audio DMA (please chec ports $4a - $52). Transfer rate is 12KHz (HBlank). I/O ports $4A-$4B and $4E-$4F are autupdated durning data transfer . 6. ROM HEADER Header taking last 10 bytes of each ROM file. Bytes : 0 - Developer ID 1 - Minimum support system 00 - WS Mono 01 - WS Color 2 - Cart ID number for developer defined at byte 0 3 - ?? 4 - ROM Size 01 - ? 02 - 4Mbit 03 - 8Mbit 04 - 16Mbit 05 - ? 06 - 32Mbit 07 - ? 08 - 64Mbit 09 - 128Mbit 5 - SRAM/EEPROM Size 00 - 0k 01 - 64k SRAM 02 - 256k SRAM 03 - 1M SRAM (Taikyoku Igo Heisei Kiin) 04 - 2M SRAM (WonderWitch) 10 - 1k EEPROM 20 - 16k EEPROM 50 - 8k EEPROM 6 - Additional capabilities(?) - bit 0 - 1 - vertical position , 1 - horizontal position - bit 2 - always 1 7 - 1 - RTC (Real Time Clock) 8,9 - Checksum = sum of all ROM bytes except two last ones ( where checksum is stored) 7. INTERRUPTS The Wonderswan CPU recognizes 7 interrupts from the hardware, these are: 7 - HBlank Timer 6 - VBlank 5 - VBlank Timer 4 - Drawing line detection 3 - Serial Recieve 2 - RTC Alarm (cartridge) 1 - Key press 0 - Serial Send Whether the CPU should indeed take action when one of these interrupts come in is determined by port B2. The above mentioned interrupts correspond with the bit numbers of port B2. When an interrupt occurs the corresponding bit of port B6 gets set to 1 and, if enabled, an interrupt to the CPU is generated. This bit of port B6 will have to be cleared through code when the interrupt has been handled. Example: The Wonderswan is set to react to VBlank begin interrupts. Then bit 7 of B6 is set high and keeps the interrupt line high until the CPU is able to take action upon this interrupt. A typical VBlank interrupt routine is as follows: out B6,40 iret The mentioned interrupts do not correspond with the same interrupt numbers for the vectors in the vector table. The base for the actual interrupt numbers is set through port B0. If B0 is set to 20h then a VBlank begin interrupt routine must be set at vector 26h. (Base is 20h and VBlank begin interrupt is 6) 8. CONTROLS - It's easy to check buttons status reading/writing port $B5(see below). There's required some delay between writing and reading port $B5 ( few NOP-s) 9. Internal EEPROM Communication(?) and 'owner' info structure I/O Ports in range 0xBA -0xBE seems to be used for serial reading of internal WS EEPROM (for example - 'owner' info). 0xBA (Word) - Data 0xBC (Word) - Address (calculated probably Modulo EEPROM size (unknown)) 0xBE (Byte) - Communication (?) bit 4 set before reading data bit 1 set by hardware , when data is ready to read Example : mov ax, $1B9 out $BC, ax mov al, $10 out $BE, al xor dx, dx miniloop: inc dx cmp dl, 32 jnc bad_data in al, $BE and al, 1 jz miniloop in ax, $BA ; Month and Day of birth 'Owner' info structure : - Name - 16 bytes ( 0 = Space, 1 = '0' ... 0xA = '9', 0xB = 'A'... ) - Year of birth - 2 bytes (BCD) - Month of birth - 1 byte (BCD) - Day of birth - 1 byte (BCD) - Sex - 1 byte (1 - male , 2 - female) - Blood - 1 byte (1 - A, 2 - B, 3 - 0, 4 - AB) Struct size - 22 bytes = 11 reads, Address range = 0x1B0 - 0x1BA 10. I/O PORTS (port number /initial value / description) - $00 - $00 - Display control bit 0 - background layer on/off bit 1 - foreground layer on/off bit 2 - sprites on/off bit 3 - sprite window on/off (window coords defined in ports $0C - $0F) bit 4,5 - fg win inside on/off (window coords defined in ports $08 - $0B) Meaning of bits 4 and 5 : 5 4 --- 0 0 FG layer is displayed inside and outside FG window area 0 1 ?? 1 0 FG layer is displayed only inside window 1 1 FG layer is displayed outside window - $01 - $00 - Determines the background color bit 0-3 - background color bit 4-7 - background palette (WSC only) - $02 - ??? - Current Line (0 - 158) (159 ???) - $03 - $BB - Line compare (for drawning line detection interrupt) - $04 - $00 - Determines the base address for the sprite table. To get the address of the table, shift this value left 9 times and clear MSB. (bits 0..5 are effective to determines the base, bits 6,7 are unknown) 0 0xxxxxx0 00000000 (Sprite Attribute Table Base can move from $00000-$07E00 with 512 bytes step) - $05 - $00 - Determines the number of the sprite to start drawing with - $06 - $00 - Determines the number of the sprite to stop drawing. - $07 - $26 - Determines the location of the foreground and background screens in RAM. Format: bits 7-0 : ?fff?bbb bit 7 - Unknown bits 6-4 - Determines foreground location (address is 00fff000 00000000) bit 3-? - Unknown bits 2-0 - Determines background location (address is 00bbb000 00000000) Back Ground Tile Map Base can move from $00000-$03800 (2048 bytes step) - $08 - $FE - x0 of FG window (x0,y0) = top left corner, (x1,y1) = bottom right corner - $09 - $DE - y0 of FG window - $0A - $F9 - x1 of FG window - $0B - $FB - y1 of FG window - $0C - $DB - x0 of SPR window - $0D - $D7 - y0 of SPR window - $0E - $7F - x1 of SPR window - $0F - $F5 - y1 of SPR window - $10 - $00 - Background layer X scroll register - $11 - $00 - Background layer Y scroll register - $12 - $00 - Foreground layer X scroll register - $13 - $00 - Foreground layer Y scroll register - $14 - $01 - LCD Control (???) bit 0 - 1 - LCD on 0 - LCD off - $15 - $00 - LCD Icons bit 0 - LCD Sleep bit 1 - Vertical Position bit 2 - Horizontal Position bit 3 - Dot 1 bit 4 - Dot 2 bit 5 - Dot 3 bit 6 - Not Used ? bit 7 - Not Used ? - $16 - $9E - ??? - $17 - $9B - ??? - $18 - $00 - ??? - $19 - $00 - ??? - $1A - $00 - ??? - $1B - $00 - ??? - $1C - $99 - PALCOL10 - $1D - $FD - PALCOL32 - $1E - $B7 - PALCOL54 - $1F - $DF - PALCOL76 - $20 - $30 - PAL00 - $21 - $57 - PAL01 - $22 - $75 - PAL10 - $23 - $76 - PAL11 - $24 - $15 - PAL20 - $25 - $73 - PAL21 - $26 - $77 - PAL30 - $27 - $77 - PAL31 - $28 - $20 - PAL40 - $29 - $75 - PAL41 - $2A - $50 - PAL50 - $2B - $36 - PAL51 - $2C - $70 - PAL60 - $2D - $67 - PAL61 - $2E - $50 - PAL70 - $2F - $77 - PAL70 - $30 - $57 - PAL00 - $31 - $54 - PAL01 - $32 - $75 - PAL10 - $33 - $77 - PAL11 - $34 - $75 - PAL20 - $35 - $17 - PAL21 - $36 - $37 - PAL30 - $37 - $73 - PAL31 - $38 - $50 - PAL40 - $39 - $57 - PAL41 - $3A - $60 - PAL50 - $3B - $77 - PAL51 - $3C - $70 - PAL60 - $3D - $77 - PAL61 - $3E - $10 - PAL70 - $3F - $73 - PAL70 - $40 - $00 - DMA (?) copy source address - $41 - $00 - ^^^ - $42 - $00 - copy source bank - $43 - $00 - copy destination bank - $44 - $00 - copy destination address - $45 - $00 - ^^^ - $46 - $00 - size of copied data (in bytes) - $47 - $00 - ^^^ - $48 - $00 - bit 7 = 1 -> copy start (bit 7=0 when data transfer is finished) DMA(?) isn't immediate and not stopping the main cpu operations (like gbc GDMA) ports $40-$48 are updated durning copy process - $49 - $00 - ??? - $4A - $00 - sound DMA source address - $4B - $00 - ^^^ - $4C - $00 - DMA source memory segment bank - $4D - $00 - ??? - $4E - $00 - DMA transfer size (in bytes) - $4F - $00 - ^^^ - $50 - $00 - ??? - $51 - $00 - ??? - $52 - $00 - bit 7 = 1 -> DMA start - $53 - $00 - ??? - $54 - $00 - ??? - $55 - $00 - ??? - $56 - $00 - ??? - $57 - $00 - ??? - $58 - $00 - ??? - $59 - $00 - ??? - $5A - $00 - ??? - $5B - $00 - ??? - $5C - $00 - ??? - $5D - $00 - ??? - $5E - $00 - ??? - $5F - $00 - ??? - $60 - $0A - video mode Meaning of bits 5-7: 765 --- 111 16 col/tile 'packed' mode - tiles like in Genesis, 16 col/tile 110 16 col/tile 'layered' mode - tiles like in GameGear, 16 col/tile 010 4 col/tile - the same as mono (below) but using color palettes, 4 cols/tile, one tile = 16 bytes, WSC only 000 4 col/tile mono - tiles like in GameBoy, [bit 7 = 16/4 color/tile , bit 6 - color/mono mode, bit 5 - 'packed' mode on/off] - $61 - $00 - ??? - $62 - $00 - ??? - $63 - $00 - ??? - $64 - $00 - ??? - $65 - $00 - ??? - $66 - $00 - ??? - $67 - $00 - ??? - $68 - $00 - ??? - $69 - $00 - ??? - $6A - $00 - ??? - $6B - $0F - ??? - $6C - $00 - ??? - $6D - $00 - ??? - $6E - $00 - ??? - $6F - $00 - ??? - $70 - $00 - ??? - $71 - $00 - ??? - $72 - $00 - ??? - $73 - $00 - ??? - $74 - $00 - ??? - $75 - $00 - ??? - $76 - $00 - ??? - $77 - $00 - ??? - $78 - $00 - ??? - $79 - $00 - ??? - $7A - $00 - ??? - $7B - $00 - ??? - $7C - $00 - ??? - $7D - $00 - ??? - $7E - $00 - ??? - $7F - $00 - ??? - $80 - $00 - Audio 1 Freq - $81 - $00 - ^^^ - $82 - $00 - Audio 2 Freq - $83 - $00 - ^^^ - $84 - $00 - Audio 3 Freq - $85 - $00 - ^^^ - $86 - $00 - Audio 4 Freq - $87 - $00 - ^^^ - $88 - $00 - Audio 1 volume - $89 - $00 - Audio 2 volume - $8A - $00 - Audio 3 volume - $8B - $00 - Audio 4 volume - $8C - $00 - ?? Sweep value - $8D - $1F - ?? Sweep step - $8E - $00 - Noise control Bits : 0 - Noise generator type 1 - ^^^ 2 - ^^^ 3 - Reset 4 - Enable 5 - ??? 6 - ??? 7 - ??? - $8F - $00 - Sample location To get the address of samples, shift this value left 6 times. 0 00xxxxxx xx000000 - $90 - $00 - Audio control Bits: 0 - Audio 1 on/off 1 - Audio 2 on/off 2 - Audio 3 on/off 3 - Audio 4 on/off 4 - ??? 5 - Audio 2 Voice 6 - Audio 3 Sweep 7 - Audio 4 Noise - $91 - $00 - Audio Output Bits : 0 - Mono 1 - Output Volume 2 - ^^^ 3 - External Stereo 4 - ??? 5 - ??? 6 - ??? 7 - External Speaker (set by hardware) - $92 - $00 - Noise Counter Shift Register (15 bits) - $93 - $00 - ^^^ - $94 - $00 - Volume (4 bit) - $95 - $00 - ??? - $96 - $00 - ??? - $97 - $00 - ??? - $98 - $00 - ??? - $99 - $00 - ??? - $9A - $00 - ??? - $9B - $00 - ??? - $9C - $00 - ??? - $9D - $00 - ??? - $9E - $03 - ??? - $9F - $00 - ??? - $A0 - $87 - Hardware type bit 1 - 1 - color 0 - mono - $A1 - $00 - ??? - $A2 - $0C - Timer Control bit 0 - Hblank Timer on/off bit 1 - Hblank Timer Mode 0 - One Shot 1 - Auto Preset bit 2 - Vblank Timer(1/75s) on/off bit 3 - Vblank Timer Mode 0 - One Shot 1 - Auto Preset - $A3 - $00 - ??? - $A4 - $00 - Hblank Timer 'frequency' 0 = no HBLANK Interrupt n = HBLANK Interrupt every n lines (???) - $A5 - $00 - ^^^ - $A6 - $4F - Vblank Timer 'frequency' - $A7 - $FF - ^^^ - $A8 - $00 - Hblank Counter - 1/12000s - $A9 - $00 - Hblank Counter - 1/(12000>>8)s - $AA - $00 - Vblank Counter - 1/75s - $AB - $00 - Vblank Counter - 1/(75>>8)s - $AC - $00 - ??? - $AD - $00 - ??? - $AE - $00 - ??? - $AF - $00 - ??? - $B0 - $00 - Interrupt Base - $B1 - $DB - Communication byte - $B2 - $00 - Interrupt enable bit 7 - HBlank Timer bit 6 - VBlank begin bit 5 - VBlank Timer bit 4 - Drawing line detection bit 3 - Serial receive bit 2 - RTC Alarm bit 1 - Key press bit 0 - Serial transmit - $B3 - $00 - Communication direction bit 7 - Recieve data interrupt generation bit 6 - Connection Speed 0 - 9600 bps 1 - 38400 bps bit 5 - Send data interrupt generation bit 4 - ??? bit 3 - ??? bit 2 - Send Complete bit 1 - Error bit 0 - Recieve Complete write $00-$7f = read $00 write $80-$bf = read $84 write $c0-$cf = read $c4 - $B4 - $00 - ??? - $B5 - $40 - Controls bits 4-7 : read/write - Select line of inputs to read 0001 - read vertical cursors 0010 - read hozizontal cursors 0100 - read buttons bits 0-3 : read only - Read the current state of the input lines (positive logic) after having written 10h,20h, or 40h. Meaning of the bits when reading cursors: bit 0 - cursor up bit 1 - cursor right bit 2 - cursor down bit 3 - cursor left Meaning of the bits when reading buttons: bit 0 - ??? bit 1 - START bit 2 - A bit 3 - B - $B6 - $00 - Interrupt Acknowledge bit 7 - HBlank Timer bit 6 - VBlank begin bit 5 - VBlank Timer bit 4 - Drawing line detection bit 3 - Serial receive bit 2 - RTC Alarm bit 1 - Key press bit 0 - Serial transmit - $B7 - $00 - ??? - $B8 - $00 - ??? - $B9 - $00 - ??? - $BA - $01 - Internal EEPROM (?) Data - $BB - $00 - ^^^ - $BC - $42 - Internal EEPROM (?) Address (calculated probably Modulo EEPROM (1kbit?) size (mirroring for read/write)) - $BD - $00 - ^^^ - $BE - $83 - Internal EEPROM (?) Command bit 7 - Initialize ? bit 6 - Protect ? bit 5 - Write bit 4 - Read bit 3 - ??? bit 2 - ??? bit 1 - Write Complete (Read only) bit 0 - Read Complete (Read only) - $BF - $00 - ??? - $C0 - $2F - ROM Bank Base Selector for segments 4-$F - $C1 - $3F - SRAM Bank selector (???) - $C2 - $FF - BNK2SLCT - ROM Bank selector for segment 2 - $C3 - $FF - BNK3SLCT - ROM Bank selector for segment 3 - $C4 - $00 - EEPROM Data - $C5 - $00 - ^^^ - $C6 - $00 - 1kbit EEPROM (16bit*64) : - bits 0-5 - address - bits 6-7 - command : 0 - Extended Comand Address bits 4-5 0 - Write Disable 1 - Write All 2 - Erase All 3 - Write Enable 1 - Write 2 - Read 3 - Erase - 16 kbit EEPROM (16bit*1024) - bits 0-7 - address (low) - $C7 - $00 - 1kbit EEPROM (16bit*64) : bit 0 - Start - 16 kbit EEPROM (16bit*1024) : - bits 0-1 - address (high) - bits 2-3 - command : 0 - Extended Comand Address bits 0-1 0 - Write Disable 1 - Write All 2 - Erase All 3 - Write Enable 1 - Write 2 - Read 3 - Erase - bit 4 - Start - $C8 - $D1 - EEPROM Command : bit 7 - Initialize ??? bit 6 - Protect ??? bit 5 - Write bit 4 - Read bit 3 - ??? bit 2 - ??? bit 1 - Write Complete (Read only) bit 0 - Read Complete (Read only) - $C9 - $D1 - ??? - $CA - $D1 - RTC Command Write : - $10 - Reset - $12 - ??? Alarm ??? - $13 - ??? - $14 - Set Time - $15 - Get Time Read: - bit 7 - Ack [HACK = 1] - $CB - $D1 - RTC Data Write : Sometimes $40 , and wait for bit 7 = 1 After Command ($CA): - $14 - 7 writes (all BCD): - Year ( + 2000) - Month - Day - Day Of Week - Hour - Min - Sec Read After Command ($CA) : - $13 - bit 7 - Ack [HACK = 1] - $15 - 7 reads (all BCD) - Year ( + 2000) - Month - Day - Day Of Week - Hour - Min - Sec - $CC - $D1 - ??? - $CD - $D1 - ??? - $CE - $D1 - ??? - $CF - $D1 - ??? - $D0 - $D1 - ??? - $D1 - $D1 - ??? - $D2 - $D1 - ??? - $D3 - $D1 - ??? - $D4 - $D1 - ??? - $D5 - $D1 - ??? - $D6 - $D1 - ??? - $D7 - $D1 - ??? - $D8 - $D1 - ??? - $D9 - $D1 - ??? - $DA - $D1 - ??? - $DB - $D1 - ??? - $DC - $D1 - ??? - $DD - $D1 - ??? - $DE - $D1 - ??? - $DF - $D1 - ??? - $E0 - $D1 - ??? - $E1 - $D1 - ??? - $E2 - $D1 - ??? - $E3 - $D1 - ??? - $E4 - $D1 - ??? - $E5 - $D1 - ??? - $E6 - $D1 - ??? - $E7 - $D1 - ??? - $E8 - $D1 - ??? - $E9 - $D1 - ??? - $EA - $D1 - ??? - $EB - $D1 - ??? - $EC - $D1 - ??? - $ED - $D1 - ??? - $EE - $D1 - ??? - $EF - $D1 - ??? - $F0 - $D1 - ??? - $F1 - $D1 - ??? - $F2 - $D1 - ??? - $F3 - $D1 - ??? - $F4 - $D1 - ??? - $F5 - $D1 - ??? - $F6 - $D1 - ??? - $F7 - $D1 - ??? - $F8 - $D1 - ??? - $F9 - $D1 - ??? - $FA - $D1 - ??? - $FB - $D1 - ??? - $FC - $D1 - ??? - $FD - $D1 - ??? - $FE - $D1 - ??? - $FF - $D1 - ??? scrc32.c000664 001750 001750 00000007776 12733066400 013167 0ustar00sergiosergio000000 000000 #ifdef __cplusplus extern "C" { #endif #ifdef WANT_CRC32 static const unsigned long crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; #define DO1_CRC32(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); #define DO2_CRC32(buf) DO1_CRC32(buf); DO1_CRC32(buf); #define DO4_CRC32(buf) DO2_CRC32(buf); DO2_CRC32(buf); #define DO8_CRC32(buf) DO4_CRC32(buf); DO4_CRC32(buf); unsigned long crc32(unsigned long crc, const unsigned char *buf, unsigned int len) { if (buf == 0) return 0L; crc = crc ^ 0xffffffffL; while (len >= 8) { DO8_CRC32(buf); len -= 8; } if (len) do { DO1_CRC32(buf); } while (--len); return crc ^ 0xffffffffL; } #endif #ifdef __cplusplus } #endif mednafen/wswan/gfx.cpp000664 001750 001750 00000044304 12733066400 016114 0ustar00sergiosergio000000 000000 /* Cygne * * Copyright notice for this file: * Copyright (C) 2002 Dox dox@space.pl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "wswan.h" #include "gfx.h" #include "wswan-memory.h" #include "v30mz.h" #include "rtc.h" #include "../video.h" static uint32 wsMonoPal[16][4]; static uint32 wsColors[8]; static uint32 wsCols[16][16]; static uint16 ColorMapG[16]; static uint16 ColorMap[4096]; static uint32 LayerEnabled; static uint8 wsLine; /*current scanline*/ static uint8 SpriteTable[0x80][4]; static uint32 SpriteCountCache; static uint8 DispControl; static uint8 BGColor; static uint8 LineCompare; static uint8 SPRBase; static uint8 SpriteStart, SpriteCount; static uint8 FGBGLoc; static uint8 FGx0, FGy0, FGx1, FGy1; static uint8 SPRx0, SPRy0, SPRx1, SPRy1; static uint8 BGXScroll, BGYScroll; static uint8 FGXScroll, FGYScroll; static uint8 LCDControl, LCDIcons; static uint8 BTimerControl; static uint16 HBTimerPeriod; static uint16 VBTimerPeriod; static uint16 HBCounter, VBCounter; static uint8 VideoMode; void WSwan_GfxInit(void) { LayerEnabled = 7; // BG, FG, sprites } void WSwan_GfxWSCPaletteRAMWrite(uint32 ws_offset, uint8 data) { ws_offset=(ws_offset&0xfffe)-0xfe00; wsCols[(ws_offset>>1)>>4][(ws_offset>>1)&15] = wsRAM[ws_offset+0xfe00] | ((wsRAM[ws_offset+0xfe01]&0x0f) << 8); } void WSwan_GfxWrite(uint32 A, uint8 V) { if(A >= 0x1C && A <= 0x1F) { wsColors[(A - 0x1C) * 2 + 0] = 0xF - (V & 0xf); wsColors[(A - 0x1C) * 2 + 1] = 0xF - (V >> 4); } else if(A >= 0x20 && A <= 0x3F) { wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) + 0] = V&7; wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) | 1] = (V>>4)&7; } else switch(A) { case 0x00: DispControl = V; break; case 0x01: BGColor = V; break; case 0x03: LineCompare = V; break; case 0x04: SPRBase = V & 0x3F; break; case 0x05: SpriteStart = V; break; case 0x06: SpriteCount = V; break; case 0x07: FGBGLoc = V; break; case 0x08: FGx0 = V; break; case 0x09: FGy0 = V; break; case 0x0A: FGx1 = V; break; case 0x0B: FGy1 = V; break; case 0x0C: SPRx0 = V; break; case 0x0D: SPRy0 = V; break; case 0x0E: SPRx1 = V; break; case 0x0F: SPRy1 = V; break; case 0x10: BGXScroll = V; break; case 0x11: BGYScroll = V; break; case 0x12: FGXScroll = V; break; case 0x13: FGYScroll = V; break; case 0x14: LCDControl = V; break; case 0x15: LCDIcons = V; break; case 0x60: VideoMode = V; wsSetVideo(V>>5, false); break; case 0xa2: if((V & 0x01) && !(BTimerControl & 0x01)) HBCounter = HBTimerPeriod; if((V & 0x04) && !(BTimerControl & 0x04)) VBCounter = VBTimerPeriod; BTimerControl = V; break; case 0xa4: HBTimerPeriod &= 0xFF00; HBTimerPeriod |= (V << 0); break; case 0xa5: HBTimerPeriod &= 0x00FF; HBTimerPeriod |= (V << 8); HBCounter = HBTimerPeriod; break; case 0xa6: VBTimerPeriod &= 0xFF00; VBTimerPeriod |= (V << 0); break; case 0xa7: VBTimerPeriod &= 0x00FF; VBTimerPeriod |= (V << 8); VBCounter = VBTimerPeriod; break; } } uint8 WSwan_GfxRead(uint32 A) { if(A >= 0x1C && A <= 0x1F) { uint8 ret = 0; ret |= 0xF - wsColors[(A - 0x1C) * 2 + 0]; ret |= (0xF - wsColors[(A - 0x1C) * 2 + 1]) << 4; return(ret); } else if(A >= 0x20 && A <= 0x3F) return wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) + 0] | (wsMonoPal[(A - 0x20) >> 1][((A & 0x1) << 1) | 1] << 4); else switch(A) { case 0x00: return(DispControl); case 0x01: return(BGColor); case 0x02: return(wsLine); case 0x03: return(LineCompare); case 0x04: return(SPRBase); case 0x05: return(SpriteStart); case 0x06: return(SpriteCount); case 0x07: return(FGBGLoc); case 0x08: return(FGx0); case 0x09: return(FGy0); case 0x0A: return(FGx1); case 0x0B: return(FGy1); case 0x0C: return(SPRx0); case 0x0D: return(SPRy0); case 0x0E: return(SPRx1); case 0x0F: return(SPRy1); case 0x10: return(BGXScroll); case 0x11: return(BGYScroll); case 0x12: return(FGXScroll); case 0x13: return(FGYScroll); case 0x14: return(LCDControl); case 0x15: return(LCDIcons); case 0x60: return(VideoMode); case 0xa0: return(wsc ? 0x87 : 0x86); case 0xa2: return(BTimerControl); case 0xa4: return((HBTimerPeriod >> 0) & 0xFF); case 0xa5: return((HBTimerPeriod >> 8) & 0xFF); case 0xa6: return((VBTimerPeriod >> 0) & 0xFF); case 0xa7: return((VBTimerPeriod >> 8) & 0xFF); case 0xa8: return((HBCounter >> 0) & 0xFF); case 0xa9: return((HBCounter >> 8) & 0xFF); case 0xaa: return((VBCounter >> 0) & 0xFF); case 0xab: return((VBCounter >> 8) & 0xFF); default: break; } return 0; } bool wsExecuteLine(MDFN_Surface *surface, bool skip) { bool ret = false; if(wsLine < 144) { if(!skip) wsScanline(surface->pixels + wsLine * surface->pitch); } WSwan_CheckSoundDMA(); // Update sprite data table if(wsLine == 142) { SpriteCountCache = SpriteCount; if(SpriteCountCache > 0x80) SpriteCountCache = 0x80; memcpy(SpriteTable, &wsRAM[(SPRBase << 9) + (SpriteStart << 2)], SpriteCountCache << 2); } if(wsLine == 144) { ret = true; WSwan_Interrupt(WSINT_VBLANK); //printf("VBlank: %d\n", wsLine); } if(HBCounter && (BTimerControl & 0x01)) { HBCounter--; if(!HBCounter) { // Loop mode? if(BTimerControl & 0x02) HBCounter = HBTimerPeriod; WSwan_Interrupt(WSINT_HBLANK_TIMER); } } v30mz_execute(224); wsLine = (wsLine + 1) % 159; if(wsLine == LineCompare) { WSwan_Interrupt(WSINT_LINE_HIT); //printf("Line hit: %d\n", wsLine); } v30mz_execute(32); WSwan_RTCClock(256); if(!wsLine) { if(VBCounter && (BTimerControl & 0x04)) { VBCounter--; if(!VBCounter) { if(BTimerControl & 0x08) // Loop mode? VBCounter = VBTimerPeriod; WSwan_Interrupt(WSINT_VBLANK_TIMER); } } wsLine = 0; } return(ret); } void WSwan_SetLayerEnableMask(uint64 mask) { LayerEnabled = mask; } void WSwan_SetPixelFormat(void) { unsigned r, g, b, i; for(r = 0; r < 16; r++) for(g = 0; g < 16; g++) for(b = 0; b < 16; b++) ColorMap[(r << 8) | (g << 4) | (b << 0)] = MAKECOLOR((r * 17), (g * 17), (b * 17), 0); //(neo_r << rs) | (neo_g << gs) | (neo_b << bs); for(i = 0; i < 16; i++) ColorMapG[i] = MAKECOLOR((i * 17), (i * 17), (i * 17), 0); //(neo_r << rs) | (neo_g << gs) | (neo_b << bs); } void wsScanline(uint16 *target) { uint32 start_tile_n,map_a,startindex,adrbuf,b1,b2,j,t,l; char ys2; uint8 b_bg[256]; uint8 b_bg_pal[256]; if(!wsVMode) memset(b_bg, wsColors[BGColor&0xF]&0xF, 256); else { memset(&b_bg[0], BGColor & 0xF, 256); memset(&b_bg_pal[0], (BGColor>>4) & 0xF, 256); } start_tile_n=(wsLine+BGYScroll)&0xff;/*First line*/ map_a=(((uint32)(FGBGLoc&0xF))<<11)+((start_tile_n&0xfff8)<<3); startindex = BGXScroll >> 3; /*First tile in row*/ adrbuf = 7-(BGXScroll&7); /*Pixel in tile*/ if((DispControl & 0x01) && (LayerEnabled & 0x01)) /*BG layer*/ { for(t=0;t<29;t++) { b1=wsRAM[map_a+(startindex<<1)]; b2=wsRAM[map_a+(startindex<<1)+1]; uint32 palette=(b2>>1)&15; b2=(b2<<8)|b1; wsGetTile(b2&0x1ff,start_tile_n&7,b2&0x8000,b2&0x4000,b2&0x2000); if(wsVMode) { if(wsVMode & 0x2) { for(int x = 0; x < 8; x++) if(wsTileRow[x]) { b_bg[adrbuf + x] = wsTileRow[x]; b_bg_pal[adrbuf + x] = palette; } } else { for(int x = 0; x < 8; x++) if(wsTileRow[x] || !(palette & 0x4)) { b_bg[adrbuf + x] = wsTileRow[x]; b_bg_pal[adrbuf + x] = palette; } } } else { for(int x = 0; x < 8; x++) if(wsTileRow[x] || !(palette & 4)) { b_bg[adrbuf + x] = wsColors[wsMonoPal[palette][wsTileRow[x]]]; } } adrbuf += 8; startindex=(startindex + 1)&31; } // end for(t = 0 ... } // End BG layer drawing if((DispControl & 0x02) && (LayerEnabled & 0x02))/*FG layer*/ { uint8 windowtype = DispControl&0x30; bool in_window[256 + 8*2]; if(windowtype) { memset(in_window, 0, sizeof(in_window)); if(windowtype == 0x20) // Display FG only inside window { if((wsLine >= FGy0) && (wsLine < FGy1)) for(j = FGx0; j <= FGx1 && j < 224; j++) in_window[7 + j] = 1; } else if(windowtype == 0x30) // Display FG only outside window { for(j = 0; j < 224; j++) { if(!(j >= FGx0 && j < FGx1) || !((wsLine >= FGy0) && (wsLine < FGy1))) in_window[7 + j] = 1; } } else { puts("Who knows!"); } } else memset(in_window, 1, sizeof(in_window)); start_tile_n=(wsLine+FGYScroll)&0xff; map_a=(((uint32)((FGBGLoc>>4)&0xF))<<11)+((start_tile_n>>3)<<6); startindex = FGXScroll >> 3; adrbuf = 7-(FGXScroll&7); for(t=0; t<29; t++) { b1=wsRAM[map_a+(startindex<<1)]; b2=wsRAM[map_a+(startindex<<1)+1]; uint32 palette=(b2>>1)&15; b2=(b2<<8)|b1; wsGetTile(b2&0x1ff,start_tile_n&7,b2&0x8000,b2&0x4000,b2&0x2000); if(wsVMode) { if(wsVMode & 0x2) for(int x = 0; x < 8; x++) { if(wsTileRow[x] && in_window[adrbuf + x]) { b_bg[adrbuf + x] = wsTileRow[x] | 0x10; b_bg_pal[adrbuf + x] = palette; } } else for(int x = 0; x < 8; x++) { if((wsTileRow[x] || !(palette & 0x4)) && in_window[adrbuf + x]) { b_bg[adrbuf + x] = wsTileRow[x] | 0x10; b_bg_pal[adrbuf + x] = palette; } } } else { for(int x = 0; x < 8; x++) if((wsTileRow[x] || !(palette & 4)) && in_window[adrbuf + x]) { b_bg[adrbuf + x] = wsColors[wsMonoPal[palette][wsTileRow[x]]] | 0x10; } } adrbuf += 8; startindex=(startindex + 1)&31; } // end for(t = 0 ... } // end FG drawing if((DispControl & 0x04) && SpriteCountCache && (LayerEnabled & 0x04))/*Sprites*/ { int xs,ts,as,ys,ysx,h; bool in_window[256 + 8*2]; if(DispControl & 0x08) { memset(in_window, 0, sizeof(in_window)); if((wsLine >= SPRy0) && (wsLine < SPRy1)) for(j = SPRx0; j < SPRx1 && j < 256; j++) in_window[7 + j] = 1; } else memset(in_window, 1, sizeof(in_window)); for(h = SpriteCountCache - 1; h >= 0; h--) { ts = SpriteTable[h][0]; as = SpriteTable[h][1]; ysx = SpriteTable[h][2]; ys2 = (int8)SpriteTable[h][2]; xs = SpriteTable[h][3]; if(xs >= 249) xs -= 256; if(ysx > 150) ys = ys2; else ys = ysx; ys = wsLine - ys; if(ys >= 0 && ys < 8 && xs < 224) { uint32 palette = ((as >> 1) & 0x7); ts |= (as&1) << 8; wsGetTile(ts, ys, as & 0x80, as & 0x40, 0); if(wsVMode) { if(wsVMode & 0x2) { for(int x = 0; x < 8; x++) if(wsTileRow[x]) { if((as & 0x20) || !(b_bg[xs + x + 7] & 0x10)) { bool drawthis = 0; if(!(DispControl & 0x08)) drawthis = true; else if((as & 0x10) && !in_window[7 + xs + x]) drawthis = true; else if(!(as & 0x10) && in_window[7 + xs + x]) drawthis = true; if(drawthis) { b_bg[xs + x + 7] = wsTileRow[x] | (b_bg[xs + x + 7] & 0x10); b_bg_pal[xs + x + 7] = 8 + palette; } } } } else { for(int x = 0; x < 8; x++) if(wsTileRow[x] || !(palette & 0x4)) { if((as & 0x20) || !(b_bg[xs + x + 7] & 0x10)) { bool drawthis = 0; if(!(DispControl & 0x08)) drawthis = true; else if((as & 0x10) && !in_window[7 + xs + x]) drawthis = true; else if(!(as & 0x10) && in_window[7 + xs + x]) drawthis = true; if(drawthis) { b_bg[xs + x + 7] = wsTileRow[x] | (b_bg[xs + x + 7] & 0x10); b_bg_pal[xs + x + 7] = 8 + palette; } } } } } else { for(int x = 0; x < 8; x++) if(wsTileRow[x] || !(palette & 4)) { if((as & 0x20) || !(b_bg[xs + x + 7] & 0x10)) { bool drawthis = 0; if(!(DispControl & 0x08)) drawthis = true; else if((as & 0x10) && !in_window[7 + xs + x]) drawthis = true; else if(!(as & 0x10) && in_window[7 + xs + x]) drawthis = true; if(drawthis) //if((as & 0x10) || in_window[7 + xs + x]) { b_bg[xs + x + 7] = wsColors[wsMonoPal[8 + palette][wsTileRow[x]]] | (b_bg[xs + x + 7] & 0x10); } } } } } } } // End sprite drawing if(wsVMode) { for(l=0;l<224;l++) target[l] = ColorMap[wsCols[b_bg_pal[l+7]][b_bg[(l+7)]&0xf]]; } else { for(l=0;l<224;l++) target[l] = ColorMapG[(b_bg[l+7])&15]; } } void WSwan_GfxReset(void) { unsigned u0, u1; wsLine=0; wsSetVideo(0,true); memset(SpriteTable, 0, sizeof(SpriteTable)); SpriteCountCache = 0; DispControl = 0; BGColor = 0; LineCompare = 0xBB; SPRBase = 0; SpriteStart = 0; SpriteCount = 0; FGBGLoc = 0; FGx0 = 0; FGy0 = 0; FGx1 = 0; FGy1 = 0; SPRx0 = 0; SPRy0 = 0; SPRx1 = 0; SPRy1 = 0; BGXScroll = BGYScroll = 0; FGXScroll = FGYScroll = 0; LCDControl = 0; LCDIcons = 0; BTimerControl = 0; HBTimerPeriod = 0; VBTimerPeriod = 0; HBCounter = 0; VBCounter = 0; for(u0=0;u0<16;u0++) for(u1=0;u1<16;u1++) wsCols[u0][u1]=0; } int WSwan_GfxStateAction(StateMem *sm, int load, int data_only) { SFORMAT StateRegs[] = { SFARRAY32N(&wsMonoPal[0][0], 16 * 4, "wsMonoPal"), SFARRAY32(wsColors, 8), SFVAR(wsLine), SFARRAYN(&SpriteTable[0][0], 0x80 * 4, "SpriteTable"), SFVAR(SpriteCountCache), SFVAR(DispControl), SFVAR(BGColor), SFVAR(LineCompare), SFVAR(SPRBase), SFVAR(SpriteStart), SFVAR(SpriteCount), SFVAR(FGBGLoc), SFVAR(FGx0), SFVAR(FGy0), SFVAR(FGx1), SFVAR(FGy1), SFVAR(SPRx0), SFVAR(SPRy0), SFVAR(SPRx1), SFVAR(SPRy1), SFVAR(BGXScroll), SFVAR(BGYScroll), SFVAR(FGXScroll), SFVAR(FGYScroll), SFVAR(LCDControl), SFVAR(LCDIcons), SFVAR(BTimerControl), SFVAR(HBTimerPeriod), SFVAR(VBTimerPeriod), SFVAR(HBCounter), SFVAR(VBCounter), SFVAR(VideoMode), SFEND }; if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, "GFX")) return(0); if(load) { wsSetVideo(VideoMode >> 5, true); } return(1); } jni/000700 001750 001750 00000000000 12733077034 012454 5ustar00sergiosergio000000 000000 msvc/msvc-2010/libretro.def000664 001750 001750 00000001011 12733066400 016476 0ustar00sergiosergio000000 000000 LIBRARY "msvc-2010" EXPORTS retro_set_environment retro_set_video_refresh retro_set_audio_sample retro_set_audio_sample_batch retro_set_input_poll retro_set_input_state retro_init retro_deinit retro_api_version retro_get_system_info retro_get_system_av_info retro_set_controller_port_device retro_reset retro_run retro_serialize_size retro_serialize retro_unserialize retro_cheat_reset retro_cheat_set retro_load_game retro_load_game_special retro_unload_game retro_get_region retro_get_memory_data retro_get_memory_size msvc/msvc-2003-xbox1.sln000664 001750 001750 00000002716 12733066400 015770 0ustar00sergiosergio000000 000000 Microsoft Visual Studio Solution File, Format Version 8.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc-2003-xbox1", "msvc-2003-xbox1/msvc-2003-xbox1.vcproj", "{8FD514E6-2E2A-4599-99B1-9A413535492F}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject Global GlobalSection(SolutionConfiguration) = preSolution Debug = Debug Profile = Profile Profile_FastCap = Profile_FastCap Release = Release Release_LTCG = Release_LTCG EndGlobalSection GlobalSection(ProjectConfiguration) = postSolution {8FD514E6-2E2A-4599-99B1-9A413535492F}.Debug.ActiveCfg = Debug|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Debug.Build.0 = Debug|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Profile.ActiveCfg = Profile|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Profile.Build.0 = Profile|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Profile_FastCap.ActiveCfg = Profile_FastCap|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Profile_FastCap.Build.0 = Profile_FastCap|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Release.ActiveCfg = Release|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Release.Build.0 = Release|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Release_LTCG.ActiveCfg = Release_LTCG|Xbox {8FD514E6-2E2A-4599-99B1-9A413535492F}.Release_LTCG.Build.0 = Release_LTCG|Xbox EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution EndGlobalSection GlobalSection(ExtensibilityAddIns) = postSolution EndGlobalSection EndGlobal Makefile.common000664 001750 001750 00000003356 12733066400 014641 0ustar00sergiosergio000000 000000 SOURCES_CXX := SOURCES_C := MEDNAFEN_DIR := $(CORE_DIR)/mednafen CORE_EMU_DIR := $(MEDNAFEN_DIR)/wswan LIBRETROCOMM_DIR := $(CORE_DIR)/libretro-common INCFLAGS := -I$(CORE_DIR) -I$(MEDNAFEN_DIR) -I$(MEDNAFEN_DIR)/include -I$(MEDNAFEN_DIR)/intl -I$(MEDNAFEN_DIR)/hw_sound -I$(MEDNAFEN_DIR)/hw_cpu -I$(MEDNAFEN_DIR)/hw_misc -I$(LIBRETROCOMM_DIR)/include ifneq ($(HAVE_GRIFFIN),1) SOURCES_CXX += \ $(CORE_EMU_DIR)/gfx.cpp \ $(CORE_EMU_DIR)/wswan-memory.cpp \ $(CORE_EMU_DIR)/v30mz.cpp \ $(CORE_EMU_DIR)/sound.cpp \ $(CORE_EMU_DIR)/tcache.cpp \ $(CORE_EMU_DIR)/interrupt.cpp \ $(CORE_EMU_DIR)/eeprom.cpp \ $(CORE_EMU_DIR)/rtc.cpp endif ifeq ($(NEED_BLIP), 1) SOURCES_CXX += $(MEDNAFEN_DIR)/sound/Blip_Buffer.cpp endif ifeq ($(NEED_THREADING), 1) FLAGS += -DWANT_THREADING SOURCES_C += $(CORE_DIR)/threads.c endif ifeq ($(NEED_CRC32), 1) FLAGS += -DWANT_CRC32 SOURCES_C += $(CORE_DIR)/scrc32.c endif ifeq ($(NEED_DEINTERLACER), 1) FLAGS += -DNEED_DEINTERLACER endif ifeq ($(IS_X86), 1) FLAGS += -DARCH_X86 endif ifeq ($(NEED_BPP), 8) FLAGS += -DWANT_8BPP endif ifeq ($(NEED_BPP), 16) FLAGS += -DWANT_16BPP endif ifeq ($(NEED_BPP), 32) FLAGS += -DWANT_32BPP endif ifeq ($(WANT_NEW_API), 1) FLAGS += -DWANT_NEW_API endif ifeq ($(NO_COMPUTED_GOTO), 1) FLAGS += -DNO_COMPUTED_GOTO endif ifeq ($(NEED_STEREO_SOUND), 1) FLAGS += -DWANT_STEREO_SOUND endif ifeq ($(FRONTEND_SUPPORTS_RGB565), 1) FLAGS += -DFRONTEND_SUPPORTS_RGB565 endif ifneq ($(HAVE_GRIFFIN), 1) SOURCES_CXX += \ $(MEDNAFEN_DIR)/mednafen.cpp \ $(MEDNAFEN_DIR)/settings.cpp \ $(MEDNAFEN_DIR)/general.cpp \ $(MEDNAFEN_DIR)/state.cpp \ $(MEDNAFEN_DIR)/mempatcher.cpp \ $(MEDNAFEN_DIR)/file.cpp \ $(CORE_DIR)/libretro.cpp SOURCES_C += \ $(MEDNAFEN_DIR)/mednafen-endian.c endif mednafen/wswan/dis/dis_tables.h000755 001750 001750 00000007421 12733066400 017665 0ustar00sergiosergio000000 000000 ///////////////////////////////////////////////////////////////////////// // $Id: dis_tables.h,v 1.29 2006/04/27 15:11:45 sshwarts Exp $ ///////////////////////////////////////////////////////////////////////// #ifndef _BX_DISASM_TABLES_ #define _BX_DISASM_TABLES_ // opcode table attributes #define _GROUPN 1 #define _SPLIT11B 2 #define _GRPFP 3 #define _GRPSSE 5 #define _GRPRM 6 #define _GRP3BOP 7 #define _GRP3BTAB 8 /* ************************************************************************ */ #define GRPSSE(n) _GRPSSE, BxDisasmGroupSSE_##n #define GRPN(n) _GROUPN, BxDisasmGroup##n #define GRPRM(n) _GRPRM, BxDisasmGroupRm##n #define GRPMOD(n) _SPLIT11B, BxDisasmGroupMod##n #define GRPFP(n) _GRPFP, BxDisasmFPGroup##n #define GR3BOP(n) _GRP3BOP, BxDisasm3ByteOp##n #define GR3BTAB(n) _GRP3BTAB, BxDisasm3ByteTable##n /* ************************************************************************ */ #define Apw &disassembler::Apw #define Apd &disassembler::Apd #define AL &disassembler::AL #define CL &disassembler::CL #define AX &disassembler::AX #define DX &disassembler::DX #define EAX &disassembler::EAX #define RAX &disassembler::RAX #define CS &disassembler::CS #define DS &disassembler::DS #define ES &disassembler::ES #define SS &disassembler::SS #define FS &disassembler::FS #define GS &disassembler::GS #define Sw &disassembler::Sw #define Td &disassembler::Td #define Cd &disassembler::Cd #define Cq &disassembler::Cq #define Dd &disassembler::Dd #define Dq &disassembler::Dq #define R8 &disassembler::R8 #define RX &disassembler::RX #define Eb &disassembler::Eb #define Ew &disassembler::Ew #define Ed &disassembler::Ed #define Eq &disassembler::Eq #define Gb &disassembler::Gb #define Gw &disassembler::Gw #define Gd &disassembler::Gd #define Gq &disassembler::Gq #define I1 &disassembler::I1 #define Ib &disassembler::Ib #define Iw &disassembler::Iw #define Id &disassembler::Id #define Iq &disassembler::Iq #define IwIb &disassembler::IwIb #define sIbw &disassembler::sIbw #define sIbd &disassembler::sIbd #define sIbq &disassembler::sIbq #define sIdq &disassembler::sIdq #define ST0 &disassembler::ST0 #define STi &disassembler::STi #define Rw &disassembler::Rw #define Rd &disassembler::Rd #define Rq &disassembler::Rq #define Pq &disassembler::Pq #define Qd &disassembler::Qd #define Qq &disassembler::Qq #define Nq &disassembler::Nq #define Vq &disassembler::Vq #define Vdq &disassembler::Vdq #define Vss &disassembler::Vss #define Vsd &disassembler::Vsd #define Vps &disassembler::Vps #define Vpd &disassembler::Vpd #define Udq &disassembler::Udq #define Wq &disassembler::Wq #define Wdq &disassembler::Wdq #define Wss &disassembler::Wss #define Wsd &disassembler::Wsd #define Wps &disassembler::Wps #define Wpd &disassembler::Wpd #define Ob &disassembler::Ob #define Ow &disassembler::Ow #define Od &disassembler::Od #define Oq &disassembler::Oq #define Ma &disassembler::Ma #define Mp &disassembler::Mp #define Ms &disassembler::Ms #define Mx &disassembler::Mx #define Mb &disassembler::Mb #define Mw &disassembler::Mw #define Md &disassembler::Md #define Mq &disassembler::Mq #define Mt &disassembler::Mt #define Mdq &disassembler::Mdq #define Mps &disassembler::Mps #define Mpd &disassembler::Mpd #define Xb &disassembler::Xb #define Xw &disassembler::Xw #define Xd &disassembler::Xd #define Xq &disassembler::Xq #define Yb &disassembler::Yb #define Yw &disassembler::Yw #define Yd &disassembler::Yd #define Yq &disassembler::Yq #define Jb &disassembler::Jb #define Jw &disassembler::Jw #define Jd &disassembler::Jd #define XX 0 const struct BxDisasmOpcodeInfo_t #include "opcodes.inc" #include "dis_tables.inc" #undef XX #endif mednafen/wswan/v30mz.cpp000664 001750 001750 00000155447 12733066400 016322 0ustar00sergiosergio000000 000000 /**************************************************************************** NEC V30MZ emulator Stripped out non-V30MZ clock counts and code. Small changes made by dox@space.pl (Corrected bug in NEG instruction , different AUX flag handling in some opcodes) (Re)Written June-September 2000 by Bryan McPhail (mish@tendril.co.uk) based on code by Oliver Bergmann (Raul_Bloodworth@hotmail.com) who based code on the i286 emulator by Fabrice Frances which had initial work based on David Hedley's pcemu(!). ****************************************************************************/ /* This NEC V30MZ emulator may be used for purposes both commercial and noncommercial if you give the author, Bryan McPhail, a small credit somewhere(such as in the documentation for an executable package). */ /* TODO: Implement bus lock fully(prevent interrupts from occuring during a REP sequence, I think...), taking into account HLT emulation to prevent deadlocks! Implement better prefix emulation. It's extremely kludgey right now. Implement prefetch/pipeline emulation. */ #include "wswan.h" #include "wswan-memory.h" #include #include "v30mz.h" #include "v30mz-private.h" #include "debug.h" static uint16 old_CS, old_IP; #ifdef WANT_DEBUGGER #define ADDBRANCHTRACE(x,y) { if(branch_trace_hook) branch_trace_hook(old_CS, old_IP, x, y, false); } #define ADDBRANCHTRACE_INT(x,y) { if(branch_trace_hook) branch_trace_hook(old_CS, old_IP, x,y, true); } #define SETOLDCSIP() { old_CS = I.sregs[PS]; old_IP = I.pc; } #else #define ADDBRANCHTRACE(x,y) { } #define ADDBRANCHTRACE_INT(x,y) { } #define SETOLDCSIP() { } #endif typedef union { /* eight general registers */ uint16 w[8]; /* viewed as 16 bits registers */ uint8 b[16]; /* or as 8 bit registers */ } v30mz_basicregs_t; typedef struct { v30mz_basicregs_t regs; uint16 sregs[4]; uint16 pc; int32 SignVal; uint32 AuxVal, OverVal, ZeroVal, CarryVal, ParityVal; /* 0 or non-0 valued flags */ uint8 TF, IF, DF; } v30mz_regs_t; static void (*cpu_writemem20)(uint32,uint8) = NULL; static uint8 (*cpu_readport)(uint32) = NULL; static void (*cpu_writeport)(uint32, uint8) = NULL; static uint8 (*cpu_readmem20)(uint32) = NULL; /***************************************************************************/ /* cpu state */ /***************************************************************************/ uint32 v30mz_timestamp; int32 v30mz_ICount; static v30mz_regs_t I; static bool InHLT; static uint32 prefix_base; /* base address of the latest prefix segment */ static char seg_prefix; /* prefix segment indicator */ #ifdef WANT_DEBUGGER static void (*cpu_hook)(uint32) = NULL; static uint8 (*read_hook)(uint32) = NULL; static void (*write_hook)(uint32, uint8) = NULL; static uint8 (*port_read_hook)(uint32) = NULL; static void (*port_write_hook)(uint32, uint8) = NULL; static bool hookie_hickey = 0; static void (*branch_trace_hook)(uint16 from_CS, uint16 from_IP, uint16 to_CS, uint16 to_IP, bool interrupt) = NULL; #endif #include "v30mz-ea.inc" #include "v30mz-modrm.inc" static uint8 parity_table[256]; static INLINE void i_real_pushf(void) { PUSH( CompressFlags() ); CLK(2); } static INLINE void i_real_popf(void) { uint32 tmp; POP(tmp); ExpandFlags(tmp); CLK(3); } /***************************************************************************/ void v30mz_init(uint8 (*readmem20)(uint32), void (*writemem20)(uint32,uint8), uint8 (*readport)(uint32), void (*writeport)(uint32, uint8)) { cpu_readmem20 = readmem20; cpu_writemem20 = writemem20; cpu_readport = readport; cpu_writeport = writeport; } void v30mz_reset(void) { unsigned i; const BREGS reg_name[8] = { AL, CL, DL, BL, AH, CH, DH, BH }; v30mz_ICount = 0; v30mz_timestamp = 0; memset(&I, 0, sizeof(I)); I.sregs[PS] = 0xffff; for(i = 0; i < 256; i++) { unsigned j; unsigned int c = 0; for (j = i; j > 0; j >>= 1) if (j & 1) c++; parity_table[i] = !(c & 1); } I.ZeroVal = I.ParityVal = 1; for(i = 0; i < 256; i++) { Mod_RM.reg.b[i] = reg_name[(i & 0x38) >> 3]; Mod_RM.reg.w[i] = (WREGS) ( (i & 0x38) >> 3) ; } for(i = 0xc0; i < 0x100; i++) { Mod_RM.RM.w[i] = (WREGS)( i & 7 ); Mod_RM.RM.b[i] = (BREGS)reg_name[i & 7]; } prefix_base = 0; seg_prefix = 0; InHLT = 0; } void v30mz_int(uint32 vector, bool IgnoreIF) { InHLT = false; // This is correct! Standby mode is always exited when there is an INT signal, regardless of whether interrupt are disabled. if(I.IF || IgnoreIF) { uint32 dest_seg, dest_off; PUSH( CompressFlags() ); I.TF = I.IF = 0; dest_off = ReadWord(vector); dest_seg = ReadWord(vector+2); PUSH(I.sregs[PS]); PUSH(I.pc); I.pc = (uint16)dest_off; I.sregs[PS] = (uint16)dest_seg; ADDBRANCHTRACE_INT(I.sregs[PS], I.pc); CLK(32); } } static void nec_interrupt(unsigned int_num) { uint32 dest_seg, dest_off; if (int_num == -1) return; i_real_pushf(); I.TF = I.IF = 0; dest_off = ReadWord((int_num)*4); dest_seg = ReadWord((int_num)*4+2); PUSH(I.sregs[PS]); PUSH(I.pc); I.pc = (uint16)dest_off; I.sregs[PS] = (uint16)dest_seg; ADDBRANCHTRACE(I.sregs[PS], I.pc); } static bool CheckInHLT(void) { if(InHLT) { WSwan_InterruptCheck(); if(InHLT) { int32 tmp = v30mz_ICount; if(tmp > 0) CLK(tmp); return(1); } } return(0); } /****************************************************************************/ /* OPCODES */ /****************************************************************************/ static INLINE void i_real_insb(void) { PutMemB(DS1,I.regs.w[IY], read_port(I.regs.w[DW])); I.regs.w[IY]+= -2 * I.DF + 1; CLK(6); } static INLINE void i_real_insw(void) { PutMemB(DS1,I.regs.w[IY],read_port(I.regs.w[DW])); PutMemB(DS1,(I.regs.w[IY]+1)&0xffff,read_port((I.regs.w[DW]+1)&0xffff)); I.regs.w[IY]+= -4 * I.DF + 2; CLK(6); } static INLINE void i_real_outsb(void) { write_port(I.regs.w[DW],GetMemB(DS0,I.regs.w[IX])); I.regs.w[IX]+= -2 * I.DF + 1; CLK(7); } static INLINE void i_real_outsw(void) { write_port(I.regs.w[DW],GetMemB(DS0,I.regs.w[IX])); write_port((I.regs.w[DW]+1)&0xffff,GetMemB(DS0,(I.regs.w[IX]+1)&0xffff)); I.regs.w[IX]+= -4 * I.DF + 2; CLK(7); } static INLINE void i_real_movsb(void) { uint32 tmp = GetMemB(DS0,I.regs.w[IX]); PutMemB(DS1,I.regs.w[IY], tmp); I.regs.w[IY] += -2 * I.DF + 1; I.regs.w[IX] += -2 * I.DF + 1; CLK(5); } static INLINE void i_real_movsw(void) { uint32 tmp = GetMemW(DS0,I.regs.w[IX]); PutMemW(DS1,I.regs.w[IY], tmp); I.regs.w[IY] += -4 * I.DF + 2; I.regs.w[IX] += -4 * I.DF + 2; CLK(5); } static INLINE void i_real_cmpsb(void) { uint32 src = GetMemB(DS1, I.regs.w[IY]); uint32 dst = GetMemB(DS0, I.regs.w[IX]); SUBB; I.regs.w[IY] += -2 * I.DF + 1; I.regs.w[IX] += -2 * I.DF + 1; CLK(6); } static INLINE void i_real_cmpsw(void) { uint32 src = GetMemW(DS1, I.regs.w[IY]); uint32 dst = GetMemW(DS0, I.regs.w[IX]); SUBW; I.regs.w[IY] += -4 * I.DF + 2; I.regs.w[IX] += -4 * I.DF + 2; CLK(6); } static INLINE void i_real_stosb(void) { PutMemB(DS1,I.regs.w[IY],I.regs.b[AL]); I.regs.w[IY] += -2 * I.DF + 1; CLK(3); } static INLINE void i_real_stosw(void) { PutMemW(DS1,I.regs.w[IY],I.regs.w[AW]); I.regs.w[IY] += -4 * I.DF + 2; CLK(3); } static INLINE void i_real_lodsb(void) { I.regs.b[AL] = GetMemB(DS0,I.regs.w[IX]); I.regs.w[IX] += -2 * I.DF + 1; CLK(3); } static INLINE void i_real_lodsw(void) { I.regs.w[AW] = GetMemW(DS0,I.regs.w[IX]); I.regs.w[IX] += -4 * I.DF + 2; CLK(3); } static INLINE void i_real_scasb(void) { uint32 src = GetMemB(DS1, I.regs.w[IY]); uint32 dst = I.regs.b[AL]; SUBB; I.regs.w[IY] += -2 * I.DF + 1; CLK(4); } static INLINE void i_real_scasw(void) { uint32 src = GetMemW(DS1, I.regs.w[IY]); uint32 dst = I.regs.w[AW]; SUBW; I.regs.w[IY] += -4 * I.DF + 2; CLK(4); } static void DoOP(uint8 opcode) { //#define OP(num,func_name) static void func_name(void) #define OP(num, func_name) case num: #define OP_RANGE(num1, num2, func_name) case num1 ... num2: #define OP_EPILOGUE break switch(opcode) { default: printf("Invalid op: %02x\n", opcode); CLK(10); break; OP( 0x00, i_add_br8 ) { DEF_br8; ADDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x01, i_add_wr16 ) { DEF_wr16; ADDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x02, i_add_r8b ) { DEF_r8b; ADDB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x03, i_add_r16w ) { DEF_r16w; ADDW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x04, i_add_ald8 ) { DEF_ald8; ADDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE; OP( 0x05, i_add_axd16) { DEF_axd16; ADDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE; OP( 0x06, i_push_ds1 ) { PUSH(I.sregs[DS1]); CLK(2); } OP_EPILOGUE; OP( 0x07, i_pop_ds1 ) { POP(I.sregs[DS1]); CLK(3); } OP_EPILOGUE; OP( 0x08, i_or_br8 ) { DEF_br8; ORB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x09, i_or_wr16 ) { DEF_wr16; ORW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x0a, i_or_r8b ) { DEF_r8b; ORB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x0b, i_or_r16w ) { DEF_r16w; ORW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x0c, i_or_ald8 ) { DEF_ald8; ORB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE; OP( 0x0d, i_or_axd16 ) { DEF_axd16; ORW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE; OP( 0x0e, i_push_cs ) { PUSH(I.sregs[PS]); CLK(2); } OP_EPILOGUE; OP( 0x10, i_adc_br8 ) { DEF_br8; src+=CF; ADDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x11, i_adc_wr16 ) { DEF_wr16; src+=CF; ADDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x12, i_adc_r8b ) { DEF_r8b; src+=CF; ADDB; RegByte(ModRM)=dst; CLKM(2, 1); } OP_EPILOGUE; OP( 0x13, i_adc_r16w ) { DEF_r16w; src+=CF; ADDW; RegWord(ModRM)=dst; CLKM(2, 1); } OP_EPILOGUE; OP( 0x14, i_adc_ald8 ) { DEF_ald8; src+=CF; ADDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE; OP( 0x15, i_adc_axd16) { DEF_axd16; src+=CF; ADDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE; OP( 0x16, i_push_ss ) { PUSH(I.sregs[SS]); CLK(2); } OP_EPILOGUE; OP( 0x17, i_pop_ss ) { POP(I.sregs[SS]); CLK(3); } OP_EPILOGUE; OP( 0x18, i_sbb_br8 ) { DEF_br8; src+=CF; SUBB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x19, i_sbb_wr16 ) { DEF_wr16; src+=CF; SUBW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x1a, i_sbb_r8b ) { DEF_r8b; src+=CF; SUBB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x1b, i_sbb_r16w ) { DEF_r16w; src+=CF; SUBW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x1c, i_sbb_ald8 ) { DEF_ald8; src+=CF; SUBB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE; OP( 0x1d, i_sbb_axd16) { DEF_axd16; src+=CF; SUBW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE; OP( 0x1e, i_push_ds ) { PUSH(I.sregs[DS0]); CLK(2); } OP_EPILOGUE; OP( 0x1f, i_pop_ds ) { POP(I.sregs[DS0]); CLK(3); } OP_EPILOGUE; OP( 0x20, i_and_br8 ) { DEF_br8; ANDB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x21, i_and_wr16 ) { DEF_wr16; ANDW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x22, i_and_r8b ) { DEF_r8b; ANDB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x23, i_and_r16w ) { DEF_r16w; ANDW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x24, i_and_ald8 ) { DEF_ald8; ANDB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE; OP( 0x25, i_and_axd16) { DEF_axd16; ANDW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE; OP( 0x26, i_ds1 ) { seg_prefix=true; prefix_base=I.sregs[DS1]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=false; } OP_EPILOGUE; OP( 0x27, i_daa ) { ADJ4(6,0x60); CLK(10); } OP_EPILOGUE; OP( 0x28, i_sub_br8 ) { DEF_br8; SUBB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x29, i_sub_wr16 ) { DEF_wr16; SUBW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x2a, i_sub_r8b ) { DEF_r8b; SUBB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x2b, i_sub_r16w ) { DEF_r16w; SUBW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x2c, i_sub_ald8 ) { DEF_ald8; SUBB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE; OP( 0x2d, i_sub_axd16) { DEF_axd16; SUBW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE; OP( 0x2e, i_ps ) { seg_prefix=true; prefix_base=I.sregs[PS]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=false; } OP_EPILOGUE; OP( 0x2f, i_das ) { ADJ4(-6,-0x60); CLK(10); } OP_EPILOGUE; OP( 0x30, i_xor_br8 ) { DEF_br8; XORB; PutbackRMByte(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x31, i_xor_wr16 ) { DEF_wr16; XORW; PutbackRMWord(ModRM,dst); CLKM(3,1); } OP_EPILOGUE; OP( 0x32, i_xor_r8b ) { DEF_r8b; XORB; RegByte(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x33, i_xor_r16w ) { DEF_r16w; XORW; RegWord(ModRM)=dst; CLKM(2,1); } OP_EPILOGUE; OP( 0x34, i_xor_ald8 ) { DEF_ald8; XORB; I.regs.b[AL]=dst; CLK(1); } OP_EPILOGUE; OP( 0x35, i_xor_axd16) { DEF_axd16; XORW; I.regs.w[AW]=dst; CLK(1); } OP_EPILOGUE; OP( 0x36, i_ss ) { seg_prefix=true; prefix_base=I.sregs[SS]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=false; } OP_EPILOGUE; OP( 0x37, i_aaa ) { ADJB(6,1); CLK(9); } OP_EPILOGUE; OP( 0x38, i_cmp_br8 ) { DEF_br8; SUBB; CLKM(2,1); } OP_EPILOGUE; OP( 0x39, i_cmp_wr16 ) { DEF_wr16; SUBW; CLKM(2,1); } OP_EPILOGUE; OP( 0x3a, i_cmp_r8b ) { DEF_r8b; SUBB; CLKM(2,1); } OP_EPILOGUE; OP( 0x3b, i_cmp_r16w ) { DEF_r16w; SUBW; CLKM(2,1); } OP_EPILOGUE; OP( 0x3c, i_cmp_ald8 ) { DEF_ald8; SUBB; CLK(1); } OP_EPILOGUE; OP( 0x3d, i_cmp_axd16) { DEF_axd16; SUBW; CLK(1); } OP_EPILOGUE; OP( 0x3e, i_ds0 ) { seg_prefix=true; prefix_base=I.sregs[DS0]<<4; CLK(1); DoOP(FETCHOP); seg_prefix=false; } OP_EPILOGUE; OP( 0x3f, i_aas ) { ADJB(-6,-1); CLK(9); } OP_EPILOGUE; OP( 0x40, i_inc_ax ) { IncWordReg(AW); CLK(1); } OP_EPILOGUE; OP( 0x41, i_inc_cx ) { IncWordReg(CW); CLK(1); } OP_EPILOGUE; OP( 0x42, i_inc_dx ) { IncWordReg(DW); CLK(1); } OP_EPILOGUE; OP( 0x43, i_inc_bx ) { IncWordReg(BW); CLK(1); } OP_EPILOGUE; OP( 0x44, i_inc_sp ) { IncWordReg(SP); CLK(1); } OP_EPILOGUE; OP( 0x45, i_inc_bp ) { IncWordReg(BP); CLK(1); } OP_EPILOGUE; OP( 0x46, i_inc_si ) { IncWordReg(IX); CLK(1); } OP_EPILOGUE; OP( 0x47, i_inc_di ) { IncWordReg(IY); CLK(1); } OP_EPILOGUE; OP( 0x48, i_dec_ax ) { DecWordReg(AW); CLK(1); } OP_EPILOGUE; OP( 0x49, i_dec_cx ) { DecWordReg(CW); CLK(1); } OP_EPILOGUE; OP( 0x4a, i_dec_dx ) { DecWordReg(DW); CLK(1); } OP_EPILOGUE; OP( 0x4b, i_dec_bx ) { DecWordReg(BW); CLK(1); } OP_EPILOGUE; OP( 0x4c, i_dec_sp ) { DecWordReg(SP); CLK(1); } OP_EPILOGUE; OP( 0x4d, i_dec_bp ) { DecWordReg(BP); CLK(1); } OP_EPILOGUE; OP( 0x4e, i_dec_si ) { DecWordReg(IX); CLK(1); } OP_EPILOGUE; OP( 0x4f, i_dec_di ) { DecWordReg(IY); CLK(1); } OP_EPILOGUE; OP( 0x50, i_push_ax ) { PUSH(I.regs.w[AW]); CLK(1); } OP_EPILOGUE; OP( 0x51, i_push_cx ) { PUSH(I.regs.w[CW]); CLK(1); } OP_EPILOGUE; OP( 0x52, i_push_dx ) { PUSH(I.regs.w[DW]); CLK(1); } OP_EPILOGUE; OP( 0x53, i_push_bx ) { PUSH(I.regs.w[BW]); CLK(1); } OP_EPILOGUE; OP( 0x54, i_push_sp ) { PUSH(I.regs.w[SP]); CLK(1); } OP_EPILOGUE; OP( 0x55, i_push_bp ) { PUSH(I.regs.w[BP]); CLK(1); } OP_EPILOGUE; OP( 0x56, i_push_si ) { PUSH(I.regs.w[IX]); CLK(1); } OP_EPILOGUE; OP( 0x57, i_push_di ) { PUSH(I.regs.w[IY]); CLK(1); } OP_EPILOGUE; OP( 0x58, i_pop_ax ) { POP(I.regs.w[AW]); CLK(1); } OP_EPILOGUE; OP( 0x59, i_pop_cx ) { POP(I.regs.w[CW]); CLK(1); } OP_EPILOGUE; OP( 0x5a, i_pop_dx ) { POP(I.regs.w[DW]); CLK(1); } OP_EPILOGUE; OP( 0x5b, i_pop_bx ) { POP(I.regs.w[BW]); CLK(1); } OP_EPILOGUE; OP( 0x5c, i_pop_sp ) { POP(I.regs.w[SP]); CLK(1); } OP_EPILOGUE; OP( 0x5d, i_pop_bp ) { POP(I.regs.w[BP]); CLK(1); } OP_EPILOGUE; OP( 0x5e, i_pop_si ) { POP(I.regs.w[IX]); CLK(1); } OP_EPILOGUE; OP( 0x5f, i_pop_di ) { POP(I.regs.w[IY]); CLK(1); } OP_EPILOGUE; OP( 0x60, i_pusha ) { unsigned tmp=I.regs.w[SP]; PUSH(I.regs.w[AW]); PUSH(I.regs.w[CW]); PUSH(I.regs.w[DW]); PUSH(I.regs.w[BW]); PUSH(tmp); PUSH(I.regs.w[BP]); PUSH(I.regs.w[IX]); PUSH(I.regs.w[IY]); CLK(9); } OP_EPILOGUE; OP( 0x61, i_popa ) { unsigned tmp; POP(I.regs.w[IY]); POP(I.regs.w[IX]); POP(I.regs.w[BP]); POP(tmp); POP(I.regs.w[BW]); POP(I.regs.w[DW]); POP(I.regs.w[CW]); POP(I.regs.w[AW]); CLK(8); } OP_EPILOGUE; OP( 0x62, i_chkind ) { uint32 low,high,tmp; GetModRM; low = GetRMWord(ModRM); high = GetnextRMWord; tmp = RegWord(ModRM); CLK(13); if (tmphigh) { nec_interrupt(5); } } OP_EPILOGUE; OP( 0x68, i_push_d16 ) { uint32 tmp; FETCHuint16(tmp); PUSH(tmp); CLK(1); } OP_EPILOGUE; OP( 0x69, i_imul_d16 ) { uint32 tmp; DEF_r16w; FETCHuint16(tmp); dst = (int32)((int16)src)*(int32)((int16)tmp); I.CarryVal = I.OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1); RegWord(ModRM)=(uint16)dst; CLKM(4,3);} OP_EPILOGUE; OP( 0x6a, i_push_d8 ) { uint32 tmp = (uint16)((int16)((int8)FETCH)); PUSH(tmp); CLK(1); } OP_EPILOGUE; OP( 0x6b, i_imul_d8 ) { uint32 src2; DEF_r16w; src2= (uint16)((int16)((int8)FETCH)); dst = (int32)((int16)src)*(int32)((int16)src2); I.CarryVal = I.OverVal = (((int32)dst) >> 15 != 0) && (((int32)dst) >> 15 != -1); RegWord(ModRM)=(uint16)dst; CLKM(4,3); } OP_EPILOGUE; OP( 0x6c, i_insb ) { i_real_insb(); } OP_EPILOGUE; OP( 0x6d, i_insw ) { i_real_insw(); } OP_EPILOGUE; OP( 0x6e, i_outsb ) { i_real_outsb(); } OP_EPILOGUE; OP( 0x6f, i_outsw ) { i_real_outsw(); } OP_EPILOGUE; OP( 0x70, i_jo ) { JMP( FLAG_O); CLK(1); } OP_EPILOGUE; OP( 0x71, i_jno ) { JMP(!FLAG_O); CLK(1); } OP_EPILOGUE; OP( 0x72, i_jc ) { JMP( CF); CLK(1); } OP_EPILOGUE; OP( 0x73, i_jnc ) { JMP(!CF); CLK(1); } OP_EPILOGUE; OP( 0x74, i_jz ) { JMP( ZF); CLK(1); } OP_EPILOGUE; OP( 0x75, i_jnz ) { JMP(!ZF); CLK(1); } OP_EPILOGUE; OP( 0x76, i_jce ) { JMP(CF || ZF); CLK(1); } OP_EPILOGUE; OP( 0x77, i_jnce ) { JMP(!(CF || ZF)); CLK(1); } OP_EPILOGUE; OP( 0x78, i_js ) { JMP( SF); CLK(1); } OP_EPILOGUE; OP( 0x79, i_jns ) { JMP(!SF); CLK(1); } OP_EPILOGUE; OP( 0x7a, i_jp ) { JMP( PF); CLK(1); } OP_EPILOGUE; OP( 0x7b, i_jnp ) { JMP(!PF); CLK(1); } OP_EPILOGUE; OP( 0x7c, i_jl ) { JMP((SF!=FLAG_O)&&(!ZF)); CLK(1); } OP_EPILOGUE; OP( 0x7d, i_jnl ) { JMP((ZF)||(SF==FLAG_O)); CLK(1); } OP_EPILOGUE; OP( 0x7e, i_jle ) { JMP((ZF)||(SF!=FLAG_O)); CLK(1); } OP_EPILOGUE; OP( 0x7f, i_jnle ) { JMP((SF==FLAG_O)&&(!ZF)); CLK(1); } OP_EPILOGUE; OP( 0x80, i_80pre ) { uint32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = FETCH; CLKM(3, 1); switch (ModRM & 0x38) { case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; case 0x08: ORB; PutbackRMByte(ModRM,dst); break; case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; case 0x30: XORB; PutbackRMByte(ModRM,dst); break; case 0x38: SUBB; break; /* CMP */ } } OP_EPILOGUE; OP( 0x81, i_81pre ) { uint32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = FETCH; src+= (FETCH << 8); CLKM(3, 1); switch (ModRM & 0x38) { case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; case 0x08: ORW; PutbackRMWord(ModRM,dst); break; case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; case 0x30: XORW; PutbackRMWord(ModRM,dst); break; case 0x38: SUBW; break; /* CMP */ } } OP_EPILOGUE; OP( 0x82, i_82pre ) { uint32 dst, src; GetModRM; dst = GetRMByte(ModRM); src = (uint8)((int8)FETCH); CLKM(3,1); switch (ModRM & 0x38) { case 0x00: ADDB; PutbackRMByte(ModRM,dst); break; case 0x08: ORB; PutbackRMByte(ModRM,dst); break; case 0x10: src+=CF; ADDB; PutbackRMByte(ModRM,dst); break; case 0x18: src+=CF; SUBB; PutbackRMByte(ModRM,dst); break; case 0x20: ANDB; PutbackRMByte(ModRM,dst); break; case 0x28: SUBB; PutbackRMByte(ModRM,dst); break; case 0x30: XORB; PutbackRMByte(ModRM,dst); break; case 0x38: SUBB; break; /* CMP */ } } OP_EPILOGUE; OP( 0x83, i_83pre ) { uint32 dst, src; GetModRM; dst = GetRMWord(ModRM); src = (uint16)((int16)((int8)FETCH)); CLKM(3,1); switch (ModRM & 0x38) { case 0x00: ADDW; PutbackRMWord(ModRM,dst); break; case 0x08: ORW; PutbackRMWord(ModRM,dst); break; case 0x10: src+=CF; ADDW; PutbackRMWord(ModRM,dst); break; case 0x18: src+=CF; SUBW; PutbackRMWord(ModRM,dst); break; case 0x20: ANDW; PutbackRMWord(ModRM,dst); break; case 0x28: SUBW; PutbackRMWord(ModRM,dst); break; case 0x30: XORW; PutbackRMWord(ModRM,dst); break; case 0x38: SUBW; break; /* CMP */ } } OP_EPILOGUE; OP( 0x84, i_test_br8 ) { DEF_br8; ANDB; CLKM(2,1); } OP_EPILOGUE; OP( 0x85, i_test_wr16 ) { DEF_wr16; ANDW; CLKM(2,1); } OP_EPILOGUE; OP( 0x86, i_xchg_br8 ) { DEF_br8; RegByte(ModRM)=dst; PutbackRMByte(ModRM,src); CLKM(5,3); } OP_EPILOGUE; OP( 0x87, i_xchg_wr16 ) { DEF_wr16; RegWord(ModRM)=dst; PutbackRMWord(ModRM,src); CLKM(5,3); } OP_EPILOGUE; OP( 0x88, i_mov_br8 ) { uint8 src; GetModRM; src = RegByte(ModRM); PutRMByte(ModRM,src); CLK(1); } OP_EPILOGUE; OP( 0x89, i_mov_wr16 ) { uint16 src; GetModRM; src = RegWord(ModRM); PutRMWord(ModRM,src); CLK(1); } OP_EPILOGUE; OP( 0x8a, i_mov_r8b ) { uint8 src; GetModRM; src = GetRMByte(ModRM); RegByte(ModRM)=src; CLK(1); } OP_EPILOGUE; OP( 0x8b, i_mov_r16w ) { uint16 src; GetModRM; src = GetRMWord(ModRM); RegWord(ModRM)=src; CLK(1); } OP_EPILOGUE; OP( 0x8c, i_mov_wsreg ) { GetModRM; PutRMWord(ModRM,I.sregs[(ModRM & 0x38) >> 3]); CLK(1); } OP_EPILOGUE; OP( 0x8d, i_lea ) { uint16 ModRM = FETCH; if(ModRM >= 192) { printf("LEA Error: %02x\n", ModRM);} else { (void)(*GetEA[ModRM])(); } RegWord(ModRM)=EO; CLK(1); } OP_EPILOGUE; OP( 0x8e, i_mov_sregw ) { uint16 src; GetModRM; src = GetRMWord(ModRM); CLKM(3,2); switch (ModRM & 0x38) { case 0x00: I.sregs[DS1] = src; break; /* mov ds1,ew */ case 0x08: I.sregs[PS] = src; break; /* mov cs,ew */ case 0x10: I.sregs[SS] = src; break; /* mov ss,ew */ case 0x18: I.sregs[DS0] = src; break; /* mov ds0,ew */ } } OP_EPILOGUE; OP( 0x8f, i_popw ) { uint16 tmp; GetModRM; POP(tmp); PutRMWord(ModRM,tmp); CLKM(3,1); } OP_EPILOGUE; OP( 0x90, i_nop ) { CLK(3); } OP_EPILOGUE; OP( 0x91, i_xchg_axcx ) { XchgAWReg(CW); CLK(3); } OP_EPILOGUE; OP( 0x92, i_xchg_axdx ) { XchgAWReg(DW); CLK(3); } OP_EPILOGUE; OP( 0x93, i_xchg_axbx ) { XchgAWReg(BW); CLK(3); } OP_EPILOGUE; OP( 0x94, i_xchg_axsp ) { XchgAWReg(SP); CLK(3); } OP_EPILOGUE; OP( 0x95, i_xchg_axbp ) { XchgAWReg(BP); CLK(3); } OP_EPILOGUE; OP( 0x96, i_xchg_axsi ) { XchgAWReg(IX); CLK(3); } OP_EPILOGUE; OP( 0x97, i_xchg_axdi ) { XchgAWReg(IY); CLK(3); } OP_EPILOGUE; // AKA CVTBW OP( 0x98, i_cbw ) { I.regs.b[AH] = (I.regs.b[AL] & 0x80) ? 0xff : 0; CLK(1); } OP_EPILOGUE; // AKA CVTWL OP( 0x99, i_cwd ) { I.regs.w[DW] = (I.regs.b[AH] & 0x80) ? 0xffff : 0; CLK(1); } OP_EPILOGUE; OP( 0x9a, i_call_far ) { uint32 tmp, tmp2; FETCHuint16(tmp); FETCHuint16(tmp2); PUSH(I.sregs[PS]); PUSH(I.pc); I.pc = (uint16)tmp; I.sregs[PS] = (uint16)tmp2; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(10); } OP_EPILOGUE; OP( 0x9b, i_poll ) { puts("POLL"); } OP_EPILOGUE; OP( 0x9c, i_pushf ) { i_real_pushf(); } OP_EPILOGUE; OP( 0x9d, i_popf ) { i_real_popf(); } OP_EPILOGUE; OP( 0x9e, i_sahf ) { uint32 tmp = (CompressFlags() & 0xff00) | (I.regs.b[AH] & 0xd5); ExpandFlags(tmp); CLK(4); } OP_EPILOGUE; OP( 0x9f, i_lahf ) { I.regs.b[AH] = CompressFlags() & 0xff; CLK(2); } OP_EPILOGUE; OP( 0xa0, i_mov_aldisp ) { uint32 addr; FETCHuint16(addr); I.regs.b[AL] = GetMemB(DS0, addr); CLK(1); } OP_EPILOGUE; OP( 0xa1, i_mov_axdisp ) { uint32 addr; FETCHuint16(addr); I.regs.b[AL] = GetMemB(DS0, addr); I.regs.b[AH] = GetMemB(DS0, (addr+1)&0xffff); CLK(1); } OP_EPILOGUE; OP( 0xa2, i_mov_dispal ) { uint32 addr; FETCHuint16(addr); PutMemB(DS0, addr, I.regs.b[AL]); CLK(1); } OP_EPILOGUE; OP( 0xa3, i_mov_dispax ) { uint32 addr; FETCHuint16(addr); PutMemB(DS0, addr, I.regs.b[AL]); PutMemB(DS0, (addr+1)&0xffff, I.regs.b[AH]); CLK(1); } OP_EPILOGUE; OP( 0xa4, i_movsb ) { i_real_movsb(); } OP_EPILOGUE; OP( 0xa5, i_movsw ) { i_real_movsw(); } OP_EPILOGUE; OP( 0xa6, i_cmpsb ) { i_real_cmpsb(); } OP_EPILOGUE; OP( 0xa7, i_cmpsw ) { i_real_cmpsw(); } OP_EPILOGUE; OP( 0xa8, i_test_ald8 ) { DEF_ald8; ANDB; CLK(1); } OP_EPILOGUE; OP( 0xa9, i_test_axd16 ) { DEF_axd16; ANDW; CLK(1); } OP_EPILOGUE; OP( 0xaa, i_stosb ) { i_real_stosb(); } OP_EPILOGUE; OP( 0xab, i_stosw ) { i_real_stosw(); } OP_EPILOGUE; OP( 0xac, i_lodsb ) { i_real_lodsb(); } OP_EPILOGUE; OP( 0xad, i_lodsw ) { i_real_lodsw(); } OP_EPILOGUE; OP( 0xae, i_scasb ) { i_real_scasb(); } OP_EPILOGUE; OP( 0xaf, i_scasw ) { i_real_scasw(); } OP_EPILOGUE; OP( 0xb0, i_mov_ald8 ) { I.regs.b[AL] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb1, i_mov_cld8 ) { I.regs.b[CL] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb2, i_mov_dld8 ) { I.regs.b[DL] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb3, i_mov_bld8 ) { I.regs.b[BL] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb4, i_mov_ahd8 ) { I.regs.b[AH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb5, i_mov_chd8 ) { I.regs.b[CH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb6, i_mov_dhd8 ) { I.regs.b[DH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb7, i_mov_bhd8 ) { I.regs.b[BH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb8, i_mov_axd16 ) { I.regs.b[AL] = FETCH; I.regs.b[AH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xb9, i_mov_cxd16 ) { I.regs.b[CL] = FETCH; I.regs.b[CH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xba, i_mov_dxd16 ) { I.regs.b[DL] = FETCH; I.regs.b[DH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xbb, i_mov_bxd16 ) { I.regs.b[BL] = FETCH; I.regs.b[BH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xbc, i_mov_spd16 ) { I.regs.b[SPL] = FETCH; I.regs.b[SPH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xbd, i_mov_bpd16 ) { I.regs.b[BPL] = FETCH; I.regs.b[BPH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xbe, i_mov_sid16 ) { I.regs.b[IXL] = FETCH; I.regs.b[IXH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xbf, i_mov_did16 ) { I.regs.b[IYL] = FETCH; I.regs.b[IYH] = FETCH; CLK(1); } OP_EPILOGUE; OP( 0xc0, i_rotshft_bd8 ) { uint32 src, dst; uint8 c; GetModRM; src = (unsigned)GetRMByte(ModRM); dst=src; c=FETCH; c&=0x1f; CLKM(5,3); if (c) switch (ModRM & 0x38) { case 0x00: do { ROL_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x08: do { ROR_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x10: do { ROLC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x18: do { RORC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x20: SHL_uint8(c); I.AuxVal = 1; break;// case 0x28: SHR_uint8(c); I.AuxVal = 1; break;// case 0x30: break; case 0x38: SHRA_uint8(c); break; } } OP_EPILOGUE; OP( 0xc1, i_rotshft_wd8 ) { uint32 src, dst; uint8 c; GetModRM; src = (unsigned)GetRMWord(ModRM); dst=src; c=FETCH; c&=0x1f; CLKM(5,3); if (c) switch (ModRM & 0x38) { case 0x00: do { ROL_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x08: do { ROR_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x10: do { ROLC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x18: do { RORC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x20: SHL_uint16(c); I.AuxVal = 1; break; case 0x28: SHR_uint16(c); I.AuxVal = 1; break; case 0x30: break; case 0x38: SHRA_uint16(c); break; } } OP_EPILOGUE; OP( 0xc2, i_ret_d16 ) { uint32 count = FETCH; count += FETCH << 8; POP(I.pc); I.regs.w[SP]+=count; CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE; OP( 0xc3, i_ret ) { POP(I.pc); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE; OP( 0xc4, i_les_dw ) { GetModRM; uint16 tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; I.sregs[DS1] = GetnextRMWord; CLK(6); } OP_EPILOGUE; OP( 0xc5, i_lds_dw ) { GetModRM; uint16 tmp = GetRMWord(ModRM); RegWord(ModRM)=tmp; I.sregs[DS0] = GetnextRMWord; CLK(6); } OP_EPILOGUE; OP( 0xc6, i_mov_bd8 ) { GetModRM; PutImmRMByte(ModRM); CLK(1); } OP_EPILOGUE; OP( 0xc7, i_mov_wd16 ) { GetModRM; PutImmRMWord(ModRM); CLK(1); } OP_EPILOGUE; // NEC calls it "PREPARE" OP( 0xc8, i_enter ) { uint32 nb = FETCH; uint32 i,level; CLK(19); nb += FETCH << 8; level = FETCH; level &= 0x1F; // Only lower 5 bits are valid on V30MZ PUSH(I.regs.w[BP]); I.regs.w[BP]=I.regs.w[SP]; I.regs.w[SP] -= nb; for (i=1;i0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x08: do { ROR_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x10: do { ROLC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x18: do { RORC_uint8; c--; } while (c>0); PutbackRMByte(ModRM,(uint8)dst); break; case 0x20: SHL_uint8(c); I.AuxVal = 1; break; case 0x28: SHR_uint8(c); I.AuxVal = 1;break; case 0x30: break; case 0x38: SHRA_uint8(c); break; } } OP_EPILOGUE; OP( 0xd3, i_rotshft_wcl ) { uint32 src, dst; uint8 c; GetModRM; src = (uint32)GetRMWord(ModRM); dst=src; c=I.regs.b[CL]; c&=0x1f; CLKM(5,3); if (c) switch (ModRM & 0x38) { case 0x00: do { ROL_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x08: do { ROR_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x10: do { ROLC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x18: do { RORC_uint16; c--; } while (c>0); PutbackRMWord(ModRM,(uint16)dst); break; case 0x20: SHL_uint16(c); I.AuxVal = 1; break; case 0x28: SHR_uint16(c); I.AuxVal = 1; break; case 0x30: break; case 0x38: SHRA_uint16(c); break; } } OP_EPILOGUE; OP( 0xd4, i_aam ) { uint32 mult=FETCH; mult=0; I.regs.b[AH] = I.regs.b[AL] / 10; I.regs.b[AL] %= 10; SetSZPF_Word(I.regs.w[AW]); CLK(17); } OP_EPILOGUE; OP( 0xd5, i_aad ) { uint32 mult=FETCH; mult=0; I.regs.b[AL] = I.regs.b[AH] * 10 + I.regs.b[AL]; I.regs.b[AH] = 0; SetSZPF_Byte(I.regs.b[AL]); CLK(6); } OP_EPILOGUE; OP( 0xd6, i_setalc ) { I.regs.b[AL] = (CF)?0xff:0x00; CLK(3); } OP_EPILOGUE; OP( 0xd7, i_trans ) { uint32 dest = (I.regs.w[BW]+I.regs.b[AL])&0xffff; I.regs.b[AL] = GetMemB(DS0, dest); CLK(5); } OP_EPILOGUE; case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: { GetModRM; CLK(1); } OP_EPILOGUE; OP( 0xe0, i_loopne ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if (!ZF && I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(3); } OP_EPILOGUE; OP( 0xe1, i_loope ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if ( ZF && I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(6); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(3); } OP_EPILOGUE; OP( 0xe2, i_loop ) { int8 disp = (int8)FETCH; I.regs.w[CW]--; if (I.regs.w[CW]) { I.pc = (uint16)(I.pc+disp); CLK(5); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(2); } OP_EPILOGUE; OP( 0xe3, i_jcxz ) { int8 disp = (int8)FETCH; if (I.regs.w[CW] == 0) { I.pc = (uint16)(I.pc+disp); CLK(4); ADDBRANCHTRACE(I.sregs[PS], I.pc); } else CLK(1); } OP_EPILOGUE; OP( 0xe4, i_inal ) { uint8 port = FETCH; I.regs.b[AL] = read_port(port); CLK(6); } OP_EPILOGUE; OP( 0xe5, i_inax ) { uint8 port = FETCH; I.regs.b[AL] = read_port(port); I.regs.b[AH] = read_port(port+1); CLK(6); } OP_EPILOGUE; OP( 0xe6, i_outal ) { uint8 port = FETCH; write_port(port, I.regs.b[AL]); CLK(6); } OP_EPILOGUE; OP( 0xe7, i_outax ) { uint8 port = FETCH; write_port(port, I.regs.b[AL]); write_port(port+1, I.regs.b[AH]); CLK(6); } OP_EPILOGUE; OP( 0xe8, i_call_d16 ) { uint32 tmp; FETCHuint16(tmp); PUSH(I.pc); I.pc = (uint16)(I.pc+(int16)tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(5); } OP_EPILOGUE; OP( 0xe9, i_jmp_d16 ) { uint32 tmp; FETCHuint16(tmp); I.pc = (uint16)(I.pc+(int16)tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(4); } OP_EPILOGUE; OP( 0xea, i_jmp_far ) { uint32 tmp,tmp1; FETCHuint16(tmp); FETCHuint16(tmp1); I.sregs[PS] = (uint16)tmp1; I.pc = (uint16)tmp; ; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLK(7); } OP_EPILOGUE; OP( 0xeb, i_jmp_d8 ) { int tmp = (int)((int8)FETCH); CLK(4);I.pc = (uint16)(I.pc+tmp); ADDBRANCHTRACE(I.sregs[PS], I.pc); } OP_EPILOGUE; OP( 0xec, i_inaldx ) { I.regs.b[AL] = read_port(I.regs.w[DW]); CLK(6);} OP_EPILOGUE; OP( 0xed, i_inaxdx ) { uint32 port = I.regs.w[DW]; I.regs.b[AL] = read_port(port); I.regs.b[AH] = read_port(port+1); CLK(6); } OP_EPILOGUE; OP( 0xee, i_outdxal ) { write_port(I.regs.w[DW], I.regs.b[AL]); CLK(6); } OP_EPILOGUE; OP( 0xef, i_outdxax ) { uint32 port = I.regs.w[DW]; write_port(port, I.regs.b[AL]); write_port(port+1, I.regs.b[AH]); CLK(6); } OP_EPILOGUE; // NEC calls it "BUSLOCK" OP( 0xf0, i_lock ) { CLK(1); DoOP(FETCHOP); } OP_EPILOGUE; // We put CHK_ICOUNT *after* the first iteration has completed, to match real behavior. #define CHK_ICOUNT(cond) if(v30mz_ICount < 0 && (cond)) { I.pc -= seg_prefix ? 3 : 2; break; } OP( 0xf2, i_repne ) { uint32 next = FETCHOP; switch(next) { /* Segments */ case 0x26: seg_prefix=true; prefix_base=I.sregs[DS1]<<4; next = FETCHOP; CLK(2); break; case 0x2e: seg_prefix=true; prefix_base=I.sregs[PS]<<4; next = FETCHOP; CLK(2); break; case 0x36: seg_prefix=true; prefix_base=I.sregs[SS]<<4; next = FETCHOP; CLK(2); break; case 0x3e: seg_prefix=true; prefix_base=I.sregs[DS0]<<4; next = FETCHOP; CLK(2); break; } switch(next) { case 0x6c: CLK(5); if (I.regs.w[CW]) do { i_real_insb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0x6d: CLK(5); if (I.regs.w[CW]) do { i_real_insw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0x6e: CLK(5); if (I.regs.w[CW]) do { i_real_outsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0x6f: CLK(5); if (I.regs.w[CW]) do { i_real_outsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xa4: CLK(5); if (I.regs.w[CW]) do { i_real_movsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xa5: CLK(5); if (I.regs.w[CW]) do { i_real_movsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xa6: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsb(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 0); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==0); break; case 0xa7: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsw(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 0); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==0); break; case 0xaa: CLK(5); if (I.regs.w[CW]) do { i_real_stosb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xab: CLK(5); if (I.regs.w[CW]) do { i_real_stosw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xac: CLK(5); if (I.regs.w[CW]) do { i_real_lodsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xad: CLK(5); if (I.regs.w[CW]) do { i_real_lodsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xae: CLK(5); if (I.regs.w[CW]) do { i_real_scasb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 0); } while (I.regs.w[CW]>0 && ZF==0); break; case 0xaf: CLK(5); if (I.regs.w[CW]) do { i_real_scasw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 0); } while (I.regs.w[CW]>0 && ZF==0); break; default: DoOP(next); break; } seg_prefix=false; } OP_EPILOGUE; OP( 0xf3, i_repe) { uint32 next = FETCHOP; switch(next) { /* Segments */ case 0x26: seg_prefix=true; prefix_base=I.sregs[DS1]<<4; next = FETCHOP; CLK(2); break; case 0x2e: seg_prefix=true; prefix_base=I.sregs[PS]<<4; next = FETCHOP; CLK(2); break; case 0x36: seg_prefix=true; prefix_base=I.sregs[SS]<<4; next = FETCHOP; CLK(2); break; case 0x3e: seg_prefix=true; prefix_base=I.sregs[DS0]<<4; next = FETCHOP; CLK(2); break; } switch(next) { case 0x6c: CLK(5); if (I.regs.w[CW]) do { i_real_insb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0x6d: CLK(5); if (I.regs.w[CW]) do { i_real_insw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0x6e: CLK(5); if (I.regs.w[CW]) do { i_real_outsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0x6f: CLK(5); if (I.regs.w[CW]) do { i_real_outsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xa4: CLK(5); if (I.regs.w[CW]) do { i_real_movsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xa5: CLK(5); if (I.regs.w[CW]) do { i_real_movsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xa6: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsb(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 1); /* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==1); break; case 0xa7: CLK(5); if (I.regs.w[CW]) do { i_real_cmpsw(); I.regs.w[CW]--; CLK(3); CHK_ICOUNT(I.regs.w[CW] && ZF == 1);/* 6 + 3 = 9 */ } while (I.regs.w[CW]>0 && ZF==1); break; case 0xaa: CLK(5); if (I.regs.w[CW]) do { i_real_stosb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xab: CLK(5); if (I.regs.w[CW]) do { i_real_stosw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xac: CLK(5); if (I.regs.w[CW]) do { i_real_lodsb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xad: CLK(5); if (I.regs.w[CW]) do { i_real_lodsw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW]); } while (I.regs.w[CW]>0); break; case 0xae: CLK(5); if (I.regs.w[CW]) do { i_real_scasb(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 1); } while (I.regs.w[CW]>0 && ZF==1); break; case 0xaf: CLK(5); if (I.regs.w[CW]) do { i_real_scasw(); I.regs.w[CW]--; CHK_ICOUNT(I.regs.w[CW] && ZF == 1); } while (I.regs.w[CW]>0 && ZF==1); break; default: DoOP(next); break; } seg_prefix=false; } OP_EPILOGUE; OP( 0xf4, i_hlt ) { InHLT = true; CheckInHLT(); } OP_EPILOGUE; OP( 0xf5, i_cmc ) { I.CarryVal = !CF; CLK(4); } OP_EPILOGUE; OP( 0xf6, i_f6pre ) { uint32 tmp; uint32 uresult,uresult2; int32 result,result2; GetModRM; tmp = GetRMByte(ModRM); switch (ModRM & 0x38) { case 0x00: tmp &= FETCH; I.CarryVal = I.OverVal = I.AuxVal=0; SetSZPF_Byte(tmp); CLKM(2,1); break; /* TEST */ case 0x08: break; case 0x10: PutbackRMByte(ModRM,~tmp); CLKM(3,1); break; /* NOT */ case 0x18: I.CarryVal=(tmp!=0);tmp=(~tmp)+1; SetSZPF_Byte(tmp); PutbackRMByte(ModRM,tmp&0xff); CLKM(3,1); break; /* NEG */ case 0x20: uresult = I.regs.b[AL]*tmp; I.regs.w[AW]=(uint16)uresult; I.CarryVal=I.OverVal=(I.regs.b[AH]!=0); CLKM(4,3); break; /* MULU */ case 0x28: result = (int16)((int8)I.regs.b[AL])*(int16)((int8)tmp); I.regs.w[AW]=(uint16)result; I.CarryVal=I.OverVal=(I.regs.b[AH]!=0); CLKM(4,3); break; /* MUL */ case 0x30: if (tmp) { DIVUB; } else nec_interrupt(0); CLKM(16,15); break; case 0x38: if (tmp) { DIVB; } else nec_interrupt(0); CLKM(18,17); break; } } OP_EPILOGUE; OP( 0xf7, i_f7pre ) { uint32 tmp,tmp2; uint32 uresult,uresult2; int32 result,result2; GetModRM; tmp = GetRMWord(ModRM); switch (ModRM & 0x38) { case 0x00: FETCHuint16(tmp2); tmp &= tmp2; I.CarryVal = I.OverVal = I.AuxVal=0; SetSZPF_Word(tmp); CLKM(2,1); break; /* TEST */ case 0x08: break; case 0x10: PutbackRMWord(ModRM,~tmp); CLKM(3,1); break; /* NOT */ case 0x18: I.CarryVal=(tmp!=0); tmp=(~tmp)+1; SetSZPF_Word(tmp); PutbackRMWord(ModRM,tmp&0xffff); CLKM(3,1); break; /* NEG */ case 0x20: uresult = I.regs.w[AW]*tmp; I.regs.w[AW]=uresult&0xffff; I.regs.w[DW]=((uint32)uresult)>>16; I.CarryVal=I.OverVal=(I.regs.w[DW]!=0); CLKM(4,3); break; /* MULU */ case 0x28: result = (int32)((int16)I.regs.w[AW])*(int32)((int16)tmp); I.regs.w[AW]=result&0xffff; I.regs.w[DW]=result>>16; I.CarryVal=I.OverVal=(I.regs.w[DW]!=0); CLKM(4,3); break; /* MUL */ case 0x30: if (tmp) { DIVUW; } else nec_interrupt(0); CLKM(24,23); break; case 0x38: if (tmp) { DIVW; } else nec_interrupt(0); CLKM(25,24); break; } } OP_EPILOGUE; OP( 0xf8, i_clc ) { I.CarryVal = 0; CLK(4); } OP_EPILOGUE; OP( 0xf9, i_stc ) { I.CarryVal = 1; CLK(4); } OP_EPILOGUE; OP( 0xfa, i_di ) { SetIF(0); CLK(4); } OP_EPILOGUE; OP( 0xfb, i_ei ) { SetIF(1); CLK(4); } OP_EPILOGUE; OP( 0xfc, i_cld ) { SetDF(0); CLK(4); } OP_EPILOGUE; OP( 0xfd, i_std ) { SetDF(1); CLK(4); } OP_EPILOGUE; OP( 0xfe, i_fepre ) { uint32 tmp, tmp1; GetModRM; tmp=GetRMByte(ModRM); switch(ModRM & 0x38) { case 0x00: tmp1 = tmp+1; I.OverVal = (tmp==0x7f); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(uint8)tmp1); CLKM(3,1); break; /* INC */ case 0x08: tmp1 = tmp-1; I.OverVal = (tmp==0x80); SetAF(tmp1,tmp,1); SetSZPF_Byte(tmp1); PutbackRMByte(ModRM,(uint8)tmp1); CLKM(3,1); break; /* DEC */ } } OP_EPILOGUE; OP( 0xff, i_ffpre ) { uint32 tmp, tmp1; GetModRM; tmp=GetRMWord(ModRM); switch(ModRM & 0x38) { case 0x00: tmp1 = tmp+1; I.OverVal = (tmp==0x7fff); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(uint16)tmp1); CLKM(3,1); break; /* INC */ case 0x08: tmp1 = tmp-1; I.OverVal = (tmp==0x8000); SetAF(tmp1,tmp,1); SetSZPF_Word(tmp1); PutbackRMWord(ModRM,(uint16)tmp1); CLKM(3,1); break; /* DEC */ case 0x10: PUSH(I.pc); I.pc = (uint16)tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(6,5); break; /* CALL */ case 0x18: tmp1 = I.sregs[PS]; I.sregs[PS] = GetnextRMWord; PUSH(tmp1); PUSH(I.pc); I.pc = tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(12,1); break; /* CALL FAR */ case 0x20: I.pc = tmp; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(5,4); break; /* JMP */ case 0x28: I.pc = tmp; I.sregs[PS] = GetnextRMWord; ADDBRANCHTRACE(I.sregs[PS], I.pc); CLKM(10,1); break; /* JMP FAR */ case 0x30: PUSH(tmp); CLKM(2,1); break; } } OP_EPILOGUE; } // End switch statement } // End func /*****************************************************************************/ unsigned v30mz_get_reg(int regnum) { switch( regnum ) { case NEC_PC: return I.pc; case NEC_SP: return I.regs.w[SP]; case NEC_FLAGS: return CompressFlags(); case NEC_AW: return I.regs.w[AW]; case NEC_CW: return I.regs.w[CW]; case NEC_DW: return I.regs.w[DW]; case NEC_BW: return I.regs.w[BW]; case NEC_BP: return I.regs.w[BP]; case NEC_IX: return I.regs.w[IX]; case NEC_IY: return I.regs.w[IY]; case NEC_DS1: return I.sregs[DS1]; case NEC_PS: return I.sregs[PS]; case NEC_SS: return I.sregs[SS]; case NEC_DS0: return I.sregs[DS0]; } return 0; } void nec_set_irq_line(int irqline, int state); void v30mz_set_reg(int regnum, unsigned val) { switch( regnum ) { case NEC_PC: I.pc = val; break; case NEC_SP: I.regs.w[SP] = val; break; case NEC_FLAGS: ExpandFlags(val); break; case NEC_AW: I.regs.w[AW] = val; break; case NEC_CW: I.regs.w[CW] = val; break; case NEC_DW: I.regs.w[DW] = val; break; case NEC_BW: I.regs.w[BW] = val; break; case NEC_BP: I.regs.w[BP] = val; break; case NEC_IX: I.regs.w[IX] = val; break; case NEC_IY: I.regs.w[IY] = val; break; case NEC_DS1: I.sregs[DS1] = val; break; case NEC_PS: I.sregs[PS] = val; break; case NEC_SS: I.sregs[SS] = val; break; case NEC_DS0: I.sregs[DS0] = val; break; } } #ifdef WANT_DEBUGGER static void (*save_cpu_writemem20)(uint32,uint8); static uint8 (*save_cpu_readport)(uint32); static void (*save_cpu_writeport)(uint32, uint8); static uint8 (*save_cpu_readmem20)(uint32); static void test_cpu_writemem20(uint32 A, uint8 V) { if(write_hook) write_hook(A, V); } static uint8 test_cpu_readmem20(uint32 A) { if(read_hook) return(read_hook(A)); else return(save_cpu_readmem20(A)); } static void test_cpu_writeport(uint32 A, uint8 V) { if(port_write_hook) port_write_hook(A, V); } static uint8 test_cpu_readport(uint32 A) { if(port_read_hook) return(port_read_hook(A)); else return(save_cpu_readport(A)); } #endif void v30mz_execute(int cycles) { v30mz_ICount += cycles; if(InHLT) { SETOLDCSIP(); WSwan_InterruptCheck(); if(InHLT) { int32 tmp = v30mz_ICount; if(tmp > 0) CLK(tmp); #ifdef WANT_DEBUGGER if(cpu_hook) cpu_hook(I.pc); #endif return; } } while(v30mz_ICount > 0) { SETOLDCSIP(); WSwan_InterruptCheck(); #ifdef WANT_DEBUGGER if(hookie_hickey) { uint32 save_timestamp = v30mz_timestamp; int32 save_ICount = v30mz_ICount; v30mz_regs_t save_I = I; uint32 save_prefix_base = prefix_base; char save_seg_prefix = seg_prefix; void (*save_branch_trace_hook)(uint16 from_CS, uint16 from_IP, uint16 to_CS, uint16 to_IP, bool interrupt) = branch_trace_hook; branch_trace_hook = NULL; save_cpu_writemem20 = cpu_writemem20; save_cpu_readport = cpu_readport; save_cpu_writeport = cpu_writeport; save_cpu_readmem20 = cpu_readmem20; cpu_writemem20 = test_cpu_writemem20; cpu_readmem20 = test_cpu_readmem20; cpu_writeport = test_cpu_writeport; cpu_readport = test_cpu_readport; DoOP(FETCHOP); branch_trace_hook = save_branch_trace_hook; v30mz_timestamp = save_timestamp; v30mz_ICount = save_ICount; I = save_I; prefix_base = save_prefix_base; seg_prefix = save_seg_prefix; cpu_readmem20 = save_cpu_readmem20; cpu_writemem20 = save_cpu_writemem20; cpu_readport = save_cpu_readport; cpu_writeport = save_cpu_writeport; InHLT = false; } if(cpu_hook) cpu_hook(I.pc); #endif DoOP(FETCHOP); } } #ifdef WANT_DEBUGGER void v30mz_debug(void (*CPUHook)(uint32), uint8 (*ReadHook)(uint32), void (*WriteHook)(uint32, uint8), uint8 (*PortReadHook)(uint32), void (*PortWriteHook)(uint32, uint8), void (*BranchTraceHook)(uint16 from_CS, uint16 from_IP, uint16 to_CS, uint16 to_IP, bool interrupt)) { cpu_hook = CPUHook; read_hook = ReadHook; write_hook = WriteHook; port_read_hook = PortReadHook; port_write_hook = PortWriteHook; hookie_hickey = read_hook || write_hook || port_read_hook || port_write_hook; branch_trace_hook = BranchTraceHook; } #endif int v30mz_StateAction(StateMem *sm, int load, int data_only) { uint16 PSW; SFORMAT StateRegs[] = { SFVARN(I.pc, "IP"), SFARRAY16N(I.regs.w, 8, "regs"), SFARRAY16N(I.sregs, 4, "sregs"), SFVARN(v30mz_ICount, "ICount"), SFVARN(InHLT, "InHLT"), SFVARN(prefix_base, "prefix_base"), SFVARN(seg_prefix, "seg_prefix"), SFVAR(PSW), SFEND }; PSW = CompressFlags(); if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, "V30")) return(0); if(load) { ExpandFlags(PSW); } return(1); } libretro.cpp000755 001750 001750 00000057147 12733066400 014250 0ustar00sergiosergio000000 000000 #include "mednafen/mednafen.h" #include "mednafen/mempatcher.h" #include "mednafen/git.h" #include "mednafen/general.h" #include "libretro.h" static MDFNGI *game; struct retro_perf_callback perf_cb; retro_get_cpu_features_t perf_get_cpu_features_cb = NULL; retro_log_printf_t log_cb; static retro_video_refresh_t video_cb; static retro_audio_sample_t audio_cb; static retro_audio_sample_batch_t audio_batch_cb; static retro_environment_t environ_cb; static retro_input_poll_t input_poll_cb; static retro_input_state_t input_state_cb; static bool overscan; static double last_sound_rate; static MDFN_Surface *surf; static bool failed_init; std::string retro_base_directory; std::string retro_base_name; std::string retro_save_directory; static void set_basename(const char *path) { const char *base = strrchr(path, '/'); if (!base) base = strrchr(path, '\\'); if (base) retro_base_name = base + 1; else retro_base_name = path; retro_base_name = retro_base_name.substr(0, retro_base_name.find_last_of('.')); } /* Cygne * * Copyright notice for this file: * Copyright (C) 2002 Dox dox@space.pl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mednafen/wswan/wswan.h" #include "mednafen/mempatcher.h" #include #include "mednafen/wswan/gfx.h" #include "mednafen/wswan/wswan-memory.h" #include "mednafen/wswan/start.inc" #include "mednafen/wswan/sound.h" #include "mednafen/wswan/v30mz.h" #include "mednafen/wswan/rtc.h" #include "mednafen/wswan/eeprom.h" #include "mednafen/wswan/debug.h" int wsc = 1; /*color/mono*/ uint32 rom_size; uint16 WSButtonStatus; static uint8 WSRCurrentSong; static void Reset(void) { int u0; v30mz_reset(); /* Reset CPU */ WSwan_MemoryReset(); WSwan_GfxReset(); WSwan_SoundReset(); WSwan_InterruptReset(); WSwan_RTCReset(); WSwan_EEPROMReset(); for(u0=0;u0<0xc9;u0++) { if(u0 != 0xC4 && u0 != 0xC5 && u0 != 0xBA && u0 != 0xBB) WSwan_writeport(u0,startio[u0]); } v30mz_set_reg(NEC_SS,0); v30mz_set_reg(NEC_SP,0x2000); } static uint8 *chee; static void Emulate(EmulateSpecStruct *espec) { espec->DisplayRect.x = 0; espec->DisplayRect.y = 0; espec->DisplayRect.w = 224; espec->DisplayRect.h = 144; if(espec->SoundFormatChanged) WSwan_SetSoundRate(espec->SoundRate); uint16 butt_data = chee[0] | (chee[1] << 8); WSButtonStatus = butt_data; MDFNMP_ApplyPeriodicCheats(); while(!wsExecuteLine(espec->surface, espec->skip)) { } espec->SoundBufSize = WSwan_SoundFlush(espec->SoundBuf, espec->SoundBufMaxSize); espec->MasterCycles = v30mz_timestamp; v30mz_timestamp = 0; } typedef struct { const uint8 id; const char *name; } DLEntry; static const DLEntry Developers[] = { { 0x01, "Bandai" }, { 0x02, "Taito" }, { 0x03, "Tomy" }, { 0x04, "Koei" }, { 0x05, "Data East" }, { 0x06, "Asmik" }, // Asmik Ace? { 0x07, "Media Entertainment" }, { 0x08, "Nichibutsu" }, { 0x0A, "Coconuts Japan" }, { 0x0B, "Sammy" }, { 0x0C, "Sunsoft" }, { 0x0D, "Mebius" }, { 0x0E, "Banpresto" }, { 0x10, "Jaleco" }, { 0x11, "Imagineer" }, { 0x12, "Konami" }, { 0x16, "Kobunsha" }, { 0x17, "Bottom Up" }, { 0x18, "Naxat" }, // Mechanic Arms? Media Entertainment? Argh! { 0x19, "Sunrise" }, { 0x1A, "Cyberfront" }, { 0x1B, "Megahouse" }, { 0x1D, "Interbec" }, { 0x1E, "NAC" }, { 0x1F, "Emotion" }, // Bandai Visual?? { 0x20, "Athena" }, { 0x21, "KID" }, { 0x24, "Omega Micott" }, { 0x25, "Upstar" }, { 0x26, "Kadokawa/Megas" }, { 0x27, "Cocktail Soft" }, { 0x28, "Squaresoft" }, { 0x2B, "TomCreate" }, { 0x2D, "Namco" }, { 0x2F, "Gust" }, { 0x36, "Capcom" }, }; static bool TestMagic(const char *name, MDFNFILE *fp) { if(strcasecmp(GET_FEXTS_PTR(fp), "ws") && strcasecmp(GET_FEXTS_PTR(fp), "wsc") && strcasecmp(GET_FEXTS_PTR(fp), "wsr")) return(false); if(GET_FSIZE_PTR(fp) < 65536) return(false); return(true); } static int Load(const char *name, MDFNFILE *fp) { uint32 real_rom_size; uint8 header[10]; if(GET_FSIZE_PTR(fp) < 65536) return(0); real_rom_size = (GET_FSIZE_PTR(fp) + 0xFFFF) & ~0xFFFF; rom_size = round_up_pow2(real_rom_size); //fp->size); wsCartROM = (uint8 *)calloc(1, rom_size); // This real_rom_size vs rom_size funny business is intended primarily for handling // WSR files. if(real_rom_size < rom_size) memset(wsCartROM, 0xFF, rom_size - real_rom_size); memcpy(wsCartROM + (rom_size - real_rom_size), GET_FDATA_PTR(fp), GET_FSIZE_PTR(fp)); memcpy(header, wsCartROM + rom_size - 10, 10); { const char *developer_name = "???"; for(unsigned int x = 0; x < sizeof(Developers) / sizeof(DLEntry); x++) { if(Developers[x].id == header[0]) { developer_name = Developers[x].name; break; } } printf(_("Developer: %s (0x%02x)\n"), developer_name, header[0]); } uint32 SRAMSize = 0; eeprom_size = 0; switch(header[5]) { case 0x01: SRAMSize = 8*1024; break; case 0x02: SRAMSize = 32*1024; break; case 0x03: SRAMSize = 16 * 65536; break; case 0x04: SRAMSize = 32 * 65536; break; // Dicing Knight! case 0x10: eeprom_size = 128; break; case 0x20: eeprom_size = 2*1024; break; case 0x50: eeprom_size = 1024; break; } { uint16 real_crc = 0; for(unsigned int i = 0; i < rom_size - 2; i++) real_crc += wsCartROM[i]; printf(_("Real Checksum: 0x%04x\n"), real_crc); } if((header[8] | (header[9] << 8)) == 0x8de1 && (header[0]==0x01)&&(header[2]==0x27)) /* Detective Conan */ { //puts("HAX"); /* WS cpu is using cache/pipeline or there's protected ROM bank where pointing CS */ wsCartROM[0xfffe8]=0xea; wsCartROM[0xfffe9]=0x00; wsCartROM[0xfffea]=0x00; wsCartROM[0xfffeb]=0x00; wsCartROM[0xfffec]=0x20; } { if(header[6] & 0x1) MDFNGameInfo->rotated = MDFN_ROTATE90; } MDFNMP_Init(16384, (1 << 20) / 1024); v30mz_init(WSwan_readmem20, WSwan_writemem20, WSwan_readport, WSwan_writeport); WSwan_MemoryInit(MDFN_GetSettingB("wswan.language"), wsc, SRAMSize, false); // EEPROM and SRAM are loaded in this func. WSwan_GfxInit(); MDFNGameInfo->fps = (uint32)((uint64)3072000 * 65536 * 256 / (159*256)); WSwan_SoundInit(); wsMakeTiles(); Reset(); return(1); } static void CloseGame(void) { WSwan_MemoryKill(); // saves sram/eeprom WSwan_SoundKill(); if(wsCartROM) { free(wsCartROM); wsCartROM = NULL; } } static void SetInput(int port, const char *type, void *ptr) { if(!port) chee = (uint8 *)ptr; } static int StateAction(StateMem *sm, int load, int data_only) { if(!v30mz_StateAction(sm, load, data_only)) return(0); // Call MemoryStateAction before others StateActions... if(!WSwan_MemoryStateAction(sm, load, data_only)) return(0); if(!WSwan_GfxStateAction(sm, load, data_only)) return(0); if(!WSwan_RTCStateAction(sm, load, data_only)) return(0); if(!WSwan_InterruptStateAction(sm, load, data_only)) return(0); if(!WSwan_SoundStateAction(sm, load, data_only)) return(0); if(!WSwan_EEPROMStateAction(sm, load, data_only)) { puts("Oops"); return(0); } return(1); } static void DoSimpleCommand(int cmd) { switch(cmd) { case MDFN_MSC_POWER: case MDFN_MSC_RESET: Reset(); break; } } static const MDFNSetting_EnumList SexList[] = { { "m", WSWAN_SEX_MALE }, { "male", WSWAN_SEX_MALE, "Male" }, { "f", WSWAN_SEX_FEMALE }, { "female", WSWAN_SEX_FEMALE, "Female" }, { "3", 3 }, { NULL, 0 }, }; static const MDFNSetting_EnumList BloodList[] = { { "a", WSWAN_BLOOD_A, "A" }, { "b", WSWAN_BLOOD_B, "B" }, { "o", WSWAN_BLOOD_O, "O" }, { "ab", WSWAN_BLOOD_AB, "AB" }, { "5", 5 }, { NULL, 0 }, }; static const MDFNSetting_EnumList LanguageList[] = { { "japanese", 0, "Japanese" }, { "0", 0 }, { "english", 1, "English" }, { "1", 1 }, { NULL, 0 }, }; static const MDFNSetting WSwanSettings[] = { { "wswan.rotateinput", MDFNSF_NOFLAGS, "Virtually rotate D-pads along with screen.", NULL, MDFNST_BOOL, "0" }, { "wswan.language", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Language games should display text in.", "The only game this setting is known to affect is \"Digimon Tamers - Battle Spirit\".", MDFNST_ENUM, "english", NULL, NULL, NULL, NULL, LanguageList }, { "wswan.name", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Name", NULL, MDFNST_STRING, "Mednafen" }, { "wswan.byear", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Birth Year", NULL, MDFNST_UINT, "1989", "0", "9999" }, { "wswan.bmonth", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Birth Month", NULL, MDFNST_UINT, "6", "1", "12" }, { "wswan.bday", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Birth Day", NULL, MDFNST_UINT, "23", "1", "31" }, { "wswan.sex", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Sex", NULL, MDFNST_ENUM, "F", NULL, NULL, NULL, NULL, SexList }, { "wswan.blood", MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE, "Blood Type", NULL, MDFNST_ENUM, "O", NULL, NULL, NULL, NULL, BloodList }, { NULL } }; static const InputDeviceInputInfoStruct IDII[] = { { "up-x", "UP ↑, X Cursors", 0, IDIT_BUTTON, "down-x", { "right-x", "down-x", "left-x" } }, { "right-x", "RIGHT →, X Cursors", 3, IDIT_BUTTON, "left-x", { "down-x", "left-x", "up-x" } }, { "down-x", "DOWN ↓, X Cursors", 1, IDIT_BUTTON, "up-x", { "left-x", "up-x", "right-x" } }, { "left-x", "LEFT ←, X Cursors", 2, IDIT_BUTTON, "right-x", { "up-x", "right-x", "down-x" } }, { "up-y", "UP ↑, Y Cur: MUST NOT = X CURSORS", 4, IDIT_BUTTON, "down-y", { "right-y", "down-y", "left-y" } }, { "right-y", "RIGHT →, Y Cur: MUST NOT = X CURSORS", 7, IDIT_BUTTON, "left-y", { "down-y", "left-y", "up-y" } }, { "down-y", "DOWN ↓, Y Cur: MUST NOT = X CURSORS", 5, IDIT_BUTTON, "up-y", { "left-y", "up-y", "right-y" } }, { "left-y", "LEFT ←, Y Cur: MUST NOT = X CURSORS", 6, IDIT_BUTTON, "right-y", { "up-y", "right-y", "down-y" } }, { "start", "Start", 8, IDIT_BUTTON, NULL }, { "a", "A", 10, IDIT_BUTTON_CAN_RAPID, NULL }, { "b", "B", 9, IDIT_BUTTON_CAN_RAPID, NULL }, }; static InputDeviceInfoStruct InputDeviceInfo[] = { { "gamepad", "Gamepad", NULL, NULL, sizeof(IDII) / sizeof(InputDeviceInputInfoStruct), IDII, } }; static const InputPortInfoStruct PortInfo[] = { { "builtin", "Built-In", sizeof(InputDeviceInfo) / sizeof(InputDeviceInfoStruct), InputDeviceInfo, "gamepad" } }; static InputInfoStruct InputInfo = { sizeof(PortInfo) / sizeof(InputPortInfoStruct), PortInfo }; static const FileExtensionSpecStruct KnownExtensions[] = { { ".ws", "WonderSwan ROM Image" }, { ".wsc", "WonderSwan Color ROM Image" }, { ".wsr", "WonderSwan Music Rip" }, { NULL, NULL } }; MDFNGI EmulatedWSwan = { "wswan", "WonderSwan", KnownExtensions, MODPRIO_INTERNAL_HIGH, NULL, &InputInfo, Load, TestMagic, NULL, NULL, CloseGame, WSwan_SetLayerEnableMask, "Background\0Foreground\0Sprites\0", NULL, NULL, NULL, NULL, NULL, NULL, false, StateAction, Emulate, SetInput, DoSimpleCommand, WSwanSettings, MDFN_MASTERCLOCK_FIXED(3072000), 0, false, // Multires possible? 224, // lcm_width 144, // lcm_height NULL, // Dummy 224, // Nominal width 144, // Nominal height 224, // Framebuffer width 144, // Framebuffer height 2, // Number of output sound channels }; #define MEDNAFEN_CORE_NAME_MODULE "wswan" #define MEDNAFEN_CORE_NAME "Mednafen WonderSwan" #define MEDNAFEN_CORE_VERSION "v0.9.35.1" #define MEDNAFEN_CORE_EXTENSIONS "ws|wsc" #define MEDNAFEN_CORE_TIMING_FPS 75.47 #define MEDNAFEN_CORE_GEOMETRY_BASE_W (game->nominal_width) #define MEDNAFEN_CORE_GEOMETRY_BASE_H (game->nominal_height) #define MEDNAFEN_CORE_GEOMETRY_MAX_W 224 #define MEDNAFEN_CORE_GEOMETRY_MAX_H 144 #define MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO (4.0 / 3.0) #define FB_WIDTH 224 #define FB_HEIGHT 144 #define FB_MAX_HEIGHT FB_HEIGHT static void check_system_specs(void) { // TODO - should theoretically be level 4, but apparently // doesn't run at fullspeed on PSP (yet) unsigned level = 4; environ_cb(RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL, &level); } void retro_init(void) { struct retro_log_callback log; if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log)) log_cb = log.log; else log_cb = NULL; const char *dir = NULL; if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir) { retro_base_directory = dir; // Make sure that we don't have any lingering slashes, etc, as they break Windows. size_t last = retro_base_directory.find_last_not_of("/\\"); if (last != std::string::npos) last++; retro_base_directory = retro_base_directory.substr(0, last); } else { /* TODO: Add proper fallback */ if (log_cb) log_cb(RETRO_LOG_WARN, "System directory is not defined. Fallback on using same dir as ROM for system directory later ...\n"); failed_init = true; } if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir) { // If save directory is defined use it, otherwise use system directory // retro_save_directory = *dir ? dir : retro_base_directory; retro_save_directory = dir; // Make sure that we don't have any lingering slashes, etc, as they break Windows. size_t last = retro_save_directory.find_last_not_of("/\\"); if (last != std::string::npos) last++; retro_save_directory = retro_save_directory.substr(0, last); } else { /* TODO: Add proper fallback */ if (log_cb) log_cb(RETRO_LOG_WARN, "Save directory is not defined. Fallback on using SYSTEM directory ...\n"); retro_save_directory = retro_base_directory; } #if defined(WANT_16BPP) && defined(FRONTEND_SUPPORTS_RGB565) enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565; if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb565) && log_cb) log_cb(RETRO_LOG_INFO, "Frontend supports RGB565 - will use that instead of XRGB1555.\n"); #endif if (environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb)) perf_get_cpu_features_cb = perf_cb.get_cpu_features; else perf_get_cpu_features_cb = NULL; check_system_specs(); } void retro_reset(void) { game->DoSimpleCommand(MDFN_MSC_RESET); } bool retro_load_game_special(unsigned, const struct retro_game_info *, size_t) { return false; } static void set_volume (uint32_t *ptr, unsigned number) { switch(number) { default: *ptr = number; break; } } static void check_variables(void) { struct retro_variable var = {0}; } #define MAX_PLAYERS 1 #define MAX_BUTTONS 11 static uint16_t input_buf; bool retro_load_game(const struct retro_game_info *info) { if (failed_init) return false; struct retro_input_descriptor desc[] = { { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "X Cursor Left" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "X Cursor Up" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "X Cursor Down" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "X Cursor Right" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L, "Y Cursor Left" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R2, "Y Cursor Up" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L2, "Y Cursor Down" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_R, "Y Cursor Right" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "A" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "B" }, { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Start" }, { 0 }, }; environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc); overscan = false; environ_cb(RETRO_ENVIRONMENT_GET_OVERSCAN, &overscan); set_basename(info->path); game = MDFNI_LoadGame(MEDNAFEN_CORE_NAME_MODULE, info->path); if (!game) return false; game->SetInput(0, "gamepad", &input_buf); surf = (MDFN_Surface*)calloc(1, sizeof(*surf)); if (!surf) return false; surf->width = FB_WIDTH; surf->height = FB_HEIGHT; surf->pitch = FB_WIDTH; surf->pixels = (uint16_t*)calloc(1, FB_WIDTH * FB_HEIGHT * 2); if (!surf->pixels) { free(surf); return false; } check_variables(); WSwan_SetPixelFormat(); return game; } void retro_unload_game() { if (!game) return; MDFNI_CloseGame(); } // Hardcoded for PSX. No reason to parse lots of structures ... // See mednafen/psx/input/gamepad.cpp static void update_input(void) { MDFNGI *currgame = (MDFNGI*)game; input_buf = 0; static unsigned map[] = { RETRO_DEVICE_ID_JOYPAD_UP, //X Cursor horizontal-layout games RETRO_DEVICE_ID_JOYPAD_RIGHT, //X Cursor horizontal-layout games RETRO_DEVICE_ID_JOYPAD_DOWN, //X Cursor horizontal-layout games RETRO_DEVICE_ID_JOYPAD_LEFT, //X Cursor horizontal-layout games RETRO_DEVICE_ID_JOYPAD_R2, //Y Cursor UP vertical-layout games RETRO_DEVICE_ID_JOYPAD_R, //Y Cursor RIGHT vertical-layout games RETRO_DEVICE_ID_JOYPAD_L2, //Y Cursor DOWN vertical-layout games RETRO_DEVICE_ID_JOYPAD_L, //Y Cursor LEFT vertical-layout games RETRO_DEVICE_ID_JOYPAD_START, RETRO_DEVICE_ID_JOYPAD_A, RETRO_DEVICE_ID_JOYPAD_B, }; for (unsigned i = 0; i < MAX_BUTTONS; i++) input_buf |= map[i] != -1u && input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, map[i]) ? (1 << i) : 0; #ifdef MSB_FIRST union { uint8_t b[2]; uint16_t s; } u; u.s = input_buf; input_buf = u.b[0] | u.b[1] << 8; #endif } static uint64_t video_frames, audio_frames; void retro_run(void) { MDFNGI *curgame = game; input_poll_cb(); update_input(); static int16_t sound_buf[0x10000]; static MDFN_Rect rects[FB_MAX_HEIGHT]; rects[0].w = ~0; EmulateSpecStruct spec = {0}; spec.surface = surf; spec.SoundRate = 44100; spec.SoundBuf = sound_buf; spec.LineWidths = rects; spec.SoundBufMaxSize = sizeof(sound_buf) / 2; spec.SoundVolume = 1.0; spec.soundmultiplier = 1.0; spec.SoundBufSize = 0; spec.VideoFormatChanged = false; spec.SoundFormatChanged = false; if (spec.SoundRate != last_sound_rate) { spec.SoundFormatChanged = true; last_sound_rate = spec.SoundRate; } curgame->Emulate(&spec); int16 *const SoundBuf = spec.SoundBuf + spec.SoundBufSizeALMS * curgame->soundchan; int32 SoundBufSize = spec.SoundBufSize - spec.SoundBufSizeALMS; const int32 SoundBufMaxSize = spec.SoundBufMaxSize - spec.SoundBufSizeALMS; spec.SoundBufSize = spec.SoundBufSizeALMS + SoundBufSize; unsigned width = spec.DisplayRect.w; unsigned height = spec.DisplayRect.h; video_cb(surf->pixels, width, height, FB_WIDTH << 1); video_frames++; audio_frames += spec.SoundBufSize; audio_batch_cb(spec.SoundBuf, spec.SoundBufSize); bool updated = false; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) check_variables(); } void retro_get_system_info(struct retro_system_info *info) { memset(info, 0, sizeof(*info)); info->library_name = MEDNAFEN_CORE_NAME; info->library_version = MEDNAFEN_CORE_VERSION; info->need_fullpath = true; info->valid_extensions = MEDNAFEN_CORE_EXTENSIONS; info->block_extract = false; } void retro_get_system_av_info(struct retro_system_av_info *info) { memset(info, 0, sizeof(*info)); info->timing.fps = MEDNAFEN_CORE_TIMING_FPS; info->timing.sample_rate = 44100; info->geometry.base_width = MEDNAFEN_CORE_GEOMETRY_BASE_W; info->geometry.base_height = MEDNAFEN_CORE_GEOMETRY_BASE_H; info->geometry.max_width = MEDNAFEN_CORE_GEOMETRY_MAX_W; info->geometry.max_height = MEDNAFEN_CORE_GEOMETRY_MAX_H; info->geometry.aspect_ratio = MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO; } void retro_deinit(void) { if (surf) free(surf); surf = NULL; if (log_cb) { log_cb(RETRO_LOG_INFO, "[%s]: Samples / Frame: %.5f\n", MEDNAFEN_CORE_NAME, (double)audio_frames / video_frames); log_cb(RETRO_LOG_INFO, "[%s]: Estimated FPS: %.5f\n", MEDNAFEN_CORE_NAME, (double)video_frames * 44100 / audio_frames); } } unsigned retro_get_region(void) { return RETRO_REGION_NTSC; // FIXME: Regions for other cores. } unsigned retro_api_version(void) { return RETRO_API_VERSION; } void retro_set_controller_port_device(unsigned in_port, unsigned device) { } void retro_set_environment(retro_environment_t cb) { environ_cb = cb; } void retro_set_audio_sample(retro_audio_sample_t cb) { audio_cb = cb; } void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; } void retro_set_input_poll(retro_input_poll_t cb) { input_poll_cb = cb; } void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; } void retro_set_video_refresh(retro_video_refresh_t cb) { video_cb = cb; } static size_t serialize_size; size_t retro_serialize_size(void) { StateMem st; memset(&st, 0, sizeof(st)); if (!MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL)) return 0; free(st.data); return serialize_size = st.len; } bool retro_serialize(void *data, size_t size) { StateMem st; memset(&st, 0, sizeof(st)); st.data = (uint8_t*)data; st.malloced = size; return MDFNSS_SaveSM(&st, 0, 0, NULL, NULL, NULL); } bool retro_unserialize(const void *data, size_t size) { StateMem st; memset(&st, 0, sizeof(st)); st.data = (uint8_t*)data; st.len = size; return MDFNSS_LoadSM(&st, 0, 0); } void *retro_get_memory_data(unsigned) { return NULL; } size_t retro_get_memory_size(unsigned) { return 0; } void retro_cheat_reset(void) {} void retro_cheat_set(unsigned, bool, const char *) {} #ifdef _WIN32 static void sanitize_path(std::string &path) { size_t size = path.size(); for (size_t i = 0; i < size; i++) if (path[i] == '/') path[i] = '\\'; } #endif // Use a simpler approach to make sure that things go right for libretro. std::string MDFN_MakeFName(MakeFName_Type type, int id1, const char *cd1) { char slash; #ifdef _WIN32 slash = '\\'; #else slash = '/'; #endif std::string ret; switch (type) { case MDFNMKF_SAV: ret = retro_save_directory +slash + retro_base_name + std::string(".") + std::string(cd1); break; case MDFNMKF_FIRMWARE: ret = retro_base_directory + slash + std::string(cd1); #ifdef _WIN32 sanitize_path(ret); // Because Windows path handling is mongoloid. #endif break; default: break; } if (log_cb) log_cb(RETRO_LOG_INFO, "MDFN_MakeFName: %s\n", ret.c_str()); return ret; } void MDFND_DispMessage(unsigned char *str) { if (log_cb) log_cb(RETRO_LOG_INFO, "%s\n", str); } void MDFND_Message(const char *str) { if (log_cb) log_cb(RETRO_LOG_INFO, "%s\n", str); } void MDFND_MidSync(const EmulateSpecStruct *) {} void MDFN_MidLineUpdate(EmulateSpecStruct *espec, int y) { //MDFND_MidLineUpdate(espec, y); } void MDFND_PrintError(const char* err) { if (log_cb) log_cb(RETRO_LOG_ERROR, "%s\n", err); } mednafen/include/000700 001750 001750 00000000000 12733077034 015074 5ustar00sergiosergio000000 000000 mednafen/wswan/sound.h000664 001750 001750 00000000736 12733066400 016126 0ustar00sergiosergio000000 000000 #ifndef __WSWAN_SOUND_H #define __WSWAN_SOUND_H int32 WSwan_SoundFlush(int16 *SoundBuf, const int32 MaxSoundFrames); void WSwan_SoundInit(void); void WSwan_SoundKill(void); void WSwan_SetSoundMultiplier(double multiplier); bool WSwan_SetSoundRate(uint32 rate); int WSwan_SoundStateAction(StateMem *sm, int load, int data_only); void WSwan_SoundWrite(uint32, uint8); uint8 WSwan_SoundRead(uint32); void WSwan_SoundReset(void); void WSwan_SoundCheckRAMWrite(uint32 A); #endif msvc/msvc-2010-360.sln000664 001750 001750 00000003516 12733066400 015234 0ustar00sergiosergio000000 000000  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc-2010-360", "msvc-2010-360\msvc-2010-360.vcxproj", "{38462FE9-E3FC-4336-B241-50F5599C537B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution CodeAnalysis|Xbox 360 = CodeAnalysis|Xbox 360 Debug|Xbox 360 = Debug|Xbox 360 Profile_FastCap|Xbox 360 = Profile_FastCap|Xbox 360 Profile|Xbox 360 = Profile|Xbox 360 Release_LTCG|Xbox 360 = Release_LTCG|Xbox 360 Release|Xbox 360 = Release|Xbox 360 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {38462FE9-E3FC-4336-B241-50F5599C537B}.CodeAnalysis|Xbox 360.ActiveCfg = CodeAnalysis|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.CodeAnalysis|Xbox 360.Build.0 = CodeAnalysis|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Debug|Xbox 360.ActiveCfg = Debug|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Debug|Xbox 360.Build.0 = Debug|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Profile_FastCap|Xbox 360.ActiveCfg = Profile_FastCap|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Profile_FastCap|Xbox 360.Build.0 = Profile_FastCap|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Profile|Xbox 360.ActiveCfg = Profile|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Profile|Xbox 360.Build.0 = Profile|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Release_LTCG|Xbox 360.ActiveCfg = Release_LTCG|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Release_LTCG|Xbox 360.Build.0 = Release_LTCG|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Release|Xbox 360.ActiveCfg = Release|Xbox 360 {38462FE9-E3FC-4336-B241-50F5599C537B}.Release|Xbox 360.Build.0 = Release|Xbox 360 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal mednafen/mempatcher-driver.h000664 001750 001750 00000002533 12733066400 017252 0ustar00sergiosergio000000 000000 #ifndef __MDFN_MEMPATCHER_DRIVER_H #define __MDFN_MEMPATCHER_DRIVER_H int MDFNI_DecodePAR(const char *code, uint32 *a, uint8 *v, uint8 *c, char *type); int MDFNI_DecodeGG(const char *str, uint32 *a, uint8 *v, uint8 *c, char *type); int MDFNI_AddCheat(const char *name, uint32 addr, uint64 val, uint64 compare, char type, unsigned int length, bool bigendian); int MDFNI_DelCheat(uint32 which); int MDFNI_ToggleCheat(uint32 which); int32 MDFNI_CheatSearchGetCount(void); void MDFNI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current)); void MDFNI_CheatSearchGet(int (*callb)(uint32 a, uint64 last, uint64 current, void *data), void *data); void MDFNI_CheatSearchBegin(void); void MDFNI_CheatSearchEnd(int type, uint64 v1, uint64 v2, unsigned int bytelen, bool bigendian); void MDFNI_ListCheats(int (*callb)(char *name, uint32 a, uint64 v, uint64 compare, int s, char type, unsigned int length, bool bigendian, void *data), void *data); int MDFNI_GetCheat(uint32 which, char **name, uint32 *a, uint64 *v, uint64 *compare, int *s, char *type, unsigned int *length, bool *bigendian); int MDFNI_SetCheat(uint32 which, const char *name, uint32 a, uint64 v, uint64 compare, int s, char type, unsigned int length, bool bigendian); void MDFNI_CheatSearchShowExcluded(void); void MDFNI_CheatSearchSetCurrentAsOriginal(void); #endif mednafen/settings-driver.h000664 001750 001750 00000000606 12733066400 016764 0ustar00sergiosergio000000 000000 #ifndef _MDFN_SETTINGS_DRIVER_H #define _MDFN_SETTINGS_DRIVER_H #include #include #include "settings-common.h" bool MDFNI_SetSetting(const char *name, const char *value, bool NetplayOverride = false); bool MDFNI_SetSettingB(const char *name, bool value); bool MDFNI_SetSettingUI(const char *name, uint64 value); bool MDFNI_DumpSettingsDef(const char *path); #endif mednafen/mempatcher.cpp000664 001750 001750 00000026421 12733066400 016316 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mednafen.h" #include #include #include #include #include "general.h" #include "mempatcher.h" #ifdef _WIN32 #include "msvc_compat.h" #endif static uint8 **RAMPtrs = NULL; static uint32 PageSize; static uint32 NumPages; typedef struct __CHEATF { char *name; char *conditions; uint32 addr; uint64 val; uint64 compare; unsigned int length; bool bigendian; unsigned int icount; // Instance count char type; /* 'R' for replace, 'S' for substitute(GG), 'C' for substitute with compare */ int status; } CHEATF; static std::vector cheats; static int savecheats; static uint32 resultsbytelen = 1; static bool resultsbigendian = 0; static bool CheatsActive = true; bool SubCheatsOn = 0; std::vector SubCheats[8]; static void RebuildSubCheats(void) { std::vector::iterator chit; SubCheatsOn = 0; for(int x = 0; x < 8; x++) SubCheats[x].clear(); if(!CheatsActive) return; for(chit = cheats.begin(); chit != cheats.end(); chit++) { if(chit->status && chit->type != 'R') { for(unsigned int x = 0; x < chit->length; x++) { SUBCHEAT tmpsub; unsigned int shiftie; if(chit->bigendian) shiftie = (chit->length - 1 - x) * 8; else shiftie = x * 8; tmpsub.addr = chit->addr + x; tmpsub.value = (chit->val >> shiftie) & 0xFF; if(chit->type == 'C') tmpsub.compare = (chit->compare >> shiftie) & 0xFF; else tmpsub.compare = -1; SubCheats[(chit->addr + x) & 0x7].push_back(tmpsub); SubCheatsOn = 1; } } } } bool MDFNMP_Init(uint32 ps, uint32 numpages) { PageSize = ps; NumPages = numpages; RAMPtrs = (uint8 **)calloc(numpages, sizeof(uint8 *)); CheatsActive = MDFN_GetSettingB("cheats"); return(1); } void MDFNMP_Kill(void) { if(RAMPtrs) { free(RAMPtrs); RAMPtrs = NULL; } } void MDFNMP_AddRAM(uint32 size, uint32 A, uint8 *RAM) { uint32 AB = A / PageSize; size /= PageSize; for(unsigned int x = 0; x < size; x++) { RAMPtrs[AB + x] = RAM; if(RAM) // Don't increment the RAM pointer if we're passed a NULL pointer RAM += PageSize; } } void MDFNMP_InstallReadPatches(void) { if(!CheatsActive) return; std::vector::iterator chit; for(unsigned int x = 0; x < 8; x++) for(chit = SubCheats[x].begin(); chit != SubCheats[x].end(); chit++) { if(MDFNGameInfo->InstallReadPatch) MDFNGameInfo->InstallReadPatch(chit->addr); } } void MDFNMP_RemoveReadPatches(void) { if(MDFNGameInfo->RemoveReadPatches) MDFNGameInfo->RemoveReadPatches(); } /* This function doesn't allocate any memory for "name" */ static int AddCheatEntry(char *name, char *conditions, uint32 addr, uint64 val, uint64 compare, int status, char type, unsigned int length, bool bigendian) { CHEATF temp; memset(&temp, 0, sizeof(CHEATF)); temp.name=name; temp.conditions = conditions; temp.addr=addr; temp.val=val; temp.status=status; temp.compare=compare; temp.length = length; temp.bigendian = bigendian; temp.type=type; cheats.push_back(temp); return(1); } void MDFN_LoadGameCheats(void *override_ptr) { RebuildSubCheats(); } void MDFN_FlushGameCheats(int nosave) { std::vector::iterator chit; for(chit = cheats.begin(); chit != cheats.end(); chit++) { free(chit->name); if(chit->conditions) free(chit->conditions); } cheats.clear(); RebuildSubCheats(); } int MDFNI_AddCheat(const char *name, uint32 addr, uint64 val, uint64 compare, char type, unsigned int length, bool bigendian) { char *t; if(!(t = strdup(name))) return(0); if(!AddCheatEntry(t, NULL, addr,val,compare,1,type, length, bigendian)) { free(t); return(0); } savecheats = 1; MDFNMP_RemoveReadPatches(); RebuildSubCheats(); MDFNMP_InstallReadPatches(); return(1); } int MDFNI_DelCheat(uint32 which) { free(cheats[which].name); cheats.erase(cheats.begin() + which); savecheats=1; MDFNMP_RemoveReadPatches(); RebuildSubCheats(); MDFNMP_InstallReadPatches(); return(1); } /* Condition format(ws = white space):
[,second condition...etc.] Value should be unsigned integer, hex(with a 0x prefix) or base-10. Operations: >= <= > < == != & // Result of AND between two values is nonzero !& // Result of AND between two values is zero ^ // same, XOR !^ | // same, OR !| Full example: 2 L 0xADDE == 0xDEAD, 1 L 0xC000 == 0xA0 */ static bool TestConditions(const char *string) { char address[64]; char operation[64]; char value[64]; char endian; unsigned int bytelen; bool passed = 1; //printf("TR: %s\n", string); while(sscanf(string, "%u %c %63s %63s %63s", &bytelen, &endian, address, operation, value) == 5 && passed) { uint32 v_address; uint64 v_value; uint64 value_at_address; if(address[0] == '0' && address[1] == 'x') v_address = strtoul(address + 2, NULL, 16); else v_address = strtoul(address, NULL, 10); if(value[0] == '0' && value[1] == 'x') v_value = strtoull(value + 2, NULL, 16); else v_value = strtoull(value, NULL, 0); value_at_address = 0; for(unsigned int x = 0; x < bytelen; x++) { unsigned int shiftie; if(endian == 'B') shiftie = (bytelen - 1 - x) * 8; else shiftie = x * 8; value_at_address |= MDFNGameInfo->MemRead(v_address + x) << shiftie; } //printf("A: %08x, V: %08llx, VA: %08llx, OP: %s\n", v_address, v_value, value_at_address, operation); if(!strcmp(operation, ">=")) { if(!(value_at_address >= v_value)) passed = 0; } else if(!strcmp(operation, "<=")) { if(!(value_at_address <= v_value)) passed = 0; } else if(!strcmp(operation, ">")) { if(!(value_at_address > v_value)) passed = 0; } else if(!strcmp(operation, "<")) { if(!(value_at_address < v_value)) passed = 0; } else if(!strcmp(operation, "==")) { if(!(value_at_address == v_value)) passed = 0; } else if(!strcmp(operation, "!=")) { if(!(value_at_address != v_value)) passed = 0; } else if(!strcmp(operation, "&")) { if(!(value_at_address & v_value)) passed = 0; } else if(!strcmp(operation, "!&")) { if(value_at_address & v_value) passed = 0; } else if(!strcmp(operation, "^")) { if(!(value_at_address ^ v_value)) passed = 0; } else if(!strcmp(operation, "!^")) { if(value_at_address ^ v_value) passed = 0; } else if(!strcmp(operation, "|")) { if(!(value_at_address | v_value)) passed = 0; } else if(!strcmp(operation, "!|")) { if(value_at_address | v_value) passed = 0; } else puts("Invalid operation"); string = strchr(string, ','); if(string == NULL) break; else string++; //printf("Foo: %s\n", string); } return(passed); } void MDFNMP_ApplyPeriodicCheats(void) { std::vector::iterator chit; if(!CheatsActive) return; for(chit = cheats.begin(); chit != cheats.end(); chit++) { if(chit->status && chit->type == 'R') { if(!chit->conditions || TestConditions(chit->conditions)) for(unsigned int x = 0; x < chit->length; x++) { uint32 page = ((chit->addr + x) / PageSize) % NumPages; if(RAMPtrs[page]) { uint64 tmpval = chit->val; if(chit->bigendian) tmpval >>= (chit->length - 1 - x) * 8; else tmpval >>= x * 8; RAMPtrs[page][(chit->addr + x) % PageSize] = tmpval; } } } } } void MDFNI_ListCheats(int (*callb)(char *name, uint32 a, uint64 v, uint64 compare, int s, char type, unsigned int length, bool bigendian, void *data), void *data) { std::vector::iterator chit; for(chit = cheats.begin(); chit != cheats.end(); chit++) { if(!callb(chit->name, chit->addr, chit->val, chit->compare, chit->status, chit->type, chit->length, chit->bigendian, data)) break; } } int MDFNI_GetCheat(uint32 which, char **name, uint32 *a, uint64 *v, uint64 *compare, int *s, char *type, unsigned int *length, bool *bigendian) { CHEATF *next = &cheats[which]; if(name) *name=next->name; if(a) *a=next->addr; if(v) *v=next->val; if(s) *s=next->status; if(compare) *compare=next->compare; if(type) *type=next->type; if(length) *length = next->length; if(bigendian) *bigendian = next->bigendian; return(1); } int MDFNI_DecodePAR(const char *str, uint32 *a, uint8 *v, uint8 *c, char *type) { int boo[4]; if(strlen(str)!=8) return(0); sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3); *c = 0; if(1) { *a=(boo[3]<<8)|(boo[2]+0x7F); *v=0; } else { *v=boo[3]; *a=boo[2]|(boo[1]<<8); } *type = 'S'; return(1); } /* name can be NULL if the name isn't going to be changed. */ int MDFNI_SetCheat(uint32 which, const char *name, uint32 a, uint64 v, uint64 compare, int s, char type, unsigned int length, bool bigendian) { CHEATF *next = &cheats[which]; if(name) { char *t; if((t=(char *)realloc(next->name,strlen(name+1)))) { next->name=t; strcpy(next->name,name); } else return(0); } next->addr=a; next->val=v; next->status=s; next->compare=compare; next->type=type; next->length = length; next->bigendian = bigendian; RebuildSubCheats(); savecheats=1; return(1); } /* Convenience function. */ int MDFNI_ToggleCheat(uint32 which) { cheats[which].status = !cheats[which].status; savecheats = 1; RebuildSubCheats(); return(cheats[which].status); } static void SettingChanged(const char *name) { MDFNMP_RemoveReadPatches(); CheatsActive = MDFN_GetSettingB("cheats"); RebuildSubCheats(); MDFNMP_InstallReadPatches(); } MDFNSetting MDFNMP_Settings[] = { { "cheats", MDFNSF_NOFLAGS, "Enable cheats.", NULL, MDFNST_BOOL, "1", NULL, NULL, NULL, SettingChanged }, { NULL} }; mednafen/settings.h000755 001750 001750 00000001265 12733066400 015476 0ustar00sergiosergio000000 000000 #ifndef MDFN_SETTINGS_H #define MDFN_SETTINGS_H #include bool MDFN_LoadSettings(const char *path, const char *section = NULL, bool override = false); bool MDFN_MergeSettings(const void*); bool MDFN_MergeSettings(const std::vector &); bool MDFN_SaveSettings(const char *path); void MDFN_KillSettings(void); // Free any resources acquired. // This should assert() or something if the setting isn't found, since it would // be a totally tubular error! uint64 MDFN_GetSettingUI(const char *name); int64 MDFN_GetSettingI(const char *name); double MDFN_GetSettingF(const char *name); bool MDFN_GetSettingB(const char *name); std::string MDFN_GetSettingS(const char *name); #endif mednafen/mednafen-endian.h000664 001750 001750 00000006575 12733066400 016657 0ustar00sergiosergio000000 000000 #ifndef __MDFN_ENDIAN_H #define __MDFN_ENDIAN_H #include #include #ifdef MSB_FIRST #ifndef le32toh #define le32toh(l) ((((l)>>24) & 0xff) | (((l)>>8) & 0xff00) \ | (((l)<<8) & 0xff0000) | (((l)<<24) & 0xff000000)) #endif #ifndef le16toh #define le16toh(l) ((((l)>>8) & 0xff) | (((l)<<8) & 0xff00)) #endif #else #ifndef le32toh #define le32toh(l) (l) #endif #ifndef le16toh #define le16toh(l) (l) #endif #endif #ifndef htole32 #define htole32 le32toh #endif #ifndef htole16 #define htole16 le16toh #endif #ifdef __cplusplus extern "C" { #endif int write16le(uint16_t b, FILE *fp); int write32le(uint32_t b, FILE *fp); int read32le(uint32_t *Bufo, FILE *fp); void Endian_A16_Swap(void *src, uint32_t nelements); void Endian_A32_Swap(void *src, uint32_t nelements); void Endian_A64_Swap(void *src, uint32_t nelements); void Endian_A16_LE_to_NE(void *src, uint32_t nelements); void Endian_A16_BE_to_NE(void *src, uint32_t nelements); void Endian_A32_LE_to_NE(void *src, uint32_t nelements); void Endian_A64_LE_to_NE(void *src, uint32_t nelements); void FlipByteOrder(uint8_t *src, uint32_t count); // The following functions can encode/decode to unaligned addresses. static inline void MDFN_en16lsb(uint8_t *buf, uint16_t morp) { buf[0]=morp; buf[1]=morp>>8; } static inline void MDFN_en24lsb(uint8_t *buf, uint32_t morp) { buf[0]=morp; buf[1]=morp>>8; buf[2]=morp>>16; } static inline void MDFN_en32lsb(uint8_t *buf, uint32_t morp) { buf[0]=morp; buf[1]=morp>>8; buf[2]=morp>>16; buf[3]=morp>>24; } static inline void MDFN_en64lsb(uint8_t *buf, uint64_t morp) { buf[0]=morp >> 0; buf[1]=morp >> 8; buf[2]=morp >> 16; buf[3]=morp >> 24; buf[4]=morp >> 32; buf[5]=morp >> 40; buf[6]=morp >> 48; buf[7]=morp >> 56; } static inline void MDFN_en16msb(uint8_t *buf, uint16_t morp) { buf[0] = morp >> 8; buf[1] = morp; } static inline void MDFN_en24msb(uint8_t *buf, uint32_t morp) { buf[0] = morp >> 16; buf[1] = morp >> 8; buf[2] = morp; } static inline void MDFN_en32msb(uint8_t *buf, uint32_t morp) { buf[0] = morp >> 24; buf[1] = morp >> 16; buf[2] = morp >> 8; buf[3] = morp; } static inline void MDFN_en64msb(uint8_t *buf, uint64_t morp) { buf[0] = morp >> 56; buf[1] = morp >> 48; buf[2] = morp >> 40; buf[3] = morp >> 32; buf[4] = morp >> 24; buf[5] = morp >> 16; buf[6] = morp >> 8; buf[7] = morp >> 0; } static inline uint16_t MDFN_de16lsb(const uint8_t *morp) { return(morp[0] | (morp[1] << 8)); } static inline uint32_t MDFN_de24lsb(const uint8_t *morp) { return(morp[0]|(morp[1]<<8)|(morp[2]<<16)); } static inline uint32_t MDFN_de32lsb(const uint8_t *morp) { return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24)); } static inline uint64_t MDFN_de64lsb(const uint8_t *morp) { uint64_t ret = 0; ret |= (uint64_t)morp[0]; ret |= (uint64_t)morp[1] << 8; ret |= (uint64_t)morp[2] << 16; ret |= (uint64_t)morp[3] << 24; ret |= (uint64_t)morp[4] << 32; ret |= (uint64_t)morp[5] << 40; ret |= (uint64_t)morp[6] << 48; ret |= (uint64_t)morp[7] << 56; return(ret); } static inline uint16_t MDFN_de16msb(const uint8_t *morp) { return(morp[1] | (morp[0] << 8)); } static inline uint32_t MDFN_de24msb(const uint8_t *morp) { return((morp[2]<<0)|(morp[1]<<8)|(morp[0]<<16)); } static inline uint32_t MDFN_de32msb(const uint8_t *morp) { return(morp[3]|(morp[2]<<8)|(morp[1]<<16)|(morp[0]<<24)); } #ifdef __cplusplus } #endif #endif mednafen/state.cpp000664 001750 001750 00000030716 12733066400 015313 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mednafen.h" #include #include "driver.h" #include "general.h" #include "state.h" #define RLSB MDFNSTATE_RLSB //0x80000000 int32 smem_read(StateMem *st, void *buffer, uint32 len) { if ((len + st->loc) > st->len) return 0; memcpy(buffer, st->data + st->loc, len); st->loc += len; return(len); } int32 smem_write(StateMem *st, void *buffer, uint32 len) { if ((len + st->loc) > st->malloced) { uint32 newsize = (st->malloced >= 32768) ? st->malloced : (st->initial_malloc ? st->initial_malloc : 32768); while(newsize < (len + st->loc)) newsize *= 2; st->data = (uint8 *)realloc(st->data, newsize); st->malloced = newsize; } memcpy(st->data + st->loc, buffer, len); st->loc += len; if (st->loc > st->len) st->len = st->loc; return(len); } int32 smem_putc(StateMem *st, int value) { uint8 tmpval = value; if(smem_write(st, &tmpval, 1) != 1) return(-1); return(1); } int32 smem_tell(StateMem *st) { return(st->loc); } int32 smem_seek(StateMem *st, uint32 offset, int whence) { switch(whence) { case SEEK_SET: st->loc = offset; break; case SEEK_END: st->loc = st->len - offset; break; case SEEK_CUR: st->loc += offset; break; } if(st->loc > st->len) { st->loc = st->len; return(-1); } if(st->loc < 0) { st->loc = 0; return(-1); } return(0); } int smem_write32le(StateMem *st, uint32 b) { uint8 s[4]; s[0]=b; s[1]=b>>8; s[2]=b>>16; s[3]=b>>24; return((smem_write(st, s, 4)<4)?0:4); } int smem_read32le(StateMem *st, uint32 *b) { uint8 s[4]; if(smem_read(st, s, 4) < 4) return(0); *b = s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); return(4); } static bool SubWrite(StateMem *st, SFORMAT *sf, const char *name_prefix = NULL) { while(sf->size || sf->name) // Size can sometimes be zero, so also check for the text name. These two should both be zero only at the end of a struct. { if(!sf->size || !sf->v) { sf++; continue; } if(sf->size == (uint32)~0) /* Link to another struct. */ { if(!SubWrite(st, (SFORMAT *)sf->v, name_prefix)) return(0); sf++; continue; } int32 bytesize = sf->size; char nameo[1 + 256]; int slen; slen = snprintf(nameo + 1, 256, "%s%s", name_prefix ? name_prefix : "", sf->name); nameo[0] = slen; if(slen >= 255) { printf("Warning: state variable name possibly too long: %s %s %s %d\n", sf->name, name_prefix, nameo, slen); slen = 255; } smem_write(st, nameo, 1 + nameo[0]); smem_write32le(st, bytesize); #ifdef MSB_FIRST /* Flip the byte order... */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_Swap(sf->v, bytesize / sizeof(uint64)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_Swap(sf->v, bytesize / sizeof(uint32)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_Swap(sf->v, bytesize / sizeof(uint16)); else if(sf->flags & RLSB) FlipByteOrder((uint8_t*)sf->v, bytesize); #endif // Special case for the evil bool type, to convert bool to 1-byte elements. // Don't do it if we're only saving the raw data. if(sf->flags & MDFNSTATE_BOOL) { for(int32 bool_monster = 0; bool_monster < bytesize; bool_monster++) { uint8 tmp_bool = ((bool *)sf->v)[bool_monster]; //printf("Bool write: %.31s\n", sf->name); smem_write(st, &tmp_bool, 1); } } else smem_write(st, (uint8 *)sf->v, bytesize); #ifdef MSB_FIRST /* Now restore the original byte order. */ if(sf->flags & MDFNSTATE_BOOL) { } else if(sf->flags & MDFNSTATE_RLSB64) Endian_A64_LE_to_NE(sf->v, bytesize / sizeof(uint64)); else if(sf->flags & MDFNSTATE_RLSB32) Endian_A32_LE_to_NE(sf->v, bytesize / sizeof(uint32)); else if(sf->flags & MDFNSTATE_RLSB16) Endian_A16_LE_to_NE(sf->v, bytesize / sizeof(uint16)); else if(sf->flags & RLSB) FlipByteOrder((uint8_t*)sf->v, bytesize); #endif sf++; } return(true); } static int WriteStateChunk(StateMem *st, const char *sname, SFORMAT *sf) { int32 data_start_pos; int32 end_pos; uint8 sname_tmp[32]; memset(sname_tmp, 0, sizeof(sname_tmp)); strncpy((char *)sname_tmp, sname, 32); if(strlen(sname) > 32) printf("Warning: section name is too long: %s\n", sname); smem_write(st, sname_tmp, 32); smem_write32le(st, 0); // We'll come back and write this later. data_start_pos = smem_tell(st); if(!SubWrite(st, sf)) return(0); end_pos = smem_tell(st); smem_seek(st, data_start_pos - 4, SEEK_SET); smem_write32le(st, end_pos - data_start_pos); smem_seek(st, end_pos, SEEK_SET); return(end_pos - data_start_pos); } struct compare_cstr { bool operator()(const char *s1, const char *s2) const { return(strcmp(s1, s2) < 0); } }; typedef std::map SFMap_t; static void MakeSFMap(SFORMAT *sf, SFMap_t &sfmap) { while(sf->size || sf->name) // Size can sometimes be zero, so also check for the text name. These two should both be zero only at the end of a struct. { if(!sf->size || !sf->v) { sf++; continue; } if(sf->size == (uint32)~0) /* Link to another SFORMAT structure. */ MakeSFMap((SFORMAT *)sf->v, sfmap); else { assert(sf->name); if(sfmap.find(sf->name) != sfmap.end()) printf("Duplicate save state variable in internal emulator structures(CLUB THE PROGRAMMERS WITH BREADSTICKS): %s\n", sf->name); sfmap[sf->name] = sf; } sf++; } } // Fast raw chunk reader static void DOReadChunk(StateMem *st, SFORMAT *sf) { while(sf->size || sf->name) // Size can sometimes be zero, so also check for the text name. // These two should both be zero only at the end of a struct. { if(!sf->size || !sf->v) { sf++; continue; } if(sf->size == (uint32) ~0) // Link to another SFORMAT struct { DOReadChunk(st, (SFORMAT *)sf->v); sf++; continue; } int32 bytesize = sf->size; // Loading raw data, bool types are stored as they appear in memory, not as single bytes in the full state format. // In the SFORMAT structure, the size member for bool entries is the number of bool elements, not the total in-memory size, // so we adjust it here. if(sf->flags & MDFNSTATE_BOOL) bytesize *= sizeof(bool); smem_read(st, (uint8 *)sf->v, bytesize); sf++; } } static int ReadStateChunk(StateMem *st, SFORMAT *sf, int size) { int temp; { SFMap_t sfmap; SFMap_t sfmap_found; // Used for identifying variables that are missing in the save state. MakeSFMap(sf, sfmap); temp = smem_tell(st); while(smem_tell(st) < (temp + size)) { uint32 recorded_size; // In bytes uint8 toa[1 + 256]; // Don't change to char unless cast toa[0] to unsigned to smem_read() and other places. if(smem_read(st, toa, 1) != 1) { puts("Unexpected EOF"); return(0); } if(smem_read(st, toa + 1, toa[0]) != toa[0]) { puts("Unexpected EOF?"); return 0; } toa[1 + toa[0]] = 0; smem_read32le(st, &recorded_size); SFMap_t::iterator sfmit; sfmit = sfmap.find((char *)toa + 1); if(sfmit != sfmap.end()) { SFORMAT *tmp = sfmit->second; uint32 expected_size = tmp->size; // In bytes if(recorded_size != expected_size) { printf("Variable in save state wrong size: %s. Need: %d, got: %d\n", toa + 1, expected_size, recorded_size); if(smem_seek(st, recorded_size, SEEK_CUR) < 0) { puts("Seek error"); return(0); } } else { sfmap_found[tmp->name] = tmp; smem_read(st, (uint8 *)tmp->v, expected_size); if(tmp->flags & MDFNSTATE_BOOL) { // Converting downwards is necessary for the case of sizeof(bool) > 1 for(int32 bool_monster = expected_size - 1; bool_monster >= 0; bool_monster--) { ((bool *)tmp->v)[bool_monster] = ((uint8 *)tmp->v)[bool_monster]; } } #ifdef MSB_FIRST if(tmp->flags & MDFNSTATE_RLSB64) Endian_A64_Swap(tmp->v, expected_size / sizeof(uint64)); else if(tmp->flags & MDFNSTATE_RLSB32) Endian_A32_Swap(tmp->v, expected_size / sizeof(uint32)); else if(tmp->flags & MDFNSTATE_RLSB16) Endian_A16_Swap(tmp->v, expected_size / sizeof(uint16)); else if(tmp->flags & RLSB) FlipByteOrder((uint8_t*)tmp->v, expected_size); #endif } } else { printf("Unknown variable in save state: %s\n", toa + 1); if(smem_seek(st, recorded_size, SEEK_CUR) < 0) { puts("Seek error"); return(0); } } } // while(...) for(SFMap_t::const_iterator it = sfmap.begin(); it != sfmap.end(); it++) { if(sfmap_found.find(it->second->name) == sfmap_found.end()) { printf("Variable missing from save state: %s\n", it->second->name); } } assert(smem_tell(st) == (temp + size)); } return 1; } static int CurrentState = 0; /* This function is called by the game driver(NES, GB, GBA) to save a state. */ int MDFNSS_StateAction(void *st_p, int load, int data_only, std::vector §ions) { StateMem *st = (StateMem*)st_p; std::vector::iterator section; if(load) { { char sname[32]; for(section = sections.begin(); section != sections.end(); section++) { int found = 0; uint32 tmp_size; uint32 total = 0; while(smem_read(st, (uint8 *)sname, 32) == 32) { if(smem_read32le(st, &tmp_size) != 4) return(0); total += tmp_size + 32 + 4; // Yay, we found the section if(!strncmp(sname, section->name, 32)) { if(!ReadStateChunk(st, section->sf, tmp_size)) { printf("Error reading chunk: %s\n", section->name); return(0); } found = 1; break; } else { if(smem_seek(st, tmp_size, SEEK_CUR) < 0) { puts("Chunk seek failure"); return(0); } } } if(smem_seek(st, -total, SEEK_CUR) < 0) { puts("Reverse seek error"); return(0); } if(!found && !section->optional) // Not found. We are sad! { printf("Section missing: %.32s\n", section->name); return(0); } } } } else { for(section = sections.begin(); section != sections.end(); section++) { if(!WriteStateChunk(st, section->name, section->sf)) return(0); } } return(1); } int MDFNSS_StateAction(void *st_p, int load, int data_only, SFORMAT *sf, const char *name, bool optional) { StateMem *st = (StateMem*)st_p; std::vector love; love.push_back(SSDescriptor(sf, name, optional)); return(MDFNSS_StateAction(st, load, 0, love)); } int MDFNSS_SaveSM(void *st_p, int, int, const void*, const void*, const void*) { StateMem *st = (StateMem*)st_p; static const char *header_magic = "MDFNSVST"; uint8 header[32]; int neowidth = 0, neoheight = 0; memset(header, 0, sizeof(header)); memcpy(header, header_magic, 8); MDFN_en32lsb(header + 16, MEDNAFEN_VERSION_NUMERIC); MDFN_en32lsb(header + 24, neowidth); MDFN_en32lsb(header + 28, neoheight); smem_write(st, header, 32); if(!MDFNGameInfo->StateAction(st, 0, 0)) return(0); uint32 sizy = smem_tell(st); smem_seek(st, 16 + 4, SEEK_SET); smem_write32le(st, sizy); return(1); } int MDFNSS_LoadSM(void *st_p, int, int) { StateMem *st = (StateMem*)st_p; uint8 header[32]; uint32 stateversion; smem_read(st, header, 32); if(memcmp(header, "MEDNAFENSVESTATE", 16) && memcmp(header, "MDFNSVST", 8)) return(0); stateversion = MDFN_de32lsb(header + 16); return(MDFNGameInfo->StateAction(st, stateversion, 0)); } mednafen/wswan/wswan-memory.cpp000664 001750 001750 00000040632 12733066400 017775 0ustar00sergiosergio000000 000000 /* Cygne * * Copyright notice for this file: * Copyright (C) 2002 Dox dox@space.pl * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "wswan.h" #include "gfx.h" #include "wswan-memory.h" #include "sound.h" #include "eeprom.h" #include "rtc.h" #include "v30mz.h" #include "../mempatcher.h" #include #include static bool SkipSL; // Skip save and load uint32 wsRAMSize; uint8 wsRAM[65536]; static uint8 *wsSRAM = NULL; uint8 *wsCartROM; static uint32 sram_size; uint32 eeprom_size; static uint8 ButtonWhich, ButtonReadLatch; static uint32 DMASource, DMADest; static uint16 DMALength; static uint8 DMAControl; static uint32 SoundDMASource; static uint16 SoundDMALength; static uint8 SoundDMAControl; static uint8 BankSelector[4]; static uint8 CommControl, CommData; static bool language; extern uint16 WSButtonStatus; void WSwan_writemem20(uint32 A, uint8 V) { uint32 offset = A & 0xffff; uint32 bank = (A>>16) & 0xF; if(!bank) /*RAM*/ { WSwan_SoundCheckRAMWrite(offset); wsRAM[offset] = V; WSWan_TCacheInvalidByAddr(offset); if(offset>=0xfe00) /*WSC palettes*/ WSwan_GfxWSCPaletteRAMWrite(offset, V); } else if(bank == 1) /* SRAM */ { if(sram_size) wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)] = V; } } uint8 WSwan_readmem20(uint32 A) { uint8 bank_num; uint32 offset = A & 0xFFFF; uint32 bank = (A >> 16) & 0xF; switch(bank) { case 0: return wsRAM[offset]; case 1: if(sram_size) return wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)]; return(0); case 2: case 3: return wsCartROM[offset+((BankSelector[bank]&((rom_size>>16)-1))<<16)]; default: break; } bank_num = ((BankSelector[0] & 0xF) << 4) | (bank & 0xf); bank_num &= (rom_size >> 16) - 1; return(wsCartROM[(bank_num << 16) | offset]); } static void ws_CheckDMA(void) { if(DMAControl & 0x80) { while(DMALength) { WSwan_writemem20(DMADest, WSwan_readmem20(DMASource)); DMASource++; // = ((DMASource + 1) & 0xFFFF) | (DMASource & 0xFF0000); //if(!(DMASource & 0xFFFF)) puts("Warning: DMA source bank crossed."); DMADest = ((DMADest + 1) & 0xFFFF) | (DMADest & 0xFF0000); DMALength--; } } DMAControl &= ~0x80; } void WSwan_CheckSoundDMA(void) { if(SoundDMAControl & 0x80) { if(SoundDMALength) { uint8 zebyte = WSwan_readmem20(SoundDMASource); if(SoundDMAControl & 0x08) zebyte ^= 0x80; if(SoundDMAControl & 0x10) WSwan_SoundWrite(0x95, zebyte); // Pick a port, any port?! else WSwan_SoundWrite(0x89, zebyte); SoundDMASource++; // = ((SoundDMASource + 1) & 0xFFFF) | (SoundDMASource & 0xFF0000); //if(!(SoundDMASource & 0xFFFF)) puts("Warning: Sound DMA source bank crossed."); SoundDMALength--; } if(!SoundDMALength) SoundDMAControl &= ~0x80; } } uint8 WSwan_readport(uint32 number) { number &= 0xFF; if(number >= 0x80 && number <= 0x9F) return(WSwan_SoundRead(number)); else if(number <= 0x3F || (number >= 0xA0 && number <= 0xAF) || (number == 0x60)) return(WSwan_GfxRead(number)); else if((number >= 0xBA && number <= 0xBE) || (number >= 0xC4 && number <= 0xC8)) return(WSwan_EEPROMRead(number)); else if(number >= 0xCA && number <= 0xCB) return(WSwan_RTCRead(number)); else switch(number) { //default: printf("Read: %04x\n", number); break; case 0x40: return(DMASource >> 0); case 0x41: return(DMASource >> 8); case 0x42: return(DMASource >> 16); case 0x43: return(DMADest >> 16); case 0x44: return(DMADest >> 0); case 0x45: return(DMADest >> 8); case 0x46: return(DMALength >> 0); case 0x47: return(DMALength >> 8); case 0x48: return(DMAControl); case 0xB0: case 0xB2: case 0xB6: return(WSwan_InterruptRead(number)); case 0xC0: return(BankSelector[0] | 0x20); case 0xC1: return(BankSelector[1]); case 0xC2: return(BankSelector[2]); case 0xC3: return(BankSelector[3]); case 0x4a: return(SoundDMASource >> 0); case 0x4b: return(SoundDMASource >> 8); case 0x4c: return(SoundDMASource >> 16); case 0x4e: return(SoundDMALength >> 0); case 0x4f: return(SoundDMALength >> 8); case 0x52: return(SoundDMAControl); case 0xB1: return(CommData); case 0xb3: { uint8 ret = CommControl & 0xf0; if(CommControl & 0x80) ret |= 0x4; // Send complete return(ret); } case 0xb5: { uint8 ret = (ButtonWhich << 4) | ButtonReadLatch; return(ret); } } if(number >= 0xC8) return(0xD0 | language); return(0); } void WSwan_writeport(uint32 IOPort, uint8 V) { IOPort &= 0xFF; if(IOPort >= 0x80 && IOPort <= 0x9F) WSwan_SoundWrite(IOPort, V); else if((IOPort >= 0x00 && IOPort <= 0x3F) || (IOPort >= 0xA0 && IOPort <= 0xAF) || (IOPort == 0x60)) WSwan_GfxWrite(IOPort, V); else if((IOPort >= 0xBA && IOPort <= 0xBE) || (IOPort >= 0xC4 && IOPort <= 0xC8)) WSwan_EEPROMWrite(IOPort, V); else if(IOPort >= 0xCA && IOPort <= 0xCB) WSwan_RTCWrite(IOPort, V); else switch(IOPort) { //default: printf("%04x %02x\n", IOPort, V); break; case 0x40: DMASource &= 0xFFFF00; DMASource |= (V << 0); break; case 0x41: DMASource &= 0xFF00FF; DMASource |= (V << 8); break; case 0x42: DMASource &= 0x00FFFF; DMASource |= ((V & 0x0F) << 16); break; case 0x43: DMADest &= 0x00FFFF; DMADest |= ((V & 0x0F) << 16); break; case 0x44: DMADest &= 0xFFFF00; DMADest |= (V << 0); break; case 0x45: DMADest &= 0xFF00FF; DMADest |= (V << 8); break; case 0x46: DMALength &= 0xFF00; DMALength |= (V << 0); break; case 0x47: DMALength &= 0x00FF; DMALength |= (V << 8); break; case 0x48: DMAControl = V; //if(V&0x80) // printf("DMA%02x: %08x %08x %08x\n", V, DMASource, DMADest, DMALength); ws_CheckDMA(); break; case 0x4a: SoundDMASource &= 0xFFFF00; SoundDMASource |= (V << 0); break; case 0x4b: SoundDMASource &= 0xFF00FF; SoundDMASource |= (V << 8); break; case 0x4c: SoundDMASource &= 0x00FFFF; SoundDMASource |= (V << 16); break; //case 0x4d: break; // Unused? case 0x4e: SoundDMALength &= 0xFF00; SoundDMALength |= (V << 0); break; case 0x4f: SoundDMALength &= 0x00FF; SoundDMALength |= (V << 8); break; //case 0x50: break; // Unused? //case 0x51: break; // Unused? case 0x52: SoundDMAControl = V; //if(V & 0x80) printf("Sound DMA: %02x, %08x %08x\n", V, SoundDMASource, SoundDMALength); break; case 0xB0: case 0xB2: case 0xB6: WSwan_InterruptWrite(IOPort, V); break; case 0xB1: CommData = V; break; case 0xB3: CommControl = V & 0xF0; break; case 0xb5: ButtonWhich = V >> 4; ButtonReadLatch = 0; if(ButtonWhich & 0x4) /*buttons*/ ButtonReadLatch |= ((WSButtonStatus >> 8) << 1) & 0xF; if(ButtonWhich & 0x2) /* H/X cursors */ ButtonReadLatch |= WSButtonStatus & 0xF; if(ButtonWhich & 0x1) /* V/Y cursors */ ButtonReadLatch |= (WSButtonStatus >> 4) & 0xF; break; case 0xC0: BankSelector[0] = V & 0xF; break; case 0xC1: BankSelector[1] = V; break; case 0xC2: BankSelector[2] = V; break; case 0xC3: BankSelector[3] = V; break; } } #ifdef WANT_DEBUGGER static void GetAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint8 *Buffer) { if(!strcmp(name, "ram")) { while(Length--) { Address &= wsRAMSize - 1; *Buffer = wsRAM[Address]; Address++; Buffer++; } } else if(!strcmp(name, "physical")) { while(Length--) { Address &= 0xFFFFF; *Buffer = WSwan_readmem20(Address); Address++; Buffer++; } } else if(!strcmp(name, "cs") || !strcmp(name, "ds") || !strcmp(name, "ss") || !strcmp(name, "es")) { uint32 segment; uint32 phys_address; if(!strcmp(name, "cs")) segment = v30mz_get_reg(NEC_PS); else if(!strcmp(name, "ss")) segment = v30mz_get_reg(NEC_SS); else if(!strcmp(name, "ds")) segment = v30mz_get_reg(NEC_DS0); else if(!strcmp(name, "es")) segment = v30mz_get_reg(NEC_DS1); phys_address = (Address + (segment << 4)) & 0xFFFFF; GetAddressSpaceBytes("physical", phys_address, Length, Buffer); } } static void PutAddressSpaceBytes(const char *name, uint32 Address, uint32 Length, uint32 Granularity, bool hl, const uint8 *Buffer) { if(!strcmp(name, "ram")) { while(Length--) { Address &= wsRAMSize - 1; wsRAM[Address] = *Buffer; WSWan_TCacheInvalidByAddr(Address); if(Address >= 0xfe00) WSwan_GfxWSCPaletteRAMWrite(Address, *Buffer); Address++; Buffer++; } } else if(!strcmp(name, "physical")) { while(Length--) { uint32 offset, bank; Address &= 0xFFFFF; offset = Address & 0xFFFF; bank = (Address >> 16) & 0xF; switch(bank) { case 0: wsRAM[offset & (wsRAMSize - 1)] = *Buffer; WSWan_TCacheInvalidByAddr(offset & (wsRAMSize - 1)); if(Address >= 0xfe00) WSwan_GfxWSCPaletteRAMWrite(offset & (wsRAMSize - 1), *Buffer); break; case 1: if(sram_size) wsSRAM[(offset | (BankSelector[1] << 16)) & (sram_size - 1)] = *Buffer; break; case 2: case 3: wsCartROM[offset+((BankSelector[bank]&((rom_size>>16)-1))<<16)] = *Buffer; break; default: { uint8 bank_num = ((BankSelector[0] & 0xF) << 4) | (bank & 0xf); bank_num &= (rom_size >> 16) - 1; wsCartROM[(bank_num << 16) | offset] = *Buffer; } break; } Address++; Buffer++; } } else if(!strcmp(name, "cs") || !strcmp(name, "ds") || !strcmp(name, "ss") || !strcmp(name, "es")) { uint32 segment; uint32 phys_address; if(!strcmp(name, "cs")) segment = v30mz_get_reg(NEC_PS); else if(!strcmp(name, "ss")) segment = v30mz_get_reg(NEC_SS); else if(!strcmp(name, "ds")) segment = v30mz_get_reg(NEC_DS0); else if(!strcmp(name, "es")) segment = v30mz_get_reg(NEC_DS1); phys_address = (Address + (segment << 4)) & 0xFFFFF; PutAddressSpaceBytes("physical", phys_address, Length, Granularity, hl, Buffer); } } uint32 WSwan_MemoryGetRegister(const unsigned int id, char *special, const uint32 special_len) { uint32 ret = 0; switch(id) { case MEMORY_GSREG_ROMBBSLCT: ret = BankSelector[0]; if(special) { snprintf(special, special_len, "((0x%02x * 0x100000) %% 0x%08x) + 20 bit address = 0x%08x + 20 bit address", BankSelector[0], rom_size, (BankSelector[0] * 0x100000) & (rom_size - 1)); } break; case MEMORY_GSREG_BNK1SLCT: ret = BankSelector[1]; break; case MEMORY_GSREG_BNK2SLCT: ret = BankSelector[2]; break; case MEMORY_GSREG_BNK3SLCT: ret = BankSelector[3]; break; } return(ret); } void WSwan_MemorySetRegister(const unsigned int id, uint32 value) { switch(id) { case MEMORY_GSREG_ROMBBSLCT: BankSelector[0] = value; break; case MEMORY_GSREG_BNK1SLCT: BankSelector[1] = value; break; case MEMORY_GSREG_BNK2SLCT: BankSelector[2] = value; break; case MEMORY_GSREG_BNK3SLCT: BankSelector[3] = value; break; } } #endif void WSwan_MemoryKill(void) { if((sram_size || eeprom_size) && !SkipSL) { std::vector EvilRams; if(eeprom_size) EvilRams.push_back(PtrLengthPair(wsEEPROM, eeprom_size)); if(sram_size) EvilRams.push_back(PtrLengthPair(wsSRAM, sram_size)); MDFN_DumpToFile(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), 6, EvilRams); } if(wsSRAM) free(wsSRAM); wsSRAM = NULL; } void WSwan_MemoryInit(bool lang, bool IsWSC, uint32 ssize, bool SkipSaveLoad) { const uint16 byear = MDFN_GetSettingUI("wswan.byear"); const uint8 bmonth = MDFN_GetSettingUI("wswan.bmonth"); const uint8 bday = MDFN_GetSettingUI("wswan.bday"); const uint8 sex = MDFN_GetSettingI("wswan.sex"); const uint8 blood = MDFN_GetSettingI("wswan.blood"); language = lang; SkipSL = SkipSaveLoad; wsRAMSize = 65536; sram_size = ssize; #ifdef WANT_DEBUGGER { ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "physical", "CPU Physical", 20); ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ram", "RAM", (int)(log(wsRAMSize) / log(2))); ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "cs", "Code Segment", 16); ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ss", "Stack Segment", 16); ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "ds", "Data Segment", 16); ASpace_Add(GetAddressSpaceBytes, PutAddressSpaceBytes, "es", "Extra Segment", 16); } #endif // WSwan_EEPROMInit() will also clear wsEEPROM WSwan_EEPROMInit(MDFN_GetSettingS("wswan.name").c_str(), byear, bmonth, bday, sex, blood); if(sram_size) { wsSRAM = (uint8*)malloc(sram_size); memset(wsSRAM, 0, sram_size); } if((sram_size || eeprom_size) && !SkipSL) { FILE *savegame_fp; savegame_fp = gzopen(MDFN_MakeFName(MDFNMKF_SAV, 0, "sav").c_str(), "rb"); if(savegame_fp) { if(eeprom_size) gzread(savegame_fp, wsEEPROM, eeprom_size); if(sram_size) gzread(savegame_fp, wsSRAM, sram_size); gzclose(savegame_fp); } } MDFNMP_AddRAM(wsRAMSize, 0x00000, wsRAM); if(sram_size) MDFNMP_AddRAM(sram_size, 0x10000, wsSRAM); } void WSwan_MemoryReset(void) { memset(wsRAM, 0, 65536); wsRAM[0x75AC] = 0x41; wsRAM[0x75AD] = 0x5F; wsRAM[0x75AE] = 0x43; wsRAM[0x75AF] = 0x31; wsRAM[0x75B0] = 0x6E; wsRAM[0x75B1] = 0x5F; wsRAM[0x75B2] = 0x63; wsRAM[0x75B3] = 0x31; memset(BankSelector, 0, sizeof(BankSelector)); ButtonWhich = 0; ButtonReadLatch = 0; DMASource = 0; DMADest = 0; DMALength = 0; DMAControl = 0; SoundDMASource = 0; SoundDMALength = 0; SoundDMAControl = 0; CommControl = 0; CommData = 0; } int WSwan_MemoryStateAction(StateMem *sm, int load, int data_only) { SFORMAT StateRegs[] = { SFARRAYN(wsRAM, 65536, "RAM"), SFARRAYN(sram_size ? wsSRAM : NULL, sram_size, "SRAM"), SFVAR(ButtonWhich), SFVAR(ButtonReadLatch), SFVAR(WSButtonStatus), SFVAR(DMASource), SFVAR(DMADest), SFVAR(DMALength), SFVAR(DMAControl), SFVAR(SoundDMASource), SFVAR(SoundDMALength), SFVAR(SoundDMAControl), SFVAR(CommControl), SFVAR(CommData), SFARRAY(BankSelector, 4), SFEND }; if(!MDFNSS_StateAction(sm, load, data_only, StateRegs, "MEMR")) return(0); if(load) { for(uint32 A = 0xfe00; A <= 0xFFFF; A++) { WSwan_GfxWSCPaletteRAMWrite(A, wsRAM[A]); } } return(1); } mednafen/mednafen-endian.c000664 001750 001750 00000010027 12733066400 016635 0ustar00sergiosergio000000 000000 /* Mednafen - Multi-system Emulator * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "mednafen-endian.h" void Endian_A16_Swap(void *src, uint32_t nelements) { uint32_t i; uint8_t *nsrc = (uint8_t *)src; for(i = 0; i < nelements; i++) { uint8_t tmp = nsrc[i * 2]; nsrc[i * 2] = nsrc[i * 2 + 1]; nsrc[i * 2 + 1] = tmp; } } void Endian_A32_Swap(void *src, uint32_t nelements) { uint32_t i; uint8_t *nsrc = (uint8_t *)src; for(i = 0; i < nelements; i++) { uint8_t tmp1 = nsrc[i * 4]; uint8_t tmp2 = nsrc[i * 4 + 1]; nsrc[i * 4] = nsrc[i * 4 + 3]; nsrc[i * 4 + 1] = nsrc[i * 4 + 2]; nsrc[i * 4 + 2] = tmp2; nsrc[i * 4 + 3] = tmp1; } } void Endian_A64_Swap(void *src, uint32_t nelements) { uint32_t i; uint8_t *nsrc = (uint8_t *)src; for(i = 0; i < nelements; i++) { unsigned z; uint8_t *base = &nsrc[i * 8]; for(z = 0; z < 4; z++) { uint8_t tmp = base[z]; base[z] = base[7 - z]; base[7 - z] = tmp; } } } void Endian_A16_LE_to_NE(void *src, uint32_t nelements) { #ifdef MSB_FIRST uint32_t i; uint8_t *nsrc = (uint8_t *)src; for(i = 0; i < nelements; i++) { uint8_t tmp = nsrc[i * 2]; nsrc[i * 2] = nsrc[i * 2 + 1]; nsrc[i * 2 + 1] = tmp; } #endif } void Endian_A16_BE_to_NE(void *src, uint32_t nelements) { #ifndef MSB_FIRST uint32_t i; uint8_t *nsrc = (uint8_t *)src; for(i = 0; i < nelements; i++) { uint8_t tmp = nsrc[i * 2]; nsrc[i * 2] = nsrc[i * 2 + 1]; nsrc[i * 2 + 1] = tmp; } #endif } void Endian_A32_LE_to_NE(void *src, uint32_t nelements) { #ifdef MSB_FIRST uint32_t i; uint8_t *nsrc = (uint8_t *)src; for(i = 0; i < nelements; i++) { uint8_t tmp1 = nsrc[i * 4]; uint8_t tmp2 = nsrc[i * 4 + 1]; nsrc[i * 4] = nsrc[i * 4 + 3]; nsrc[i * 4 + 1] = nsrc[i * 4 + 2]; nsrc[i * 4 + 2] = tmp2; nsrc[i * 4 + 3] = tmp1; } #endif } void Endian_A64_LE_to_NE(void *src, uint32_t nelements) { #ifdef MSB_FIRST uint32_t i; uint8_t *nsrc = (uint8_t *)src; for(i = 0; i < nelements; i++) { unsigned z; uint8_t *base = &nsrc[i * 8]; for(z = 0; z < 4; z++) { uint8_t tmp = base[z]; base[z] = base[7 - z]; base[7 - z] = tmp; } } #endif } void FlipByteOrder(uint8_t *src, uint32_t count) { uint8_t *start=src; uint8_t *end=src+count-1; if((count&1) || !count) return; /* This shouldn't happen. */ count >>= 1; while(count--) { uint8_t tmp = *end; *end=*start; *start=tmp; end--; start++; } } int write16le(uint16_t b, FILE *fp) { uint8_t s[2]; s[0]=b; s[1]=b>>8; return((fwrite(s,1,2,fp)<2)?0:2); } int write32le(uint32_t b, FILE *fp) { uint8_t s[4]; s[0]=b; s[1]=b>>8; s[2]=b>>16; s[3]=b>>24; return((fwrite(s,1,4,fp)<4)?0:4); } int read32le(uint32_t *Bufo, FILE *fp) { uint32_t buf; if(fread(&buf,1,4,fp)<4) return 0; #ifdef MSB_FIRST *(uint32_t*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24); #else *(uint32_t*)Bufo=buf; #endif return 1; } int read16le(char *d, FILE *fp) { #ifdef MSB_FIRST int ret; ret=fread(d+1,1,1,fp); ret+=fread(d,1,1,fp); return ret<2?0:2; #else return((fread(d,1,2,fp)<2)?0:2); #endif } libretro-common/include/compat/msvc/stdint.h000664 001750 001750 00000017143 12733066400 022355 0ustar00sergiosergio000000 000000 /* ISO C9x compliant stdint.h for Microsoft Visual Studio * Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 * * Copyright (c) 2006-2008 Alexander Chemeris * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. The name of the author may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __RARCH_STDINT_H #define __RARCH_STDINT_H #if _MSC_VER && (_MSC_VER < 1600) /* Pre-MSVC 2010 needs an implementation of stdint.h. */ #if _MSC_VER > 1000 #pragma once #endif #include /* For Visual Studio 6 in C++ mode and for many Visual Studio versions when * compiling for ARM we should wrap include with 'extern "C++" {}' * or compiler give many errors like this: * * error C2733: second C linkage of overloaded function 'wmemchr' not allowed */ #ifdef __cplusplus extern "C" { #endif # include #ifdef __cplusplus } #endif /* Define _W64 macros to mark types changing their size, like intptr_t. */ #ifndef _W64 # if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 # define _W64 __w64 # else # define _W64 # endif #endif /* 7.18.1 Integer types. */ /* 7.18.1.1 Exact-width integer types. */ /* Visual Studio 6 and Embedded Visual C++ 4 doesn't * realize that, e.g. char has the same size as __int8 * so we give up on __intX for them. */ #if (_MSC_VER < 1300) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #endif typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; /* 7.18.1.2 Minimum-width integer types. */ typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; /* 7.18.1.3 Fastest minimum-width integer types. */ typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; /* 7.18.1.4 Integer types capable of holding object pointers. */ #ifdef _WIN64 /* [ */ typedef signed __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else /* _WIN64 ][ */ typedef _W64 signed int intptr_t; typedef _W64 unsigned int uintptr_t; #endif /* _WIN64 ] */ /* 7.18.1.5 Greatest-width integer types. */ typedef int64_t intmax_t; typedef uint64_t uintmax_t; /* 7.18.2 Limits of specified-width integer types. */ #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* [ See footnote 220 at page 257 and footnote 221 at page 259. */ /* 7.18.2.1 Limits of exact-width integer types. */ #define INT8_MIN ((int8_t)_I8_MIN) #define INT8_MAX _I8_MAX #define INT16_MIN ((int16_t)_I16_MIN) #define INT16_MAX _I16_MAX #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #define UINT8_MAX _UI8_MAX #define UINT16_MAX _UI16_MAX #define UINT32_MAX _UI32_MAX #define UINT64_MAX _UI64_MAX /* 7.18.2.2 Limits of minimum-width integer types. */ #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX /* 7.18.2.3 Limits of fastest minimum-width integer types. */ #define INT_FAST8_MIN INT8_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MIN INT16_MIN #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MIN INT32_MIN #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MIN INT64_MIN #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX /* 7.18.2.4 Limits of integer types capable of holding object pointers. */ #ifdef _WIN64 /* [ */ # define INTPTR_MIN INT64_MIN # define INTPTR_MAX INT64_MAX # define UINTPTR_MAX UINT64_MAX #else /* _WIN64 ][ */ # define INTPTR_MIN INT32_MIN # define INTPTR_MAX INT32_MAX # define UINTPTR_MAX UINT32_MAX #endif /* _WIN64 ] */ /* 7.18.2.5 Limits of greatest-width integer types */ #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX /* 7.18.3 Limits of other integer types */ #ifdef _WIN64 /* [ */ # define PTRDIFF_MIN _I64_MIN # define PTRDIFF_MAX _I64_MAX #else /* _WIN64 ][ */ # define PTRDIFF_MIN _I32_MIN # define PTRDIFF_MAX _I32_MAX #endif /* _WIN64 ] */ #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX /* [ */ # ifdef _WIN64 /* [ */ # define SIZE_MAX _UI64_MAX # else /* _WIN64 ][ */ # define SIZE_MAX _UI32_MAX # endif /* _WIN64 ] */ #endif /* SIZE_MAX ] */ /* WCHAR_MIN and WCHAR_MAX are also defined in */ #ifndef WCHAR_MIN /* [ */ # define WCHAR_MIN 0 #endif /* WCHAR_MIN ] */ #ifndef WCHAR_MAX // [ # define WCHAR_MAX _UI16_MAX #endif /* WCHAR_MAX ] */ #define WINT_MIN 0 #define WINT_MAX _UI16_MAX #endif /* __STDC_LIMIT_MACROS ] */ /* 7.18.4 Limits of other integer types */ #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* [ See footnote 224 at page 260 */ /* 7.18.4.1 Macros for minimum-width integer constants */ #define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 #define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 /* 7.18.4.2 Macros for greatest-width integer constants */ #define INTMAX_C INT64_C #define UINTMAX_C UINT64_C #endif /* __STDC_CONSTANT_MACROS ] */ #else /* Sanity for everything else. */ #include #endif #endif mednafen/000700 001750 001750 00000000000 12733077034 013451 5ustar00sergiosergio000000 000000 libretro-common/include/retro_miscellaneous.h000664 001750 001750 00000012605 12733066400 022671 0ustar00sergiosergio000000 000000 /* Copyright (C) 2010-2016 The RetroArch team * * --------------------------------------------------------------------------------------- * The following license statement only applies to this file (retro_miscellaneous.h). * --------------------------------------------------------------------------------------- * * Permission is hereby granted, free of charge, * to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __RARCH_MISCELLANEOUS_H #define __RARCH_MISCELLANEOUS_H #include #include #if defined(__CELLOS_LV2__) && !defined(__PSL1GHT__) #include #elif defined(XENON) #include