mednafen/include/blargg_source.h000664 001750 001750 00000004574 12733066344 020113 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 00000002303 12733066344 015413 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) #ifndef gettext_noop #define gettext_noop(a) (a) #endif extern MDFNGI *MDFNGameInfo; #include "settings.h" void MDFN_PrintError(const char *format, ...); void MDFN_printf(const char *format, ...); void MDFN_DispMessage(const char *format, ...); void MDFN_DebugPrintReal(const char *file, const int line, const char *format, ...); 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 12733066344 021066 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 00000004174 12733066344 014565 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 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); #endif mednafen/git.h000664 001750 001750 00000034054 12733066344 014431 0ustar00sergiosergio000000 000000 #ifndef _GIT_H #define _GIT_H #include typedef struct { const char *extension; // Example ".nes" const char *description; // Example "iNES Format ROM Image" } FileExtensionSpecStruct; #include "file.h" #include "video/surface.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 mednafen/vb/vip_draw.inc000664 001750 001750 00000033564 12733066344 016417 0ustar00sergiosergio000000 000000 #include "vb.h" #define BGM_AFFINE 0x2 #define BGM_OBJ 0x3 static void DrawBG(uint8 *target, uint16 RealY, bool lr, uint8 bgmap_base_raw, bool overplane, uint16 overplane_char, uint32 SourceX, uint32 SourceY, uint32 scx, uint32 scy, uint16 DestX, uint16 DestY, uint16 DestWidth, uint16 DestHeight) { const uint16 *CHR16 = CHR_RAM; const uint16 *BGMap = DRAM; uint32 BGMap_Base = bgmap_base_raw << 12; int32 start_x, final_x; const uint32 bgsc_overplane = DRAM[overplane_char]; const uint32 BGMap_XCount = 1 << scx; const uint32 BGMap_YCount = 1 << scy; const uint32 SourceX_Size = 512 * BGMap_XCount; const uint32 SourceY_Size = 512 * BGMap_YCount; const uint32 SourceX_Mask = overplane ? 0x1FFF : (SourceX_Size - 1); const uint32 SourceY_Mask = overplane ? 0x1FFF : (SourceY_Size - 1); if((uint16)(RealY - DestY) > DestHeight) return; //printf("%d, %d, %d, %d\n", overplane, srcXSize, srcYSize, bgmap_base_raw); DestX = sign_10_to_s16(DestX); if(DestX & 0x8000) SourceX -= DestX; start_x = (int16)DestX; final_x = (int16)DestX + DestWidth; if(start_x < 0) start_x = 0; if(final_x > 383) final_x = 383; if(start_x > final_x) return; // Optimization: SourceY &= SourceY_Mask; BGMap_Base |= (((SourceY >> 3) & 0x3F) * 0x40) | (((SourceY << 3) & ~0xFFF) << scx); for(int x = start_x; x <= final_x; x++) { uint32 bgsc; uint32 char_no; uint32 palette_selector; uint32 hflip_xor; uint32 vflip_xor; SourceX &= SourceX_Mask; bgsc = bgsc_overplane; if(SourceX < SourceX_Size && SourceY < SourceY_Size) bgsc = BGMap[(BGMap_Base | ((SourceX << 3) & ~0xFFF) | ((SourceX >> 3) & 0x3F)) & 0xFFFF]; char_no = bgsc & 0x7FF; palette_selector = bgsc >> 14; hflip_xor = (bgsc & 0x2000) ? 7 : 0; //(((int32)bgsc << 18) >> 31) & 0x7; vflip_xor = (bgsc & 0x1000) ? 7 : 0; //(((int32)bgsc << 19) >> 31) & 0x7; unsigned int char_sub_y = vflip_xor ^ (SourceY & 0x7); if(!(SourceX & 7) && (x + 7) <= final_x) { uint32 pixels = CHR16[char_no * 8 + char_sub_y]; #if 0 unsigned int char_sub_x; uint8 *sub_target = target + x + 8; for(int sub_x = -8; sub_x < 0; sub_x++) { if(pixels & 3) sub_target[sub_x] = GPLT_Cache[palette_selector][pixels & 3]; pixels >>= 2; } #endif if(bgsc & 0x2000) { if((pixels >> 14) & 3) target[0 + x] = GPLT_Cache[palette_selector][(pixels >> 14) & 3]; if((pixels >> 12) & 3) target[1 + x] = GPLT_Cache[palette_selector][(pixels >> 12) & 3]; if((pixels >> 10) & 3) target[2 + x] = GPLT_Cache[palette_selector][(pixels >> 10) & 3]; if((pixels >> 8) & 3) target[3 + x] = GPLT_Cache[palette_selector][(pixels >> 8) & 3]; if((pixels >> 6) & 3) target[4 + x] = GPLT_Cache[palette_selector][(pixels >> 6) & 3]; if((pixels >> 4) & 3) target[5 + x] = GPLT_Cache[palette_selector][(pixels >> 4) & 3]; if((pixels >> 2) & 3) target[6 + x] = GPLT_Cache[palette_selector][(pixels >> 2) & 3]; if((pixels >> 0) & 3) target[7 + x] = GPLT_Cache[palette_selector][(pixels >> 0) & 3]; } else { if((pixels >> 0) & 3) target[0 + x] = GPLT_Cache[palette_selector][(pixels >> 0) & 3]; if((pixels >> 2) & 3) target[1 + x] = GPLT_Cache[palette_selector][(pixels >> 2) & 3]; if((pixels >> 4) & 3) target[2 + x] = GPLT_Cache[palette_selector][(pixels >> 4) & 3]; if((pixels >> 6) & 3) target[3 + x] = GPLT_Cache[palette_selector][(pixels >> 6) & 3]; if((pixels >> 8) & 3) target[4 + x] = GPLT_Cache[palette_selector][(pixels >> 8) & 3]; if((pixels >> 10) & 3) target[5 + x] = GPLT_Cache[palette_selector][(pixels >> 10) & 3]; if((pixels >> 12) & 3) target[6 + x] = GPLT_Cache[palette_selector][(pixels >> 12) & 3]; if((pixels >> 14) & 3) target[7 + x] = GPLT_Cache[palette_selector][(pixels >> 14) & 3]; } x += 7; SourceX += 8; } else { unsigned int char_sub_x; char_sub_x = hflip_xor ^ (SourceX & 0x7); uint8 pixel = (CHR16[char_no * 8 + char_sub_y] >> (char_sub_x * 2)) & 0x3; if(pixel) target[x] = GPLT_Cache[palette_selector][pixel]; //target[x] = (GPLT[palette_selector] >> (pixel * 2)) & 0x3; SourceX++; } } } static void DrawAffine(uint8 *target, uint16 RealY, bool lr, uint32 ParamBase, uint32 BGMap_Base, bool OverplaneMode, uint16 OverplaneChar, uint32 scx, uint32 scy, uint16 DestX, uint16 DestY, uint16 DestWidth, uint16 DestHeight) { const uint16 *CHR16 = CHR_RAM; const uint16 *BGMap = DRAM; const uint32 BGMap_XCount = 1 << scx; const uint32 BGMap_YCount = 1 << scy; const uint32 SourceX_Size = 512 * BGMap_XCount; const uint32 SourceY_Size = 512 * BGMap_YCount; const uint16 *param_ptr = &DRAM[(ParamBase + 8 * (RealY - DestY)) & 0xFFFF]; int16 mx = param_ptr[0], mp = (ParallaxDisabled ? 0 : param_ptr[1]), my = param_ptr[2], dx = param_ptr[3], dy = param_ptr[4]; uint32 SourceX, SourceY; uint32 SourceX_Mask, SourceY_Mask; int32 start_x, final_x; const uint32 bgsc_overplane = DRAM[OverplaneChar]; DestX = sign_10_to_s16(DestX); if((uint16)(RealY - DestY) > DestHeight) return; SourceX = (int32)mx << 6; SourceY = (int32)my << 6; if(DestX & 0x8000) { SourceX += dx * (65536 - DestX); SourceY += dy * (65536 - DestX); } if(mp >= 0 && lr) { SourceX += dx * mp; SourceY += dy * mp; } else if(mp < 0 && !lr) { SourceX += dx * -mp; SourceY += dy * -mp; } if(OverplaneMode) { SourceX_Mask = 0x3FFFFFF; //(((uint32)SourceX_Size << 9) * 2) - 1; SourceY_Mask = 0x3FFFFFF; //(((uint32)SourceY_Size << 9) * 2) - 1; } else { SourceX_Mask = ((uint32)SourceX_Size << 9) - 1; SourceY_Mask = ((uint32)SourceY_Size << 9) - 1; } start_x = (int16)DestX; final_x = (int16)DestX + DestWidth; if(start_x < 0) start_x = 0; if(final_x > 383) final_x = 383; if(dy == 0) // Optimization for no rotation. { SourceY &= SourceY_Mask; if(SourceY >= (SourceY_Size << 9)) return; BGMap_Base |= (((SourceY >> 6) & ~0xFFF) << scx) | (((SourceY >> 12) & 0x3F) * 0x40); for(int x = start_x; x <= final_x; x++) { uint32 bgsc; uint32 hflip_xor; uint32 vflip_xor; uint32 pixel = 0; SourceX &= SourceX_Mask; bgsc = bgsc_overplane; if(SourceX < (SourceX_Size << 9)) bgsc = BGMap[(BGMap_Base | ((SourceX >> 6) & ~0xFFF) | ((SourceX >> 12) & 0x3F)) & 0xFFFF]; //hflip_xor = bgsc & 0x2000 ? 0xE : 0; //vflip_xor = bgsc & 0x1000 ? 0x7 : 0; hflip_xor = ((int32)(bgsc << 18) >> 30) & 0xE; vflip_xor = ((int32)(bgsc << 19) >> 31) & 0x7; unsigned int char_sub_y = vflip_xor ^ ((SourceY >> 9) & 0x7); unsigned int char_sub_x = hflip_xor ^ ((SourceX >> 8) & 0xE); pixel = (CHR16[((bgsc & 0x7FF) * 8) | char_sub_y] >> char_sub_x) & 0x3; if(pixel) target[x] = GPLT_Cache[bgsc >> 14][pixel]; SourceX += dx; } } else for(int x = start_x; x <= final_x; x++) { uint32 bgsc; uint32 char_no; uint32 palette_selector; uint32 hflip_xor; uint32 vflip_xor; uint8 pixel = 0; SourceX &= SourceX_Mask; SourceY &= SourceY_Mask; bgsc = bgsc_overplane; if(SourceX < (SourceX_Size << 9) && SourceY < (SourceY_Size << 9)) { uint32 m_index = ((SourceX >> 6) & ~0xFFF) + (((SourceY >> 6) & ~0xFFF) << scx); uint32 sub_index = ((SourceX >> 12) & 0x3F) + (((SourceY >> 12) & 0x3F) * 0x40); bgsc = BGMap[(BGMap_Base | m_index | sub_index) & 0xFFFF]; //bgsc = BGMap[(BGMapBase + (SourceX >> 12) + (SourceY >> 12) * (SourceX_Size >> 3)) & 0xFFFF ]; } char_no = bgsc & 0x7FF; palette_selector = bgsc >> 14; hflip_xor = bgsc & 0x2000 ? 7 : 0; //(((int32)bgsc << 18) >> 31) & 0x7; vflip_xor = bgsc & 0x1000 ? 7 : 0; //(((int32)bgsc << 19) >> 31) & 0x7; unsigned int char_sub_y = vflip_xor ^ ((SourceY >> 9) & 0x7); unsigned int char_sub_x = hflip_xor ^ ((SourceX >> 9) & 0x7); pixel = (CHR16[char_no * 8 + char_sub_y] >> (char_sub_x * 2)) & 0x3; if(pixel) target[x] = GPLT_Cache[palette_selector][pixel]; SourceX += dx; SourceY += dy; } } static int obj_search_which; static void DrawOBJ(uint8 *fb[2], uint16 Y, bool lron[2]) { const uint16 *CHR16 = CHR_RAM; int32 start_oam; int32 end_oam; start_oam = SPT[obj_search_which]; end_oam = 1023; if(obj_search_which) end_oam = SPT[obj_search_which - 1]; int32 oam = start_oam; do { const uint16 *oam_ptr = &DRAM[(0x1E000 + (oam * 8)) >> 1]; const uint32 jy = oam_ptr[2]; const uint32 tile_y = (Y - jy) & 0xFF; // I think this mask is right. See: http://www.planetvb.com/modules/newbb/viewtopic.php?topic_id=3797&forum=2 if(tile_y >= 8) continue; uint32 jx = oam_ptr[0]; uint32 jp = ParallaxDisabled ? 0 : (oam_ptr[1] & 0x3FFF); uint32 palette_selector = oam_ptr[3] >> 14; uint32 vflip_xor = (oam_ptr[3] & 0x1000) ? 7 : 0; uint32 char_sub_y = vflip_xor ^ tile_y; bool jlron[2] = { (bool)(oam_ptr[1] & 0x8000), (bool)(oam_ptr[1] & 0x4000) }; uint32 char_no = oam_ptr[3] & 0x7FF; const uint32 pixels_save = CHR16[char_no * 8 + char_sub_y]; for(int lr = 0; lr < 2; lr++) { if(!(jlron[lr] & lron[lr])) continue; uint32 pixels = pixels_save; int32 x = sign_x_to_s32(10, (jx + (lr ? jp : -jp))); // It may actually be 9, TODO? if(x >= -7 && x < 384) // Make sure we always keep the pitch of our 384x8 buffer large enough(with padding before and after the visible space) { uint8 *target = &fb[lr][x]; if(oam_ptr[3] & 0x2000) { target += 7; for(int meow = 8; meow; meow--) { if(pixels & 3) *target = JPLT_Cache[palette_selector][pixels & 3]; target--; pixels >>= 2; } } else { for(int meow = 8; meow; meow--) { if(pixels & 3) *target = JPLT_Cache[palette_selector][pixels & 3]; target++; pixels >>= 2; } } #if 0 if(oam_ptr[3] & 0x2000) { if((pixels >> 14) & 3) fb[lr][0 + x] = JPLT_Cache[palette_selector][(pixels >> 14) & 3]; if((pixels >> 12) & 3) fb[lr][1 + x] = JPLT_Cache[palette_selector][(pixels >> 12) & 3]; if((pixels >> 10) & 3) fb[lr][2 + x] = JPLT_Cache[palette_selector][(pixels >> 10) & 3]; if((pixels >> 8) & 3) fb[lr][3 + x] = JPLT_Cache[palette_selector][(pixels >> 8) & 3]; if((pixels >> 6) & 3) fb[lr][4 + x] = JPLT_Cache[palette_selector][(pixels >> 6) & 3]; if((pixels >> 4) & 3) fb[lr][5 + x] = JPLT_Cache[palette_selector][(pixels >> 4) & 3]; if((pixels >> 2) & 3) fb[lr][6 + x] = JPLT_Cache[palette_selector][(pixels >> 2) & 3]; if((pixels >> 0) & 3) fb[lr][7 + x] = JPLT_Cache[palette_selector][(pixels >> 0) & 3]; } else { if((pixels >> 0) & 3) fb[lr][0 + x] = JPLT_Cache[palette_selector][(pixels >> 0) & 3]; if((pixels >> 2) & 3) fb[lr][1 + x] = JPLT_Cache[palette_selector][(pixels >> 2) & 3]; if((pixels >> 4) & 3) fb[lr][2 + x] = JPLT_Cache[palette_selector][(pixels >> 4) & 3]; if((pixels >> 6) & 3) fb[lr][3 + x] = JPLT_Cache[palette_selector][(pixels >> 6) & 3]; if((pixels >> 8) & 3) fb[lr][4 + x] = JPLT_Cache[palette_selector][(pixels >> 8) & 3]; if((pixels >> 10) & 3) fb[lr][5 + x] = JPLT_Cache[palette_selector][(pixels >> 10) & 3]; if((pixels >> 12) & 3) fb[lr][6 + x] = JPLT_Cache[palette_selector][(pixels >> 12) & 3]; if((pixels >> 14) & 3) fb[lr][7 + x] = JPLT_Cache[palette_selector][(pixels >> 14) & 3]; } #endif } } } while( (oam = (oam - 1) & 1023) != end_oam); } void VIP_DrawBlock(uint8 block_no, uint8 *fb_l, uint8 *fb_r) { for(int y = 0; y < 8; y++) { memset(fb_l + y * 512, BKCOL, 384); memset(fb_r + y * 512, BKCOL, 384); } obj_search_which = 3; for(int world = 31; world >= 0; world--) { const uint16 *world_ptr = &DRAM[(0x1D800 + world * 0x20) >> 1]; uint32 bgmap_base = world_ptr[0] & 0xF; bool end = world_ptr[0] & 0x40; bool over = world_ptr[0] & 0x80; uint32 scy = (world_ptr[0] >> 8) & 3; uint32 scx = (world_ptr[0] >> 10) & 3; uint32 bgm = (world_ptr[0] >> 12) & 3; bool lron[2] = { (bool)(world_ptr[0] & 0x8000), (bool)(world_ptr[0] & 0x4000) }; uint16 gx = sign_11_to_s16(world_ptr[1]); uint16 gp = ParallaxDisabled ? 0 : sign_9_to_s16(world_ptr[2]); uint16 gy = sign_11_to_s16(world_ptr[3]); uint16 mx = world_ptr[4]; uint16 mp = ParallaxDisabled ? 0 : sign_9_to_s16(world_ptr[5]); uint16 my = world_ptr[6]; uint16 window_width = sign_11_to_s16(world_ptr[7]); uint16 window_height = (world_ptr[8] & 0x3FF); uint32 param_base = (world_ptr[9] & 0xFFF0); uint16 overplane_char = world_ptr[10]; if(end) break; if(((512 << scx) + (512 << scy)) > 4096) { printf("BG Size too large for world: %d(scx=%d, scy=%d)\n", world, scx, scy); } // if(world != 2) // continue; // if(block_no == 8) // printf("World: %d; gx: %d, gp: %d, gy: %d, mx: %d, mp: %d, my: %d, window_width: %d, window_height: %d\n", world, gx, gp, gy, mx, mp, my, window_width, window_height); for(int y = 0; y < 8; y++) { uint8 *fb[2] = { &fb_l[y * 512], &fb_r[y * 512] }; if(bgm == BGM_OBJ) { if(!lron[0] || !lron[1]) printf("Bad OBJ World? %d(%d/%d) %d~%d\n", world, lron[0], lron[1], SPT[obj_search_which], obj_search_which ? (SPT[obj_search_which - 1] + 1) : 0); DrawOBJ(fb, (block_no * 8) + y, lron); } else if(bgm == BGM_AFFINE) { //if(((block_no * 8) + y) == 128) // printf("Draw affine: %d %d\n", gx, gp); for(int lr = 0; lr < 2; lr++) { if(lron[lr]) { DrawAffine(fb[lr], (block_no * 8) + y, lr, param_base, bgmap_base * 4096, over, overplane_char, scx, scy, gx + (lr ? gp : -gp), gy, window_width, window_height); } } } else for(int lr = 0; lr < 2; lr++) { uint16 srcX, srcY; uint16 RealY = (block_no * 8) + y; uint16 DestX; uint16 DestY; srcX = mx + (lr ? mp : -mp); srcY = my + (RealY - gy); DestX = gx + (lr ? gp : -gp); DestY = gy; if(lron[lr]) { if(bgm == 1) // HBias srcX += (int16)DRAM[(param_base + (((RealY - DestY) * 2) | lr)) & 0xFFFF]; DrawBG(fb[lr], RealY, lr, bgmap_base, over, overplane_char, (int32)(int16)srcX, (int32)(int16)srcY, scx, scy, DestX, DestY, window_width, window_height); } } } if(bgm == BGM_OBJ) if(obj_search_which) obj_search_which--; } } msvc/msvc-2003-xbox1/stdint.h000664 001750 001750 00000017100 12733066344 016730 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 boolean.h000664 001750 001750 00000002040 12733066344 013476 0ustar00sergiosergio000000 000000 /* RetroArch - A frontend for libretro. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen * * RetroArch 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 Found- * ation, either version 3 of the License, or (at your option) any later version. * * RetroArch 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 RetroArch. * If not, see . */ #ifndef __RARCH_BOOLEAN_H #define __RARCH_BOOLEAN_H #ifndef __cplusplus #if defined(_MSC_VER) && !defined(SN_TARGET_PS3) /* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */ #define bool unsigned char #define true 1 #define false 0 #else #include #endif #endif #endif msvc/msvc-2003-xbox1/000700 001750 001750 00000000000 12733076376 015245 5ustar00sergiosergio000000 000000 Makefile000664 001750 001750 00000020757 12733066344 013365 0ustar00sergiosergio000000 000000 DEBUG = 0 FRONTEND_SUPPORTS_RGB565 = 1 CORE_DIR := . 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 = vb NEED_BPP = 32 NEED_BLIP = 1 WANT_NEW_API = 1 NEED_STEREO_SOUND = 1 CORE_DEFINE := -DWANT_VB_EMU TARGET_NAME := mednafen_$(core)_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 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) 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 NEED_BPP := 16 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 # GCW0 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/hw_cpu/v810/v810_oploop.inc000664 001750 001750 00000061227 12733066344 020243 0ustar00sergiosergio000000 000000 /* V810 Emulator * * Copyright (C) 2006 David Tucker * * 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 */ // Macro test taken from http://gcc.gnu.org/viewcvs/trunk/gcc/testsuite/gcc.dg/20020919-1.c?view=markup&pathrev=142696 //#if defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) || defined (__POWERPC__) || defined (PPC) || defined (_IBMR2) // register v810_timestamp_t timestamp_rl asm("15") = v810_timestamp; //#elif defined(__x86_64__) // register v810_timestamp_t timestamp_rl asm("r11") = v810_timestamp; //#else register v810_timestamp_t timestamp_rl = v810_timestamp; //#endif uint32 opcode; uint32 tmp2; int val = 0; #define ADDCLOCK(__n) { timestamp += __n; } #define CHECK_HALTED(); { if(Halted && timestamp < next_event_ts) { timestamp = next_event_ts; } } while(Running) { #ifdef RB_DEBUGMODE uint32 old_PC = RB_GETPC(); #endif uint32 tmpop; assert(timestamp_rl <= next_event_ts); if(!IPendingCache) { if(Halted) { timestamp_rl = next_event_ts; } else if(in_bstr) { tmpop = in_bstr_to; opcode = tmpop >> 9; goto op_BSTR; } } while(timestamp_rl < next_event_ts) { #ifdef RB_DEBUGMODE old_PC = RB_GETPC(); #endif P_REG[0] = 0; //Zero the Zero Reg!!! RB_CPUHOOK(RB_GETPC()); { //printf("%08x\n", RB_GETPC()); { v810_timestamp_t timestamp = timestamp_rl; tmpop = RB_RDOP(0, 0); timestamp_rl = timestamp; } opcode = (tmpop >> 9) | IPendingCache; //printf("%02x\n", opcode >> 1); #ifdef _MSC_VER #include "v810_op_table_msvc.inc" #else static const void *const op_goto_table[256] = { #include "v810_op_table.inc" }; goto *op_goto_table[opcode]; #endif // Bit string subopcodes #define DO_AM_BSTR() \ const uint32 arg1 = (tmpop >> 5) & 0x1F; \ const uint32 arg2 = (tmpop & 0x1F); \ RB_INCPCBY2(); #define DO_AM_FPP() \ const uint32 arg1 = (tmpop >> 5) & 0x1F; \ const uint32 arg2 = (tmpop & 0x1F); \ const uint32 arg3 = ((RB_RDOP(2) >> 10)&0x3F); \ RB_INCPCBY4(); #define DO_AM_UDEF() \ RB_INCPCBY2(); #define DO_AM_I() \ const uint32 arg1 = tmpop & 0x1F; \ const uint32 arg2 = (tmpop >> 5) & 0x1F; \ RB_INCPCBY2(); #define DO_AM_II() DO_AM_I(); #define DO_AM_IV() \ const uint32 arg1 = ((tmpop & 0x000003FF) << 16) | RB_RDOP(2); \ #define DO_AM_V() \ const uint32 arg3 = (tmpop >> 5) & 0x1F; \ const uint32 arg2 = tmpop & 0x1F; \ const uint32 arg1 = RB_RDOP(2); \ RB_INCPCBY4(); #define DO_AM_VIa() \ const uint32 arg1 = RB_RDOP(2); \ const uint32 arg2 = tmpop & 0x1F; \ const uint32 arg3 = (tmpop >> 5) & 0x1F; \ RB_INCPCBY4(); \ #define DO_AM_VIb() \ const uint32 arg1 = (tmpop >> 5) & 0x1F; \ const uint32 arg2 = RB_RDOP(2); \ const uint32 arg3 = (tmpop & 0x1F); \ RB_INCPCBY4(); \ #define DO_AM_IX() \ const uint32 arg1 = (tmpop & 0x1); \ RB_INCPCBY2(); \ #define DO_AM_III() \ const uint32 arg1 = tmpop & 0x1FE; #include "v810_do_am.h" #define BEGIN_OP(meowtmpop) { op_##meowtmpop: v810_timestamp_t timestamp = timestamp_rl; DO_##meowtmpop ##_AM(); #define END_OP() timestamp_rl = timestamp; goto OpFinished; } #define END_OP_SKIPLO() timestamp_rl = timestamp; goto OpFinishedSkipLO; } BEGIN_OP(MOV); ADDCLOCK(1); SetPREG(arg2, P_REG[arg1]); END_OP(); BEGIN_OP(ADD); ADDCLOCK(1); uint32 temp = P_REG[arg2] + P_REG[arg1]; SetFlag(PSW_OV, ((P_REG[arg2]^(~P_REG[arg1]))&(P_REG[arg2]^temp))&0x80000000); SetFlag(PSW_CY, temp < P_REG[arg2]); SetPREG(arg2, temp); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(SUB); ADDCLOCK(1); uint32 temp = P_REG[arg2] - P_REG[arg1]; SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000); SetFlag(PSW_CY, temp > P_REG[arg2]); SetPREG(arg2, temp); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(CMP); ADDCLOCK(1); uint32 temp = P_REG[arg2] - P_REG[arg1]; SetSZ(temp); SetFlag(PSW_OV, ((P_REG[arg2]^P_REG[arg1])&(P_REG[arg2]^temp))&0x80000000); SetFlag(PSW_CY, temp > P_REG[arg2]); END_OP(); BEGIN_OP(SHL); ADDCLOCK(1); val = P_REG[arg1] & 0x1F; // set CY before we destroy the regisrer info.... SetFlag(PSW_CY, (val != 0) && ((P_REG[arg2] >> (32 - val))&0x01) ); SetFlag(PSW_OV, false); SetPREG(arg2, P_REG[arg2] << val); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(SHR); ADDCLOCK(1); val = P_REG[arg1] & 0x1F; // set CY before we destroy the regisrer info.... SetFlag(PSW_CY, (val) && ((P_REG[arg2] >> (val-1))&0x01)); SetFlag(PSW_OV, false); SetPREG(arg2, P_REG[arg2] >> val); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(JMP); (void)arg2; // arg2 is unused. ADDCLOCK(3); RB_SETPC((P_REG[arg1] & 0xFFFFFFFE)); if(RB_AccurateMode) { BRANCH_ALIGN_CHECK(PC); } RB_ADDBT(old_PC, RB_GETPC(), 0); END_OP(); BEGIN_OP(SAR); ADDCLOCK(1); val = P_REG[arg1] & 0x1F; SetFlag(PSW_CY, (val) && ((P_REG[arg2]>>(val-1))&0x01) ); SetFlag(PSW_OV, false); SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> val)); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(OR); ADDCLOCK(1); SetPREG(arg2, P_REG[arg1] | P_REG[arg2]); SetFlag(PSW_OV, false); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(AND); ADDCLOCK(1); SetPREG(arg2, P_REG[arg1] & P_REG[arg2]); SetFlag(PSW_OV, false); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(XOR); ADDCLOCK(1); SetPREG(arg2, P_REG[arg1] ^ P_REG[arg2]); SetFlag(PSW_OV, false); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(NOT); ADDCLOCK(1); SetPREG(arg2, ~P_REG[arg1]); SetFlag(PSW_OV, false); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(MOV_I); ADDCLOCK(1); SetPREG(arg2,sign_5(arg1)); END_OP(); BEGIN_OP(ADD_I); ADDCLOCK(1); uint32 temp = P_REG[arg2] + sign_5(arg1); SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000); SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]); SetPREG(arg2, (uint32)temp); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(SETF); ADDCLOCK(1); P_REG[arg2] = 0; switch (arg1 & 0x0F) { case COND_V: if (TESTCOND_V) P_REG[arg2] = 1; break; case COND_C: if (TESTCOND_C) P_REG[arg2] = 1; break; case COND_Z: if (TESTCOND_Z) P_REG[arg2] = 1; break; case COND_NH: if (TESTCOND_NH) P_REG[arg2] = 1; break; case COND_S: if (TESTCOND_S) P_REG[arg2] = 1; break; case COND_T: P_REG[arg2] = 1; break; case COND_LT: if (TESTCOND_LT) P_REG[arg2] = 1; break; case COND_LE: if (TESTCOND_LE) P_REG[arg2] = 1; break; case COND_NV: if (TESTCOND_NV) P_REG[arg2] = 1; break; case COND_NC: if (TESTCOND_NC) P_REG[arg2] = 1; break; case COND_NZ: if (TESTCOND_NZ) P_REG[arg2] = 1; break; case COND_H: if (TESTCOND_H) P_REG[arg2] = 1; break; case COND_NS: if (TESTCOND_NS) P_REG[arg2] = 1; break; case COND_F: //always false! do nothing more break; case COND_GE: if (TESTCOND_GE) P_REG[arg2] = 1; break; case COND_GT: if (TESTCOND_GT) P_REG[arg2] = 1; break; } END_OP(); BEGIN_OP(CMP_I); ADDCLOCK(1); uint32 temp = P_REG[arg2] - sign_5(arg1); SetSZ(temp); SetFlag(PSW_OV, ((P_REG[arg2]^(sign_5(arg1)))&(P_REG[arg2]^temp))&0x80000000); SetFlag(PSW_CY, temp > P_REG[arg2]); END_OP(); BEGIN_OP(SHR_I); ADDCLOCK(1); SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (arg1-1))&0x01) ); // set CY before we destroy the regisrer info.... SetPREG(arg2, P_REG[arg2] >> arg1); SetFlag(PSW_OV, false); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(SHL_I); ADDCLOCK(1); SetFlag(PSW_CY, arg1 && ((P_REG[arg2] >> (32 - arg1))&0x01) ); // set CY before we destroy the regisrer info.... SetPREG(arg2, P_REG[arg2] << arg1); SetFlag(PSW_OV, false); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(SAR_I); ADDCLOCK(1); SetFlag(PSW_CY, arg1 && ((P_REG[arg2]>>(arg1-1))&0x01) ); SetPREG(arg2, (uint32) ((int32)P_REG[arg2] >> arg1)); SetFlag(PSW_OV, false); SetSZ(P_REG[arg2]); END_OP(); BEGIN_OP(LDSR); // Loads a Sys Reg with the value in specified PR ADDCLOCK(1); // ? SetSREG(timestamp, arg1 & 0x1F, P_REG[arg2 & 0x1F]); END_OP(); BEGIN_OP(STSR); // Loads a PR with the value in specified Sys Reg ADDCLOCK(1); // ? P_REG[arg2 & 0x1F] = GetSREG(arg1 & 0x1F); END_OP(); BEGIN_OP(EI); (void)arg1; // arg1 is unused. (void)arg2; // arg2 is unused. if(VBMode) { ADDCLOCK(1); S_REG[PSW] = S_REG[PSW] &~ PSW_ID; RecalcIPendingCache(); } else { ADDCLOCK(1); RB_DECPCBY2(); Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); CHECK_HALTED(); } END_OP(); BEGIN_OP(DI); (void)arg1; // arg1 is unused. (void)arg2; // arg2 is unused. if(VBMode) { ADDCLOCK(1); S_REG[PSW] |= PSW_ID; IPendingCache = 0; } else { ADDCLOCK(1); RB_DECPCBY2(); Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); CHECK_HALTED(); } END_OP(); #define COND_BRANCH(cond) \ if(cond) \ { \ ADDCLOCK(3); \ RB_PCRELCHANGE(sign_9(arg1) & 0xFFFFFFFE); \ if(RB_AccurateMode) \ { \ BRANCH_ALIGN_CHECK(PC); \ } \ RB_ADDBT(old_PC, RB_GETPC(), 0); \ } \ else \ { \ ADDCLOCK(1); \ RB_INCPCBY2(); \ } BEGIN_OP(BV); COND_BRANCH(TESTCOND_V); END_OP(); BEGIN_OP(BL); COND_BRANCH(TESTCOND_L); END_OP(); BEGIN_OP(BE); COND_BRANCH(TESTCOND_E); END_OP(); BEGIN_OP(BNH); COND_BRANCH(TESTCOND_NH); END_OP(); BEGIN_OP(BN); COND_BRANCH(TESTCOND_N); END_OP(); BEGIN_OP(BR); COND_BRANCH(true); END_OP(); BEGIN_OP(BLT); COND_BRANCH(TESTCOND_LT); END_OP(); BEGIN_OP(BLE); COND_BRANCH(TESTCOND_LE); END_OP(); BEGIN_OP(BNV); COND_BRANCH(TESTCOND_NV); END_OP(); BEGIN_OP(BNL); COND_BRANCH(TESTCOND_NL); END_OP(); BEGIN_OP(BNE); COND_BRANCH(TESTCOND_NE); END_OP(); BEGIN_OP(BH); COND_BRANCH(TESTCOND_H); END_OP(); BEGIN_OP(BP); COND_BRANCH(TESTCOND_P); END_OP(); BEGIN_OP(BGE); COND_BRANCH(TESTCOND_GE); END_OP(); BEGIN_OP(BGT); COND_BRANCH(TESTCOND_GT); END_OP(); BEGIN_OP(JR); ADDCLOCK(3); RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE); if(RB_AccurateMode) { BRANCH_ALIGN_CHECK(PC); } RB_ADDBT(old_PC, RB_GETPC(), 0); END_OP(); BEGIN_OP(JAL); ADDCLOCK(3); P_REG[31] = RB_GETPC() + 4; RB_PCRELCHANGE(sign_26(arg1) & 0xFFFFFFFE); if(RB_AccurateMode) { BRANCH_ALIGN_CHECK(PC); } RB_ADDBT(old_PC, RB_GETPC(), 0); END_OP(); BEGIN_OP(MOVEA); ADDCLOCK(1); SetPREG(arg3, P_REG[arg2] + sign_16(arg1)); END_OP(); BEGIN_OP(ADDI); ADDCLOCK(1); uint32 temp = P_REG[arg2] + sign_16(arg1); SetFlag(PSW_OV, ((P_REG[arg2]^(~sign_16(arg1)))&(P_REG[arg2]^temp))&0x80000000); SetFlag(PSW_CY, (uint32)temp < P_REG[arg2]); SetPREG(arg3, (uint32)temp); SetSZ(P_REG[arg3]); END_OP(); BEGIN_OP(ORI); ADDCLOCK(1); SetPREG(arg3, arg1 | P_REG[arg2]); SetFlag(PSW_OV, false); SetSZ(P_REG[arg3]); END_OP(); BEGIN_OP(ANDI); ADDCLOCK(1); SetPREG(arg3, (arg1 & P_REG[arg2])); SetFlag(PSW_OV, false); SetSZ(P_REG[arg3]); END_OP(); BEGIN_OP(XORI); ADDCLOCK(1); SetPREG(arg3, arg1 ^ P_REG[arg2]); SetFlag(PSW_OV, false); SetSZ(P_REG[arg3]); END_OP(); BEGIN_OP(MOVHI); ADDCLOCK(1); SetPREG(arg3, (arg1 << 16) + P_REG[arg2]); END_OP(); // LD.B BEGIN_OP(LD_B); ADDCLOCK(1); tmp2 = (sign_16(arg1)+P_REG[arg2])&0xFFFFFFFF; SetPREG(arg3, sign_8(MemRead8(timestamp, tmp2))); //should be 3 clocks when executed alone, 2 when precedes another LD, or 1 //when precedes an instruction with many clocks (I'm guessing FP, MUL, DIV, etc) if(lastop >= 0) { if(lastop == LASTOP_LD) { ADDCLOCK(1); } else { ADDCLOCK(2); } } lastop = LASTOP_LD; END_OP_SKIPLO(); // LD.H BEGIN_OP(LD_H); ADDCLOCK(1); tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE; SetPREG(arg3, sign_16(MemRead16(timestamp, tmp2))); if(lastop >= 0) { if(lastop == LASTOP_LD) { ADDCLOCK(1); } else { ADDCLOCK(2); } } lastop = LASTOP_LD; END_OP_SKIPLO(); // LD.W BEGIN_OP(LD_W); ADDCLOCK(1); tmp2 = (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC; if(MemReadBus32[tmp2 >> 24]) { SetPREG(arg3, MemRead32(timestamp, tmp2)); if(lastop >= 0) { if(lastop == LASTOP_LD) { ADDCLOCK(1); } else { ADDCLOCK(2); } } } else { SetPREG(arg3, MemRead16(timestamp, tmp2) | (MemRead16(timestamp, tmp2 | 2) << 16)); if(lastop >= 0) { if(lastop == LASTOP_LD) { ADDCLOCK(3); } else { ADDCLOCK(4); } } } lastop = LASTOP_LD; END_OP_SKIPLO(); // ST.B BEGIN_OP(ST_B); ADDCLOCK(1); MemWrite8(timestamp, sign_16(arg2)+P_REG[arg3], P_REG[arg1] & 0xFF); if(lastop == LASTOP_ST) { ADDCLOCK(1); } lastop = LASTOP_ST; END_OP_SKIPLO(); // ST.H BEGIN_OP(ST_H); ADDCLOCK(1); MemWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE, P_REG[arg1] & 0xFFFF); if(lastop == LASTOP_ST) { ADDCLOCK(1); } lastop = LASTOP_ST; END_OP_SKIPLO(); // ST.W BEGIN_OP(ST_W); ADDCLOCK(1); tmp2 = (sign_16(arg2)+P_REG[arg3]) & 0xFFFFFFFC; if(MemWriteBus32[tmp2 >> 24]) { MemWrite32(timestamp, tmp2, P_REG[arg1]); if(lastop == LASTOP_ST) { ADDCLOCK(1); } } else { MemWrite16(timestamp, tmp2, P_REG[arg1] & 0xFFFF); MemWrite16(timestamp, tmp2 | 2, P_REG[arg1] >> 16); if(lastop == LASTOP_ST) { ADDCLOCK(3); } } lastop = LASTOP_ST; END_OP_SKIPLO(); // IN.B BEGIN_OP(IN_B); { ADDCLOCK(3); SetPREG(arg3, IORead8(timestamp, sign_16(arg1)+P_REG[arg2])); } lastop = LASTOP_IN; END_OP_SKIPLO(); // IN.H BEGIN_OP(IN_H); { ADDCLOCK(3); SetPREG(arg3, IORead16(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFE)); } lastop = LASTOP_IN; END_OP_SKIPLO(); // IN.W BEGIN_OP(IN_W); if(IORead32) { ADDCLOCK(3); SetPREG(arg3, IORead32(timestamp, (sign_16(arg1)+P_REG[arg2]) & 0xFFFFFFFC)); } else { uint32 eff_addr = (sign_16(arg1) + P_REG[arg2]) & 0xFFFFFFFC; ADDCLOCK(5); SetPREG(arg3, IORead16(timestamp, eff_addr) | ((IORead16(timestamp, eff_addr | 2) << 16))); } lastop = LASTOP_IN; END_OP_SKIPLO(); // OUT.B BEGIN_OP(OUT_B); ADDCLOCK(1); IOWrite8(timestamp, sign_16(arg2)+P_REG[arg3],P_REG[arg1]&0xFF); if(lastop == LASTOP_OUT) { ADDCLOCK(1); } lastop = LASTOP_OUT; END_OP_SKIPLO(); // OUT.H BEGIN_OP(OUT_H); ADDCLOCK(1); IOWrite16(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFE,P_REG[arg1]&0xFFFF); if(lastop == LASTOP_OUT) { ADDCLOCK(1); } lastop = LASTOP_OUT; END_OP_SKIPLO(); // OUT.W BEGIN_OP(OUT_W); ADDCLOCK(1); if(IOWrite32) IOWrite32(timestamp, (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC,P_REG[arg1]); else { uint32 eff_addr = (sign_16(arg2)+P_REG[arg3])&0xFFFFFFFC; IOWrite16(timestamp, eff_addr, P_REG[arg1] & 0xFFFF); IOWrite16(timestamp, eff_addr | 2, P_REG[arg1] >> 16); } if(lastop == LASTOP_OUT) { if(IOWrite32) { ADDCLOCK(1); } else { ADDCLOCK(3); } } lastop = LASTOP_OUT; END_OP_SKIPLO(); BEGIN_OP(NOP); (void)arg1; // arg1 is unused. ADDCLOCK(1); RB_INCPCBY2(); END_OP(); BEGIN_OP(RETI); (void)arg1; // arg1 is unused. ADDCLOCK(10); //Return from Trap/Interupt if(S_REG[PSW] & PSW_NP) { // Read the FE Reg RB_SETPC(S_REG[FEPC] & 0xFFFFFFFE); S_REG[PSW] = S_REG[FEPSW]; } else { //Read the EI Reg Interupt RB_SETPC(S_REG[EIPC] & 0xFFFFFFFE); S_REG[PSW] = S_REG[EIPSW]; } RecalcIPendingCache(); RB_ADDBT(old_PC, RB_GETPC(), 0); END_OP(); BEGIN_OP(MUL); ADDCLOCK(13); uint64 temp = (int64)(int32)P_REG[arg1] * (int32)P_REG[arg2]; SetPREG(30, (uint32)(temp >> 32)); SetPREG(arg2, temp); SetSZ(P_REG[arg2]); SetFlag(PSW_OV, temp != (uint64)(int64)(int32)(uint32)temp); lastop = -1; END_OP_SKIPLO(); BEGIN_OP(MULU); ADDCLOCK(13); uint64 temp = (uint64)P_REG[arg1] * (uint64)P_REG[arg2]; SetPREG(30, (uint32)(temp >> 32)); SetPREG(arg2, (uint32)temp); SetSZ(P_REG[arg2]); SetFlag(PSW_OV, temp != (uint32)temp); lastop = -1; END_OP_SKIPLO(); BEGIN_OP(DIVU); ADDCLOCK(36); if(P_REG[arg1] == 0) // Divide by zero! { RB_DECPCBY2(); Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV); CHECK_HALTED(); } else { // Careful here, since arg2 can be == 30 uint32 quotient = (uint32)P_REG[arg2] / (uint32)P_REG[arg1]; uint32 remainder = (uint32)P_REG[arg2] % (uint32)P_REG[arg1]; SetPREG(30, remainder); SetPREG(arg2, quotient); SetFlag(PSW_OV, false); SetSZ(quotient); } lastop = -1; END_OP_SKIPLO(); BEGIN_OP(DIV); //if(P_REG[arg1] & P_REG[arg2] & 0x80000000) //{ // printf("Div: %08x %08x\n", P_REG[arg1], P_REG[arg2]); //} ADDCLOCK(38); if((uint32)P_REG[arg1] == 0) // Divide by zero! { RB_DECPCBY2(); Exception(ZERO_DIV_HANDLER_ADDR, ECODE_ZERO_DIV); CHECK_HALTED(); } else { if((P_REG[arg2]==0x80000000)&&(P_REG[arg1]==0xFFFFFFFF)) { SetFlag(PSW_OV, true); P_REG[30]=0; SetPREG(arg2, 0x80000000); SetSZ(P_REG[arg2]); } else { // Careful here, since arg2 can be == 30 uint32 quotient = (int32)P_REG[arg2] / (int32)P_REG[arg1]; uint32 remainder = (int32)P_REG[arg2] % (int32)P_REG[arg1]; SetPREG(30, remainder); SetPREG(arg2, quotient); SetFlag(PSW_OV, false); SetSZ(quotient); } } lastop = -1; END_OP_SKIPLO(); BEGIN_OP(FPP); ADDCLOCK(1); fpu_subop(timestamp, arg3, arg1, arg2); lastop = -1; CHECK_HALTED(); END_OP_SKIPLO(); BEGIN_OP(BSTR); if(!in_bstr) { ADDCLOCK(1); } if(bstr_subop(timestamp, arg2, arg1)) { RB_DECPCBY2(); in_bstr = true; in_bstr_to = tmpop; } else { in_bstr = false; have_src_cache = have_dst_cache = false; } END_OP(); BEGIN_OP(HALT); (void)arg1; // arg1 is unused. ADDCLOCK(1); Halted = HALT_HALT; //printf("Untested opcode: HALT\n"); END_OP(); BEGIN_OP(TRAP); (void)arg2; // arg2 is unused. ADDCLOCK(15); Exception(TRAP_HANDLER_BASE + (arg1 & 0x10), ECODE_TRAP_BASE + (arg1 & 0x1F)); CHECK_HALTED(); END_OP(); BEGIN_OP(CAXI); //printf("Untested opcode: caxi\n"); // Lock bus(N/A) ADDCLOCK(26); { uint32 addr, tmp, compare_temp; uint32 to_write; addr = sign_16(arg1) + P_REG[arg2]; addr &= ~3; if(MemReadBus32[addr >> 24]) tmp = MemRead32(timestamp, addr); else tmp = MemRead16(timestamp, addr) | (MemRead16(timestamp, addr | 2) << 16); compare_temp = P_REG[arg3] - tmp; SetSZ(compare_temp); SetFlag(PSW_OV, ((P_REG[arg3]^tmp)&(P_REG[arg3]^compare_temp))&0x80000000); SetFlag(PSW_CY, compare_temp > P_REG[arg3]); if(!compare_temp) // If they're equal... to_write = P_REG[30]; else to_write = tmp; if(MemWriteBus32[addr >> 24]) MemWrite32(timestamp, addr, to_write); else { MemWrite16(timestamp, addr, to_write & 0xFFFF); MemWrite16(timestamp, addr | 2, to_write >> 16); } P_REG[arg3] = tmp; } // Unlock bus(N/A) END_OP(); op_INT_HANDLER: { int iNum = ilevel; S_REG[EIPC] = GetPC(); S_REG[EIPSW] = S_REG[PSW]; SetPC(0xFFFFFE00 | (iNum << 4)); RB_ADDBT(old_PC, RB_GETPC(), 0xFE00 | (iNum << 4)); S_REG[ECR] = 0xFE00 | (iNum << 4); S_REG[PSW] |= PSW_EP; S_REG[PSW] |= PSW_ID; S_REG[PSW] &= ~PSW_AE; // Now, set need to set the interrupt enable level to he level that is being processed + 1, // saturating at 15. iNum++; if(iNum > 0x0F) iNum = 0x0F; S_REG[PSW] &= ~PSW_IA; S_REG[PSW] |= iNum << 16; // Accepting an interrupt takes us out of normal HALT status, of course! Halted = HALT_NONE; // Invalidate our bitstring state(forces the instruction to be re-read, and the r/w buffers reloaded). in_bstr = false; have_src_cache = false; have_dst_cache = false; IPendingCache = 0; goto OpFinished; } BEGIN_OP(INVALID); RB_DECPCBY2(); if(!RB_AccurateMode) { RB_SETPC(RB_GETPC()); if((uint32)(RB_RDOP(0, 0) >> 9) != opcode) { //printf("Trampoline: %08x %02x\n", RB_GETPC(), opcode >> 1); } else { ADDCLOCK(1); Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); CHECK_HALTED(); } } else { ADDCLOCK(1); Exception(INVALID_OP_HANDLER_ADDR, ECODE_INVALID_OP); CHECK_HALTED(); } END_OP(); } OpFinished: ; lastop = opcode; OpFinishedSkipLO: ; } // end while(timestamp_rl < next_event_ts) next_event_ts = event_handler(timestamp_rl); //printf("Next: %d, Cur: %d\n", next_event_ts, timestamp); } v810_timestamp = timestamp_rl; libretro-common/include/compat/getopt.h000664 001750 001750 00000005233 12733066344 021406 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/hw_cpu/v810/v810_cpuD.cpp000664 001750 001750 00000037112 12733066344 017633 0ustar00sergiosergio000000 000000 /* V810 Emulator * * Copyright (C) 2006 David Tucker * * 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 */ ////////////////////////////////////////////////////////// // CPU Debug routines //what do we realy need? //#include //#include //#include //#include #include "../../mednafen.h" #include "v810_opt.h" #include "v810_cpu.h" #include "v810_cpuD.h" //////////////////////////////////////////////////////////// // Defines //Structure to store an element in our linked list // used to dynamicaly dissasemble a rom typedef struct dasms { int offset; uint32 PC; uint32 jump; struct dasms * nextElement; } dasmS; typedef struct { int addr_mode; // Addressing mode const char * opname; // Opcode name (string) } operation; static const operation optable[80] = { { AM_I, "mov " }, // 0x00 { AM_I, "add " }, // 0x01 { AM_I, "sub " }, // 0x02 { AM_I, "cmp " }, // 0x03 { AM_I, "shl " }, // 0x04 { AM_I, "shr " }, // 0x05 { AM_I, "jmp " }, // 0x06 { AM_I, "sar " }, // 0x07 { AM_I, "mul " }, // 0x08 { AM_I, "div " }, // 0x09 { AM_I, "mulu " }, // 0x0A { AM_I, "divu " }, // 0x0B { AM_I, "or " }, // 0x0C { AM_I, "and " }, // 0x0D { AM_I, "xor " }, // 0x0E { AM_I, "not " }, // 0x0F { AM_II, "mov " }, // 0x10 // Imediate { AM_II, "add " }, // 0x11 { AM_II, "setf " }, // 0x12 { AM_II, "cmp " }, // 0x13 { AM_II, "shl " }, // 0x14 { AM_II, "shr " }, // 0x15 {0x8000|AM_IX,"ei " }, // 0x16 // EI(VB only) { AM_II, "sar " }, // 0x17 { AM_II, "trap " }, // 0x18 { AM_IX, "reti " }, // 0x19 //BRKRETI { AM_IX, "halt " }, // 0x1A //STBY {AM_UDEF, "??? " }, // 0x1B // Unknown { AM_II, "ldsr " }, // 0x1C { AM_II, "stsr " }, // 0x1D {0x8000|AM_IX,"di " }, // 0x1E // DI(VB only) {AM_BSTR, "BSTR " }, // 0x1F // Special Bit String Instructions {AM_UDEF, "??? " }, // 0x20 // Unknown // This is a fudg on our part {AM_UDEF, "??? " }, // 0x21 // Unknown // We have 6 and 7 bit instructions {AM_UDEF, "??? " }, // 0x22 // Unknown // this is filld in by the Conditional Branch Instructions {AM_UDEF, "??? " }, // 0x23 // Unknown {AM_UDEF, "??? " }, // 0x24 // Unknown {AM_UDEF, "??? " }, // 0x25 // Unknown {AM_UDEF, "??? " }, // 0x26 // Unknown {AM_UDEF, "??? " }, // 0x27 // Unknown { AM_V, "movea" }, // 0x28 { AM_V, "addi " }, // 0x29 { AM_IV, "jr " }, // 0x2A { AM_IV, "jal " }, // 0x2B { AM_V, "ori " }, // 0x2C { AM_V, "andi " }, // 0x2D { AM_V, "xori " }, // 0x2E { AM_V, "movhi" }, // 0x2F { AM_VIa, "ld.b " }, // 0x30 { AM_VIa, "ld.h " }, // 0x31 {AM_UDEF, "??? " }, // 0x32 // Unknown { AM_VIa, "ld.w " }, // 0x33 { AM_VIb, "st.b " }, // 0x34 { AM_VIb, "st.h " }, // 0x35 {AM_UDEF, "??? " }, // 0x36 // Unknown { AM_VIb, "st.w " }, // 0x37 { AM_VIa, "in.b " }, // 0x38 { AM_VIa, "in.h " }, // 0x39 { AM_VIa, "caxi " }, // 0x3A { AM_VIa, "in.w " }, // 0x3B { AM_VIb, "out.b" }, // 0x3C { AM_VIb, "out.h" }, // 0x3D { AM_FPP, "FPP " }, // 0x3E //Floating Point Instruction, Special Case { AM_VIb, "out.w" }, // 0x3F { AM_III, "bv " }, // 0x40 { AM_III, "bl " }, // 0x41 //BC 0x41 { AM_III, "be " }, // 0x42 //BZ 0x42 { AM_III, "bnh " }, // 0x43 { AM_III, "bn " }, // 0x44 { AM_III, "br " }, // 0x45 { AM_III, "blt " }, // 0x46 { AM_III, "ble " }, // 0x47 { AM_III, "bnv " }, // 0x48 { AM_III, "bnl " }, // 0x49 //BNC 0x49 { AM_III, "bne " }, // 0x4A //BNZ 0x4A { AM_III, "bh " }, // 0x4B { AM_III, "bp " }, // 0x4C { AM_III, "nop " }, // 0x4D { AM_III, "bge " }, // 0x4E { AM_III, "bgt " } // 0x4F }; // All instructions greater than 0x50 are undefined (this should not be posible of cource) //Structure for holding the SubOpcodes, Same as above, without the InsType. typedef struct { const char * opname; // Opcode name (string) } suboperation; // Bit String Subopcodes static const suboperation bssuboptable[16] = { { "SCH0BSU" }, // 0x00 { "SCH0BSD" }, // 0x01 { "SCH1BSU" }, // 0x02 { "SCH1BSD" }, // 0x03 { "BError4" }, // 0x04 // Unknown { "BError5" }, // 0x05 // Unknown { "BError6" }, // 0x06 // Unknown { "BError7" }, // 0x07 // Unknown { "ORBSU " }, // 0x08 { "ANDBSU " }, // 0x09 { "XORBSU " }, // 0x0A { "MOVBSU " }, // 0x0B { "ORNBSU " }, // 0x0C { "ANDNBSU" }, // 0x0D { "XORNBSU" }, // 0x0E { "NOTBSU " } // 0x0F }; // Floating Point Subopcodes static const suboperation fpsuboptable[16] = { { "cmpf.s " }, // 0x00 { "FError1" }, // 0x01 // Unknown { "cvt.ws " }, // 0x02 { "cvt.sw " }, // 0x03 { "addf.s " }, // 0x04 { "subf.s " }, // 0x05 { "mulf.s " }, // 0x06 { "divf.s " }, // 0x07 { "FError8" }, // 0x08 // Invalid { "FError9" }, // 0x09 // Invalid { "FErrorA" }, // 0x0A // Invalid { "FErrorB" }, // 0x0B // Invalid { "FErrorC" }, // 0x0C // Invalid { "FErrorD" }, // 0x0D // Invalid { "FErrorE" }, // 0x0E // Invalid { "FErrorF" } // 0x0F // Invalid }; static const suboperation fpsuboptable_vb[16] = { { "cmpf.s " }, // 0x00 { "FError1" }, // 0x01 // Unknown { "cvt.ws " }, // 0x02 { "cvt.sw " }, // 0x03 { "addf.s " }, // 0x04 { "subf.s " }, // 0x05 { "mulf.s " }, // 0x06 { "divf.s " }, // 0x07 { "XB" }, // 0x08 // undocumented { "XH" }, // 0x09 // undocumented //VFishing??? { "REV" }, // 0x0A // undocumented { "trnc.sw" }, // 0x0B { "MPYHW" }, // 0x0C // undocumented { "FErrorD" }, // 0x0D // Unknown { "FErrorE" }, // 0x0E // Unknown { "FErrorF" } // 0x0F // Unknown }; static const char *pretty_preg_names[32] = { "r0", "r1", "hsp", "sp", "gp", "tp", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "lp", }; static const char *pretty_sreg_names[32] = { "sr0(eipc)", "sr1(eipsw)", "sr2(fepc)", "sr3(fepsw)", "sr4(ecr)", "sr5(psw)", "sr6(pir)", "sr7(tkcw)", "sr8(invalid)", "sr9(invalid)", "sr10(invalid)", "sr11(invalid)", "sr12(invalid)", "sr13(invalid)", "sr14(invalid)", "sr15(invalid)", "sr16(invalid)", "sr17(invalid)", "sr18(invalid)", "sr19(invalid)", "sr20(invalid)", "sr21(invalid)", "sr22(invalid)", "sr23(invalid)", "sr24(chcw)", "sr25(adtre)", "sr26(invalid)", "sr27(invalid)", "sr28(invalid)", "sr29(invalid)", "sr30(invalid)", "sr31(invalid)" }; void v810_dis(uint32 &tPC, int num, char *buf, uint16 (*rhword)(uint32), bool vbmode) { int lowB, highB, lowB2, highB2; // up to 4 bytes for instruction (either 16 or 32 bits) int opcode, arg1, arg2, arg3; int i = 0; buf[0] = 0; for(i = 0; i< num; i++) { const uint16 hw0 = rhword(tPC); const uint16 hw1 = rhword(tPC + 2); lowB = hw0 & 0xFF; highB = hw0 >> 8; lowB2 = hw1 & 0xFF; highB2 = hw1 >> 8; opcode = highB >> 2; if((highB & 0xE0) == 0x80) // Special opcode format for opcode = (highB >> 1); // type III instructions. if((opcode > 0x4F) | (opcode < 0)) { //Error Invalid opcode! sprintf(&buf[strlen(buf)], "0x%04x", hw0); tPC += 2; } int am = optable[opcode].addr_mode; if((am & 0x8000) && !vbmode) am = AM_UDEF; am &= ~0x8000; switch(am) { case AM_I: // Do the same Ither way =) arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); if (opcode == JMP) { sprintf(&buf[strlen(buf)],"%s [%s]", optable[opcode].opname, pretty_preg_names[arg2]); } else { sprintf(&buf[strlen(buf)],"%s %s, %s", optable[opcode].opname, pretty_preg_names[arg2], pretty_preg_names[arg1]); } tPC += 2; // 16 bit instruction break; case AM_II: arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); if(opcode == LDSR) { sprintf(&buf[strlen(buf)],"%s %s, %s", optable[opcode].opname, pretty_preg_names[arg1], pretty_sreg_names[arg2]); } else if(opcode == STSR) { sprintf(&buf[strlen(buf)],"%s %s, %s", optable[opcode].opname, pretty_sreg_names[arg2], pretty_preg_names[arg1]); } else if(opcode == ADD_I || opcode == CMP_I) { sprintf(&buf[strlen(buf)],"%s %d, %s", optable[opcode].opname, sign_5(arg2), pretty_preg_names[arg1]); } else { sprintf(&buf[strlen(buf)],"%s %d, %s", optable[opcode].opname, arg2, pretty_preg_names[arg1]); } tPC += 2; // 16 bit instruction break; case AM_III: arg1 = ((highB & 0x1) << 8) + (lowB & 0xFE); if(opcode == NOP) sprintf(&buf[strlen(buf)],"%s", optable[opcode].opname); else sprintf(&buf[strlen(buf)],"%s %08x", optable[opcode].opname, tPC + sign_9(arg1)); tPC += 2; // 16 bit instruction break; case AM_IV: arg1 = ((highB & 0x3) << 24) + (lowB << 16) + (highB2 << 8) + lowB2; sprintf(&buf[strlen(buf)],"%s %08x", optable[opcode].opname, tPC + sign_26(arg1)); tPC += 4; // 32 bit instruction break; case AM_V: arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); arg3 = (highB2 << 8) + lowB2; // TODO: What would be the best way to disassemble the MOVEA instruction? //if(opcode == MOVEA) // sprintf(&buf[strlen(buf)],"%s 0x%X, %s, %s", optable[opcode].opname, (uint32)(int32)(int16)(uint16)arg3, pretty_preg_names[arg2], pretty_preg_names[arg1] ); //else sprintf(&buf[strlen(buf)],"%s 0x%X, %s, %s", optable[opcode].opname, arg3, pretty_preg_names[arg2], pretty_preg_names[arg1] ); tPC += 4; // 32 bit instruction break; case AM_VIa: // Mode6 form1 arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); arg3 = (highB2 << 8) + lowB2; if(!arg3) // Don't bother printing offset if it's 0 sprintf(&buf[strlen(buf)],"%s [%s], %s", optable[opcode].opname, pretty_preg_names[arg2], pretty_preg_names[arg1]); else if(sign_16(arg3) >= 0) // Make disassembly prettier if it's a positive offset sprintf(&buf[strlen(buf)],"%s 0x%04x[%s], %s", optable[opcode].opname, sign_16(arg3), pretty_preg_names[arg2], pretty_preg_names[arg1]); else sprintf(&buf[strlen(buf)],"%s %d[%s], %s", optable[opcode].opname, sign_16(arg3), pretty_preg_names[arg2], pretty_preg_names[arg1]); tPC += 4; // 32 bit instruction break; case AM_VIb: // Mode6 form2 arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); arg3 = (highB2 << 8) + lowB2; // whats the order??? 2,3,1 or 1,3,2 if(!arg3) // Don't bother printing offset if it's 0 sprintf(&buf[strlen(buf)],"%s %s, [%s]", optable[opcode].opname, pretty_preg_names[arg1], pretty_preg_names[arg2]); else if(sign_16(arg3) >= 0) // Make disassembly prettier if it's a positive offset sprintf(&buf[strlen(buf)],"%s %s, 0x%04x[%s]", optable[opcode].opname, pretty_preg_names[arg1], sign_16(arg3), pretty_preg_names[arg2]); else sprintf(&buf[strlen(buf)],"%s %s, %d[%s]", optable[opcode].opname, pretty_preg_names[arg1], sign_16(arg3), pretty_preg_names[arg2]); tPC += 4; // 32 bit instruction break; case AM_VII: // Unhandled sprintf(&buf[strlen(buf)],"0x%2x 0x%2x 0x%2x 0x%2x", lowB, highB, lowB2, highB2); tPC +=4; // 32 bit instruction break; case AM_VIII: // Unhandled sprintf(&buf[strlen(buf)],"0x%2x 0x%2x 0x%2x 0x%2x", lowB, highB, lowB2, highB2); tPC += 4; // 32 bit instruction break; case AM_IX: arg1 = (lowB & 0x1); // Mode ID, Ignore for now sprintf(&buf[strlen(buf)],"%s", optable[opcode].opname); tPC += 2; // 16 bit instruction break; case AM_BSTR: // Bit String Subopcodes arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); if(arg2 > 15) { sprintf(&buf[strlen(buf)],"BError"); } else { //sprintf(&buf[strlen(buf)],"%s, $%d", bssuboptable[arg2].opname,arg1); sprintf(&buf[strlen(buf)], "%s", bssuboptable[arg2].opname); } tPC += 2; // 16 bit instruction break; case AM_FPP: // Floating Point Subcode arg1 = (lowB >> 5) + ((highB & 0x3) << 3); arg2 = (lowB & 0x1F); arg3 = (highB2 >> 2); if(arg3 > 15) { sprintf(&buf[strlen(buf)],"(Invalid FPU: 0x%02x)", arg3); } else { sprintf(&buf[strlen(buf)],"%s %s, %s", (vbmode ? fpsuboptable_vb[arg3].opname : fpsuboptable[arg3].opname), pretty_preg_names[arg2], pretty_preg_names[arg1]); } tPC += 4; // 32 bit instruction break; case AM_UDEF: // Invalid opcode. default: // Invalid opcode. sprintf(&buf[strlen(buf)],"0x%04x", hw0); tPC += 2; } } } mednafen/include/blargg_common.h000664 001750 001750 00000011103 12733066344 020065 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 mednafen/vb/input.cpp000664 001750 001750 00000010751 12733066344 015745 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 "vb.h" #include "input.h" static bool InstantReadHack; static bool IntPending; static uint8 *data_ptr; static uint16 PadData; static uint16 PadLatched; static uint8 SCR; static uint16 SDR; #define SCR_S_ABT_DIS 0x01 #define SCR_SI_STAT 0x02 #define SCR_HW_SI 0x04 #define SCR_SOFT_CLK 0x10 #define SCR_PARA_SI 0x20 #define SCR_K_INT_INH 0x80 static uint32 ReadBitPos; static int32 ReadCounter; static v810_timestamp_t last_ts; void VBINPUT_Init(void) { InstantReadHack = true; } void VBINPUT_SetInstantReadHack(bool enabled) { InstantReadHack = enabled; } void VBINPUT_SetInput(int port, const char *type, void *ptr) { data_ptr = (uint8 *)ptr; } uint8 VBINPUT_Read(v810_timestamp_t ×tamp, uint32 A) { uint8_t ret = 0; VBINPUT_Update(timestamp); switch(A & 0xFF) { case 0x10: if(InstantReadHack) ret = PadData; else ret = SDR & 0xFF; break; case 0x14: if(InstantReadHack) ret = PadData >> 8; else ret = SDR >> 8; break; case 0x28: ret = SCR | (0x40 | 0x08 | SCR_HW_SI); if(ReadCounter > 0) ret |= SCR_SI_STAT; break; } // printf("Input Read: %08x %02x\n", A, ret); VB_SetEvent(VB_EVENT_INPUT, (ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); return(ret); } void VBINPUT_Write(v810_timestamp_t ×tamp, uint32 A, uint8 V) { VBINPUT_Update(timestamp); //printf("Input write: %d, %08x %02x\n", timestamp, A, V); switch(A & 0xFF) { case 0x28: if((V & SCR_HW_SI) && !(SCR & SCR_S_ABT_DIS) && ReadCounter <= 0) { //printf("Start Read: %d\n", timestamp); PadLatched = PadData; ReadBitPos = 0; ReadCounter = 640; } if(V & SCR_S_ABT_DIS) { ReadCounter = 0; ReadBitPos = 0; } if(V & SCR_K_INT_INH) { IntPending = false; VBIRQ_Assert(VBIRQ_SOURCE_INPUT, IntPending); } SCR = V & (0x80 | 0x20 | 0x10 | 1); break; } VB_SetEvent(VB_EVENT_INPUT, (ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); } void VBINPUT_Frame(void) { PadData = (MDFN_de16lsb(data_ptr) << 2) | 0x2; } v810_timestamp_t VBINPUT_Update(const v810_timestamp_t timestamp) { int32 clocks = timestamp - last_ts; if(ReadCounter > 0) { ReadCounter -= clocks; while(ReadCounter <= 0) { SDR &= ~(1 << ReadBitPos); SDR |= PadLatched & (1 << ReadBitPos); ReadBitPos++; if(ReadBitPos < 16) ReadCounter += 640; else { //printf("Read End: %d\n", timestamp); if(!(SCR & SCR_K_INT_INH)) { //printf("Input IRQ: %d\n", timestamp); IntPending = true; VBIRQ_Assert(VBIRQ_SOURCE_INPUT, IntPending); } break; } } } last_ts = timestamp; return((ReadCounter > 0) ? (timestamp + ReadCounter) : VB_EVENT_NONONO); } void VBINPUT_ResetTS(void) { last_ts = 0; } void VBINPUT_Power(void) { last_ts = 0; PadData = 0; PadLatched = 0; SDR = 0; SCR = 0; ReadBitPos = 0; ReadCounter = 0; IntPending = false; VBIRQ_Assert(VBIRQ_SOURCE_INPUT, 0); } int VBINPUT_StateAction(StateMem *sm, int load, int data_only) { SFORMAT StateRegs[] = { SFVAR(PadData), SFVAR(PadLatched), SFVAR(SCR), SFVAR(SDR), SFVAR(ReadBitPos), SFVAR(ReadCounter), SFVAR(IntPending), SFEND }; int ret = MDFNSS_StateAction(sm, load, data_only, StateRegs, "INPUT"); if(load) { } return(ret); } mednafen/hw_cpu/v810/fpu-new/softfloat-specialize000664 001750 001750 00000021770 12733066344 023114 0ustar00sergiosergio000000 000000 /*============================================================================ This C source fragment is part of the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b. Written by John R. Hauser. This work was made possible in part by the International Computer Science Institute, located at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding was partially provided by the National Science Foundation under grant MIP-9311980. The original version of this code was written as part of a project to build a fixed-point vector processor in collaboration with the University of California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. More information is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ arithmetic/SoftFloat.html'. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. Derivative works are acceptable, even for commercial purposes, so long as (1) the source code for the derivative work includes prominent notice that the work is derivative, and (2) the source code includes prominent notice with these four paragraphs for those parts of this code that are retained. =============================================================================*/ /*---------------------------------------------------------------------------- | Underflow tininess-detection mode, statically initialized to default value. | (The declaration in `softfloat.h' must match the `int8' type here.) *----------------------------------------------------------------------------*/ int8 float_detect_tininess = float_tininess_after_rounding; /*---------------------------------------------------------------------------- | Raises the exceptions specified by `flags'. Floating-point traps can be | defined here if desired. It is currently not possible for such a trap | to substitute a result value. If traps are not implemented, this routine | should be simply `float_exception_flags |= flags;'. *----------------------------------------------------------------------------*/ void float_raise( int8 flags ) { float_exception_flags |= flags; } /*---------------------------------------------------------------------------- | Internal canonical NaN format. *----------------------------------------------------------------------------*/ typedef struct { flag sign; bits32 high, low; } commonNaNT; /*---------------------------------------------------------------------------- | The pattern for a default generated single-precision NaN. *----------------------------------------------------------------------------*/ enum { float32_default_nan = 0xFFFFFFFF }; /*---------------------------------------------------------------------------- | Returns 1 if the single-precision floating-point value `a' is a NaN; | otherwise returns 0. *----------------------------------------------------------------------------*/ flag float32_is_nan( float32 a ) { return ( 0xFF000000 < (bits32) ( a<<1 ) ); } /*---------------------------------------------------------------------------- | Returns 1 if the single-precision floating-point value `a' is a signaling | NaN; otherwise returns 0. *----------------------------------------------------------------------------*/ flag float32_is_signaling_nan( float32 a ) { return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); } /*---------------------------------------------------------------------------- | Returns the result of converting the single-precision floating-point NaN | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ static commonNaNT float32ToCommonNaN( float32 a ) { commonNaNT z; if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); z.sign = a>>31; z.low = 0; z.high = a<<9; return z; } /*---------------------------------------------------------------------------- | Returns the result of converting the canonical NaN `a' to the single- | precision floating-point format. *----------------------------------------------------------------------------*/ static float32 commonNaNToFloat32( commonNaNT a ) { return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>9 ); } /*---------------------------------------------------------------------------- | Takes two single-precision floating-point values `a' and `b', one of which | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ static float32 propagateFloat32NaN( float32 a, float32 b ) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; aIsNaN = float32_is_nan( a ); aIsSignalingNaN = float32_is_signaling_nan( a ); bIsNaN = float32_is_nan( b ); bIsSignalingNaN = float32_is_signaling_nan( b ); a |= 0x00400000; b |= 0x00400000; if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); if ( aIsNaN ) { return ( aIsSignalingNaN & bIsNaN ) ? b : a; } else { return b; } } /*---------------------------------------------------------------------------- | The pattern for a default generated double-precision NaN. The `high' and | `low' values hold the most- and least-significant bits, respectively. *----------------------------------------------------------------------------*/ enum { float64_default_nan_high = 0xFFFFFFFF, float64_default_nan_low = 0xFFFFFFFF }; /*---------------------------------------------------------------------------- | Returns 1 if the double-precision floating-point value `a' is a NaN; | otherwise returns 0. *----------------------------------------------------------------------------*/ flag float64_is_nan( float64 a ) { return ( 0xFFE00000 <= (bits32) ( a.high<<1 ) ) && ( a.low || ( a.high & 0x000FFFFF ) ); } /*---------------------------------------------------------------------------- | Returns 1 if the double-precision floating-point value `a' is a signaling | NaN; otherwise returns 0. *----------------------------------------------------------------------------*/ flag float64_is_signaling_nan( float64 a ) { return ( ( ( a.high>>19 ) & 0xFFF ) == 0xFFE ) && ( a.low || ( a.high & 0x0007FFFF ) ); } /*---------------------------------------------------------------------------- | Returns the result of converting the double-precision floating-point NaN | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid | exception is raised. *----------------------------------------------------------------------------*/ static commonNaNT float64ToCommonNaN( float64 a ) { commonNaNT z; if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); z.sign = a.high>>31; shortShift64Left( a.high, a.low, 12, &z.high, &z.low ); return z; } /*---------------------------------------------------------------------------- | Returns the result of converting the canonical NaN `a' to the double- | precision floating-point format. *----------------------------------------------------------------------------*/ static float64 commonNaNToFloat64( commonNaNT a ) { float64 z; shift64Right( a.high, a.low, 12, &z.high, &z.low ); z.high |= ( ( (bits32) a.sign )<<31 ) | 0x7FF80000; return z; } /*---------------------------------------------------------------------------- | Takes two double-precision floating-point values `a' and `b', one of which | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a | signaling NaN, the invalid exception is raised. *----------------------------------------------------------------------------*/ static float64 propagateFloat64NaN( float64 a, float64 b ) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; aIsNaN = float64_is_nan( a ); aIsSignalingNaN = float64_is_signaling_nan( a ); bIsNaN = float64_is_nan( b ); bIsSignalingNaN = float64_is_signaling_nan( b ); a.high |= 0x00080000; b.high |= 0x00080000; if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); if ( aIsNaN ) { return ( aIsSignalingNaN & bIsNaN ) ? b : a; } else { return b; } } jni/000700 001750 001750 00000000000 12733076376 012464 5ustar00sergiosergio000000 000000 mednafen/hw_cpu/v810/fpu-new/timesoftfloat.c000664 001750 001750 00000102131 12733066344 022055 0ustar00sergiosergio000000 000000 /*============================================================================ This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic Package, Release 2b. Written by John R. Hauser. This work was made possible in part by the International Computer Science Institute, located at Suite 600, 1947 Center Street, Berkeley, California 94704. Funding was partially provided by the National Science Foundation under grant MIP-9311980. The original version of this code was written as part of a project to build a fixed-point vector processor in collaboration with the University of California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. More information is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ arithmetic/SoftFloat.html'. THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. Derivative works are acceptable, even for commercial purposes, so long as (1) the source code for the derivative work includes prominent notice that the work is derivative, and (2) the source code includes prominent notice with these four paragraphs for those parts of this code that are retained. =============================================================================*/ #include #include #include #include #include #include "milieu.h" #include "softfloat.h" enum { minIterations = 1000 }; void fail( const char *message, ... ) { va_list varArgs; fputs( "timesoftfloat: ", stderr ); va_start( varArgs, message ); vfprintf( stderr, message, varArgs ); va_end( varArgs ); fputs( ".\n", stderr ); exit( EXIT_FAILURE ); } static char *functionName, *roundingModeName, *tininessModeName; static void reportTime( int32 count, long clocks ) { printf( "%8.1f kops/s: %s", ( count / ( ( (float) clocks ) / CLOCKS_PER_SEC ) ) / 1000, functionName ); if ( roundingModeName ) { fputs( ", rounding ", stdout ); fputs( roundingModeName, stdout ); if ( tininessModeName ) { fputs( ", tininess ", stdout ); fputs( tininessModeName, stdout ); fputs( " rounding", stdout ); } } fputc( '\n', stdout ); } enum { numInputs_int32 = 32 }; static const int32 inputs_int32[ numInputs_int32 ] = { 0xFFFFBB79, 0x405CF80F, 0x00000000, 0xFFFFFD04, 0xFFF20002, 0x0C8EF795, 0xF00011FF, 0x000006CA, 0x00009BFE, 0xFF4862E3, 0x9FFFEFFE, 0xFFFFFFB7, 0x0BFF7FFF, 0x0000F37A, 0x0011DFFE, 0x00000006, 0xFFF02006, 0xFFFFF7D1, 0x10200003, 0xDE8DF765, 0x00003E02, 0x000019E8, 0x0008FFFE, 0xFFFFFB5C, 0xFFDF7FFE, 0x07C42FBF, 0x0FFFE3FF, 0x040B9F13, 0xBFFFFFF8, 0x0001BF56, 0x000017F6, 0x000A908A }; static void time_a_int32_z_float32( float32 function( int32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_int32_z_float64( float64 function( int32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_int32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } enum { numInputs_float32 = 32 }; static const float32 inputs_float32[ numInputs_float32 ] = { 0x4EFA0000, 0xC1D0B328, 0x80000000, 0x3E69A31E, 0xAF803EFF, 0x3F800000, 0x17BF8000, 0xE74A301A, 0x4E010003, 0x7EE3C75D, 0xBD803FE0, 0xBFFEFF00, 0x7981F800, 0x431FFFFC, 0xC100C000, 0x3D87EFFF, 0x4103FEFE, 0xBC000007, 0xBF01F7FF, 0x4E6C6B5C, 0xC187FFFE, 0xC58B9F13, 0x4F88007F, 0xDF004007, 0xB7FFD7FE, 0x7E8001FB, 0x46EFFBFF, 0x31C10000, 0xDB428661, 0x33F89B1F, 0xA3BFEFFF, 0x537BFFBE }; static void time_a_float32_z_int32( int32 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float32_z_float64( float64 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_az_float32( float32 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_ab_float32_z_flag( flag function( float32, float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_abz_float32( float32 function( float32, float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static const float32 inputs_float32_pos[ numInputs_float32 ] = { 0x4EFA0000, 0x41D0B328, 0x00000000, 0x3E69A31E, 0x2F803EFF, 0x3F800000, 0x17BF8000, 0x674A301A, 0x4E010003, 0x7EE3C75D, 0x3D803FE0, 0x3FFEFF00, 0x7981F800, 0x431FFFFC, 0x4100C000, 0x3D87EFFF, 0x4103FEFE, 0x3C000007, 0x3F01F7FF, 0x4E6C6B5C, 0x4187FFFE, 0x458B9F13, 0x4F88007F, 0x5F004007, 0x37FFD7FE, 0x7E8001FB, 0x46EFFBFF, 0x31C10000, 0x5B428661, 0x33F89B1F, 0x23BFEFFF, 0x537BFFBE }; static void time_az_float32_pos( float32 function( float32 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { function( inputs_float32_pos[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { function( inputs_float32_pos[ inputNum ] ); inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } enum { numInputs_float64 = 32 }; static const struct { bits32 high, low; } inputs_float64[ numInputs_float64 ] = { { 0x422FFFC0, 0x08000000 }, { 0xB7E00004, 0x80000000 }, { 0xF3FD2546, 0x120B7935 }, { 0x3FF00000, 0x00000000 }, { 0xCE07F766, 0xF09588D6 }, { 0x80000000, 0x00000000 }, { 0x3FCE0004, 0x00000000 }, { 0x8313B60F, 0x0032BED8 }, { 0xC1EFFFFF, 0xC0002000 }, { 0x3FB3C75D, 0x224F2B0F }, { 0x7FD00000, 0x004000FF }, { 0xA12FFF80, 0x00001FFF }, { 0x3EE00000, 0x00FE0000 }, { 0x00100000, 0x80000004 }, { 0x41CFFFFE, 0x00000020 }, { 0x40303FFF, 0xFFFFFFFD }, { 0x3FD00000, 0x3FEFFFFF }, { 0xBFD00000, 0x10000000 }, { 0xB7FC6B5C, 0x16CA55CF }, { 0x413EEB94, 0x0B9D1301 }, { 0xC7E00200, 0x001FFFFF }, { 0x47F00021, 0xFFFFFFFE }, { 0xBFFFFFFF, 0xF80000FF }, { 0xC07FFFFF, 0xE00FFFFF }, { 0x001497A6, 0x3740C5E8 }, { 0xC4BFFFE0, 0x001FFFFF }, { 0x96FFDFFE, 0xFFFFFFFF }, { 0x403FC000, 0x000001FE }, { 0xFFD00000, 0x000001F6 }, { 0x06404000, 0x02000000 }, { 0x479CEE1E, 0x4F789FE0 }, { 0xC237FFFF, 0xFFFFFDFE } }; static void time_a_float64_z_int32( int32 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float64 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float64[ inputNum ].low; a.high = inputs_float64[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float64[ inputNum ].low; a.high = inputs_float64[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_a_float64_z_float32( float32 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float64 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float64[ inputNum ].low; a.high = inputs_float64[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float64[ inputNum ].low; a.high = inputs_float64[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_az_float64( float64 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float64 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float64[ inputNum ].low; a.high = inputs_float64[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float64[ inputNum ].low; a.high = inputs_float64[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_ab_float64_z_flag( flag function( float64, float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; float64 a, b; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float64[ inputNumA ].low; a.high = inputs_float64[ inputNumA ].high; b.low = inputs_float64[ inputNumB ].low; b.high = inputs_float64[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float64[ inputNumA ].low; a.high = inputs_float64[ inputNumA ].high; b.low = inputs_float64[ inputNumB ].low; b.high = inputs_float64[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static void time_abz_float64( float64 function( float64, float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNumA, inputNumB; float64 a, b; count = 0; inputNumA = 0; inputNumB = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float64[ inputNumA ].low; a.high = inputs_float64[ inputNumA ].high; b.low = inputs_float64[ inputNumB ].low; b.high = inputs_float64[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNumA = 0; inputNumB = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float64[ inputNumA ].low; a.high = inputs_float64[ inputNumA ].high; b.low = inputs_float64[ inputNumB ].low; b.high = inputs_float64[ inputNumB ].high; function( a, b ); inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 ); if ( inputNumA == 0 ) ++inputNumB; inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } static const struct { bits32 high, low; } inputs_float64_pos[ numInputs_float64 ] = { { 0x422FFFC0, 0x08000000 }, { 0x37E00004, 0x80000000 }, { 0x73FD2546, 0x120B7935 }, { 0x3FF00000, 0x00000000 }, { 0x4E07F766, 0xF09588D6 }, { 0x00000000, 0x00000000 }, { 0x3FCE0004, 0x00000000 }, { 0x0313B60F, 0x0032BED8 }, { 0x41EFFFFF, 0xC0002000 }, { 0x3FB3C75D, 0x224F2B0F }, { 0x7FD00000, 0x004000FF }, { 0x212FFF80, 0x00001FFF }, { 0x3EE00000, 0x00FE0000 }, { 0x00100000, 0x80000004 }, { 0x41CFFFFE, 0x00000020 }, { 0x40303FFF, 0xFFFFFFFD }, { 0x3FD00000, 0x3FEFFFFF }, { 0x3FD00000, 0x10000000 }, { 0x37FC6B5C, 0x16CA55CF }, { 0x413EEB94, 0x0B9D1301 }, { 0x47E00200, 0x001FFFFF }, { 0x47F00021, 0xFFFFFFFE }, { 0x3FFFFFFF, 0xF80000FF }, { 0x407FFFFF, 0xE00FFFFF }, { 0x001497A6, 0x3740C5E8 }, { 0x44BFFFE0, 0x001FFFFF }, { 0x16FFDFFE, 0xFFFFFFFF }, { 0x403FC000, 0x000001FE }, { 0x7FD00000, 0x000001F6 }, { 0x06404000, 0x02000000 }, { 0x479CEE1E, 0x4F789FE0 }, { 0x4237FFFF, 0xFFFFFDFE } }; static void time_az_float64_pos( float64 function( float64 ) ) { clock_t startClock, endClock; int32 count, i; int8 inputNum; float64 a; count = 0; inputNum = 0; startClock = clock(); do { for ( i = minIterations; i; --i ) { a.low = inputs_float64_pos[ inputNum ].low; a.high = inputs_float64_pos[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } count += minIterations; } while ( clock() - startClock < CLOCKS_PER_SEC ); inputNum = 0; startClock = clock(); for ( i = count; i; --i ) { a.low = inputs_float64_pos[ inputNum ].low; a.high = inputs_float64_pos[ inputNum ].high; function( a ); inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 ); } endClock = clock(); reportTime( count, endClock - startClock ); } enum { INT32_TO_FLOAT32 = 1, INT32_TO_FLOAT64, FLOAT32_TO_INT32, FLOAT32_TO_INT32_ROUND_TO_ZERO, FLOAT32_TO_FLOAT64, FLOAT32_ROUND_TO_INT, FLOAT32_ADD, FLOAT32_SUB, FLOAT32_MUL, FLOAT32_DIV, FLOAT32_REM, FLOAT32_SQRT, FLOAT32_EQ, FLOAT32_LE, FLOAT32_LT, FLOAT32_EQ_SIGNALING, FLOAT32_LE_QUIET, FLOAT32_LT_QUIET, FLOAT64_TO_INT32, FLOAT64_TO_INT32_ROUND_TO_ZERO, FLOAT64_TO_FLOAT32, FLOAT64_ROUND_TO_INT, FLOAT64_ADD, FLOAT64_SUB, FLOAT64_MUL, FLOAT64_DIV, FLOAT64_REM, FLOAT64_SQRT, FLOAT64_EQ, FLOAT64_LE, FLOAT64_LT, FLOAT64_EQ_SIGNALING, FLOAT64_LE_QUIET, FLOAT64_LT_QUIET, NUM_FUNCTIONS }; static struct { char *name; int8 numInputs; flag roundingMode, tininessMode; } functions[ NUM_FUNCTIONS ] = { { 0, 0, 0, 0 }, { "int32_to_float32", 1, TRUE, FALSE }, { "int32_to_float64", 1, FALSE, FALSE }, { "float32_to_int32", 1, TRUE, FALSE }, { "float32_to_int32_round_to_zero", 1, FALSE, FALSE }, { "float32_to_float64", 1, FALSE, FALSE }, { "float32_round_to_int", 1, TRUE, FALSE }, { "float32_add", 2, TRUE, FALSE }, { "float32_sub", 2, TRUE, FALSE }, { "float32_mul", 2, TRUE, TRUE, }, { "float32_div", 2, TRUE, FALSE }, { "float32_rem", 2, FALSE, FALSE }, { "float32_sqrt", 1, TRUE, FALSE }, { "float32_eq", 2, FALSE, FALSE }, { "float32_le", 2, FALSE, FALSE }, { "float32_lt", 2, FALSE, FALSE }, { "float32_eq_signaling", 2, FALSE, FALSE }, { "float32_le_quiet", 2, FALSE, FALSE }, { "float32_lt_quiet", 2, FALSE, FALSE }, { "float64_to_int32", 1, TRUE, FALSE }, { "float64_to_int32_round_to_zero", 1, FALSE, FALSE }, { "float64_to_float32", 1, TRUE, TRUE, }, { "float64_round_to_int", 1, TRUE, FALSE }, { "float64_add", 2, TRUE, FALSE }, { "float64_sub", 2, TRUE, FALSE }, { "float64_mul", 2, TRUE, TRUE, }, { "float64_div", 2, TRUE, FALSE }, { "float64_rem", 2, FALSE, FALSE }, { "float64_sqrt", 1, TRUE, FALSE }, { "float64_eq", 2, FALSE, FALSE }, { "float64_le", 2, FALSE, FALSE }, { "float64_lt", 2, FALSE, FALSE }, { "float64_eq_signaling", 2, FALSE, FALSE }, { "float64_le_quiet", 2, FALSE, FALSE }, { "float64_lt_quiet", 2, FALSE, FALSE } }; enum { ROUND_NEAREST_EVEN = 1, ROUND_TO_ZERO, ROUND_DOWN, ROUND_UP, NUM_ROUNDINGMODES }; enum { TININESS_BEFORE_ROUNDING = 1, TININESS_AFTER_ROUNDING, NUM_TININESSMODES }; static void timeFunctionVariety( uint8 functionCode, int8 roundingMode, int8 tininessMode ) { uint8 roundingCode; int8 tininessCode; functionName = functions[ functionCode ].name; switch ( roundingMode ) { case 0: roundingModeName = 0; roundingCode = float_round_nearest_even; break; case ROUND_NEAREST_EVEN: roundingModeName = "nearest_even"; roundingCode = float_round_nearest_even; break; case ROUND_TO_ZERO: roundingModeName = "to_zero"; roundingCode = float_round_to_zero; break; case ROUND_DOWN: roundingModeName = "down"; roundingCode = float_round_down; break; case ROUND_UP: roundingModeName = "up"; roundingCode = float_round_up; break; } float_rounding_mode = roundingCode; switch ( tininessMode ) { case 0: tininessModeName = 0; tininessCode = float_tininess_after_rounding; break; case TININESS_BEFORE_ROUNDING: tininessModeName = "before"; tininessCode = float_tininess_before_rounding; break; case TININESS_AFTER_ROUNDING: tininessModeName = "after"; tininessCode = float_tininess_after_rounding; break; } float_detect_tininess = tininessCode; switch ( functionCode ) { case INT32_TO_FLOAT32: time_a_int32_z_float32( int32_to_float32 ); break; case INT32_TO_FLOAT64: time_a_int32_z_float64( int32_to_float64 ); break; case FLOAT32_TO_INT32: time_a_float32_z_int32( float32_to_int32 ); break; case FLOAT32_TO_INT32_ROUND_TO_ZERO: time_a_float32_z_int32( float32_to_int32_round_to_zero ); break; case FLOAT32_TO_FLOAT64: time_a_float32_z_float64( float32_to_float64 ); break; case FLOAT32_ROUND_TO_INT: time_az_float32( float32_round_to_int ); break; case FLOAT32_ADD: time_abz_float32( float32_add ); break; case FLOAT32_SUB: time_abz_float32( float32_sub ); break; case FLOAT32_MUL: time_abz_float32( float32_mul ); break; case FLOAT32_DIV: time_abz_float32( float32_div ); break; case FLOAT32_REM: time_abz_float32( float32_rem ); break; case FLOAT32_SQRT: time_az_float32_pos( float32_sqrt ); break; case FLOAT32_EQ: time_ab_float32_z_flag( float32_eq ); break; case FLOAT32_LE: time_ab_float32_z_flag( float32_le ); break; case FLOAT32_LT: time_ab_float32_z_flag( float32_lt ); break; case FLOAT32_EQ_SIGNALING: time_ab_float32_z_flag( float32_eq_signaling ); break; case FLOAT32_LE_QUIET: time_ab_float32_z_flag( float32_le_quiet ); break; case FLOAT32_LT_QUIET: time_ab_float32_z_flag( float32_lt_quiet ); break; case FLOAT64_TO_INT32: time_a_float64_z_int32( float64_to_int32 ); break; case FLOAT64_TO_INT32_ROUND_TO_ZERO: time_a_float64_z_int32( float64_to_int32_round_to_zero ); break; case FLOAT64_TO_FLOAT32: time_a_float64_z_float32( float64_to_float32 ); break; case FLOAT64_ROUND_TO_INT: time_az_float64( float64_round_to_int ); break; case FLOAT64_ADD: time_abz_float64( float64_add ); break; case FLOAT64_SUB: time_abz_float64( float64_sub ); break; case FLOAT64_MUL: time_abz_float64( float64_mul ); break; case FLOAT64_DIV: time_abz_float64( float64_div ); break; case FLOAT64_REM: time_abz_float64( float64_rem ); break; case FLOAT64_SQRT: time_az_float64_pos( float64_sqrt ); break; case FLOAT64_EQ: time_ab_float64_z_flag( float64_eq ); break; case FLOAT64_LE: time_ab_float64_z_flag( float64_le ); break; case FLOAT64_LT: time_ab_float64_z_flag( float64_lt ); break; case FLOAT64_EQ_SIGNALING: time_ab_float64_z_flag( float64_eq_signaling ); break; case FLOAT64_LE_QUIET: time_ab_float64_z_flag( float64_le_quiet ); break; case FLOAT64_LT_QUIET: time_ab_float64_z_flag( float64_lt_quiet ); break; } } static void timeFunction( uint8 functionCode, int8 roundingModeIn, int8 tininessModeIn ) { int8 roundingMode, tininessMode; for ( roundingMode = 1; roundingMode < NUM_ROUNDINGMODES; ++roundingMode ) { if ( ! functions[ functionCode ].roundingMode ) { roundingMode = 0; } else if ( roundingModeIn ) { roundingMode = roundingModeIn; } for ( tininessMode = 1; tininessMode < NUM_TININESSMODES; ++tininessMode ) { if ( ! functions[ functionCode ].tininessMode ) { tininessMode = 0; } else if ( tininessModeIn ) { tininessMode = tininessModeIn; } timeFunctionVariety( functionCode, roundingMode, tininessMode ); if ( tininessModeIn || ! tininessMode ) break; } if ( roundingModeIn || ! roundingMode ) break; } } main( int argc, char **argv ) { char *argPtr; flag functionArgument; uint8 functionCode; int8 operands, roundingMode, tininessMode; if ( argc <= 1 ) goto writeHelpMessage; functionArgument = FALSE; functionCode = 0; operands = 0; roundingMode = 0; tininessMode = 0; --argc; ++argv; while ( argc && ( argPtr = argv[ 0 ] ) ) { if ( argPtr[ 0 ] == '-' ) ++argPtr; if ( strcmp( argPtr, "help" ) == 0 ) { writeHelpMessage: fputs( "timesoftfloat [