merge trunk to bgklink

git-svn-id: https://svn.code.sf.net/p/vbam/code/branches/bgk-link@1230 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
squall-leonhart 2014-03-18 10:03:06 +00:00
parent a604ebee68
commit 05435d0f34
40 changed files with 926 additions and 284 deletions

View File

@ -6,7 +6,7 @@ or when stated otherwise in the source file:
Copyright for the modifications to the files mentioned above: Copyright for the modifications to the files mentioned above:
VisualBoyAdvance-M GB/GBA emulator VisualBoyAdvance-M GB/GBA emulator
Copyright (C) 2007-2008 VBA-M development team Copyright (C) 2007-2013 VBA-M development team
All files excluding gb_apu, modified files from zlib All files excluding gb_apu, modified files from zlib

View File

@ -138,6 +138,7 @@ Spacy
DJRobX DJRobX
Jonas Quinn Jonas Quinn
kode54 kode54
Normmatt
============== ==============
Special Thanks Special Thanks
@ -172,3 +173,6 @@ kode64:
shuffle2: shuffle2:
- SFML library - SFML library
- various build fixes - various build fixes
Squarepusher
- Libretro merge

View File

@ -1,45 +1,49 @@
#ifndef SYSTEM_H #ifndef SYSTEM_H
#define SYSTEM_H #define SYSTEM_H
#include "common/Types.h" #include "common/Types.h"
#include <zlib.h> #include <zlib.h>
class SoundDriver; class SoundDriver;
struct EmulatedSystem { struct EmulatedSystem {
// main emulation function // main emulation function
void (*emuMain)(int); void (*emuMain)(int);
// reset emulator // reset emulator
void (*emuReset)(); void (*emuReset)();
// clean up memory // clean up memory
void (*emuCleanUp)(); void (*emuCleanUp)();
// load battery file // load battery file
bool (*emuReadBattery)(const char *); bool (*emuReadBattery)(const char *);
// write battery file // write battery file
bool (*emuWriteBattery)(const char *); bool (*emuWriteBattery)(const char *);
// load state #ifdef __LIBRETRO__
bool (*emuReadState)(const char *); // load state
// save state bool (*emuReadState)(const u8*, unsigned);
bool (*emuWriteState)(const char *); // load state
// load memory state (rewind) unsigned (*emuWriteState)(u8*, unsigned);
bool (*emuReadMemState)(char *, int); #else
// write memory state (rewind) // load state
bool (*emuWriteMemState)(char *, int); bool (*emuReadState)(const char *);
// write PNG file // save state
bool (*emuWritePNG)(const char *); bool (*emuWriteState)(const char *);
// write BMP file #endif
bool (*emuWriteBMP)(const char *); // load memory state (rewind)
// emulator update CPSR (ARM only) bool (*emuReadMemState)(char *, int);
void (*emuUpdateCPSR)(); // write memory state (rewind)
// emulator has debugger bool (*emuWriteMemState)(char *, int);
bool emuHasDebugger; // write PNG file
// clock ticks to emulate bool (*emuWritePNG)(const char *);
int emuCount; // write BMP file
bool (*emuWriteBMP)(const char *);
// emulator update CPSR (ARM only)
void (*emuUpdateCPSR)();
// emulator has debugger
bool emuHasDebugger;
// clock ticks to emulate
int emuCount;
}; };
extern void log(const char *,...); extern void log(const char *,...);
extern bool systemPauseOnFrame(); extern bool systemPauseOnFrame();
extern void systemGbPrint(u8 *,int,int,int,int,int); extern void systemGbPrint(u8 *,int,int,int,int,int);
extern void systemScreenCapture(int); extern void systemScreenCapture(int);
@ -56,14 +60,13 @@ extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length);
extern void systemOnSoundShutdown(); extern void systemOnSoundShutdown();
extern void systemScreenMessage(const char *); extern void systemScreenMessage(const char *);
extern void systemUpdateMotionSensor(); extern void systemUpdateMotionSensor();
extern int systemGetSensorX(); extern int systemGetSensorX();
extern int systemGetSensorY(); extern int systemGetSensorY();
extern bool systemCanChangeSoundQuality(); extern bool systemCanChangeSoundQuality();
extern void systemShowSpeed(int); extern void systemShowSpeed(int);
extern void system10Frames(int); extern void system10Frames(int);
extern void systemFrame(); extern void systemFrame();
extern void systemGbBorderOn(); extern void systemGbBorderOn();
extern void Sm60FPS_Init(); extern void Sm60FPS_Init();
extern bool Sm60FPS_CanSkipFrame(); extern bool Sm60FPS_CanSkipFrame();
extern void Sm60FPS_Sleep(); extern void Sm60FPS_Sleep();
@ -73,10 +76,8 @@ extern void DbgMsg(const char *msg, ...);
#else #else
extern void winlog(const char *,...); extern void winlog(const char *,...);
#endif #endif
extern void (*dbgOutput)(const char *s, u32 addr); extern void (*dbgOutput)(const char *s, u32 addr);
extern void (*dbgSignal)(int sig,int number); extern void (*dbgSignal)(int sig,int number);
extern u16 systemColorMap16[0x10000]; extern u16 systemColorMap16[0x10000];
extern u32 systemColorMap32[0x10000]; extern u32 systemColorMap32[0x10000];
extern u16 systemGbPalette[24]; extern u16 systemGbPalette[24];
@ -89,8 +90,6 @@ extern int systemVerbose;
extern int systemFrameSkip; extern int systemFrameSkip;
extern int systemSaveUpdateCounter; extern int systemSaveUpdateCounter;
extern int systemSpeed; extern int systemSpeed;
#define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_UPDATED 30
#define SYSTEM_SAVE_NOT_UPDATED 0 #define SYSTEM_SAVE_NOT_UPDATED 0
#endif // SYSTEM_H #endif // SYSTEM_H

View File

@ -439,6 +439,8 @@ static bool utilIsImage(const char *file)
#include <Windows.h> #include <Windows.h>
#endif #endif
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]);
IMAGE_TYPE utilFindType(const char *file) IMAGE_TYPE utilFindType(const char *file)
{ {
char buffer [2048]; char buffer [2048];
@ -453,11 +455,10 @@ IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048])
pwText = new wchar_t[dwNum]; pwText = new wchar_t[dwNum];
if(!pwText) if(!pwText)
{ {
delete []pwText; return IMAGE_UNKNOWN;
} }
MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum ); MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
char* file_conv = fex_wide_to_path( pwText); char* file_conv = fex_wide_to_path( pwText);
delete []pwText;
// if ( !utilIsImage( file_conv ) ) // TODO: utilIsArchive() instead? // if ( !utilIsImage( file_conv ) ) // TODO: utilIsArchive() instead?
// { // {
fex_t* fe = scan_arc(file_conv,utilIsImage,buffer); fex_t* fe = scan_arc(file_conv,utilIsImage,buffer);
@ -501,7 +502,7 @@ u8 *utilLoad(const char *file,
pwText = new wchar_t[dwNum]; pwText = new wchar_t[dwNum];
if(!pwText) if(!pwText)
{ {
delete []pwText; return NULL;
} }
MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum ); MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
char* file_conv = fex_wide_to_path( pwText); char* file_conv = fex_wide_to_path( pwText);

View File

@ -11,23 +11,22 @@ enum IMAGE_TYPE {
// save game // save game
typedef struct { typedef struct {
void *address; void *address;
int size; int size;
} variable_desc; } variable_desc;
bool utilWritePNGFile(const char *, int, int, u8 *); bool utilWritePNGFile(const char *, int, int, u8 *);
bool utilWriteBMPFile(const char *, int, int, u8 *); bool utilWriteBMPFile(const char *, int, int, u8 *);
void utilApplyIPS(const char *ips, u8 **rom, int *size); void utilApplyIPS(const char *ips, uint8_t **rom, int *size);
bool utilIsGBAImage(const char *); bool utilIsGBAImage(const char *);
bool utilIsGBImage(const char *); bool utilIsGBImage(const char *);
bool utilIsGzipFile(const char *); bool utilIsGzipFile(const char *);
bool utilIsZipFile(const char *);
void utilStripDoubleExtension(const char *, char *); void utilStripDoubleExtension(const char *, char *);
IMAGE_TYPE utilFindType(const char *); IMAGE_TYPE utilFindType(const char *);
IMAGE_TYPE utilFindType(const char *, char (&)[2048]); uint8_t *utilLoad(const char *, bool (*)(const char*), uint8_t *, int &);
u8 *utilLoad(const char *, bool (*)(const char*), u8 *, int &);
void utilPutDword(u8 *, u32); void utilPutDword(uint8_t *, uint32_t);
void utilPutWord(u8 *, u16); void utilPutWord(uint8_t *, uint16_t);
void utilWriteData(gzFile, variable_desc *); void utilWriteData(gzFile, variable_desc *);
void utilReadData(gzFile, variable_desc *); void utilReadData(gzFile, variable_desc *);
void utilReadDataSkip(gzFile, variable_desc *); void utilReadDataSkip(gzFile, variable_desc *);
@ -44,4 +43,15 @@ void utilGBAFindSave(const u8 *, const int);
void utilUpdateSystemColorMaps(bool lcd = false); void utilUpdateSystemColorMaps(bool lcd = false);
bool utilFileExists( const char *filename ); bool utilFileExists( const char *filename );
#ifdef __LIBRETRO__
void utilWriteIntMem(uint8_t *& data, int);
void utilWriteMem(uint8_t *& data, const void *in_data, unsigned size);
void utilWriteDataMem(uint8_t *& data, variable_desc *);
int utilReadIntMem(const uint8_t *& data);
void utilReadMem(void *buf, const uint8_t *& data, unsigned size);
void utilReadDataMem(const uint8_t *& data, variable_desc *);
#endif
#endif // UTIL_H #endif // UTIL_H

View File

@ -276,7 +276,7 @@ static bool patchApplyUPS(const char *patchname, u8 **rom, int *size)
static int ppfVersion(FILE *f) static int ppfVersion(FILE *f)
{ {
fseeko64(f, 0, SEEK_SET); fseeko64(f, 0, SEEK_SET);
if (fgetc(f) != 'P' || fgetc(f) != 'P' || fgetc(f) != 'F') if (fgetc(f) != 'P' || fgetc(f) != 'P' || fgetc(f) != 'F') //-V501
return 0; return 0;
switch(fgetc(f)){ switch(fgetc(f)){
case '1': return 1; case '1': return 1;

View File

@ -1,6 +1,16 @@
#ifndef PORT_H #ifndef PORT_H
#define PORT_H #define PORT_H
#ifdef __CELLOS_LV2__
/* PlayStation3 */
#include <ppu_intrinsics.h>
#endif
#ifdef _XBOX360
/* XBox 360 */
#include <ppcintrinsics.h>
#endif
#include "Types.h" #include "Types.h"
// swaps a 16-bit value // swaps a 16-bit value

View File

@ -40,12 +40,22 @@ void SoundSDL::read(u16 * stream, int length)
if (!_initialized || length <= 0 || !emulating) if (!_initialized || length <= 0 || !emulating)
return; return;
/* since this is running in a different thread, speedup and
* throttle can change at any time; save the value so locks
* stay in sync */
bool lock = (emulating && !speedup) ? true : false;
if (lock)
SDL_SemWait (_semBufferFull);
SDL_mutexP(_mutex); SDL_mutexP(_mutex);
_rbuf.read(stream, std::min(static_cast<std::size_t>(length) / 2, _rbuf.used())); _rbuf.read(stream, std::min(static_cast<std::size_t>(length) / 2, _rbuf.used()));
SDL_CondSignal(_cond);
SDL_mutexV(_mutex); SDL_mutexV(_mutex);
SDL_SemPost (_semBufferEmpty);
} }
void SoundSDL::write(u16 * finalWave, int length) void SoundSDL::write(u16 * finalWave, int length)
@ -63,23 +73,25 @@ void SoundSDL::write(u16 * finalWave, int length)
std::size_t avail; std::size_t avail;
while ((avail = _rbuf.avail() / 2) < samples) while ((avail = _rbuf.avail() / 2) < samples)
{ {
bool lock = (emulating && !speedup) ? true : false;
_rbuf.write(finalWave, avail * 2); _rbuf.write(finalWave, avail * 2);
finalWave += avail * 2; finalWave += avail * 2;
samples -= avail; samples -= avail;
// If emulating and not in speed up mode, synchronize to audio SDL_mutexV(_mutex);
// by waiting till there is enough room in the buffer SDL_SemPost(_semBufferFull);
if (emulating && !speedup) if (lock)
{ {
SDL_CondWait(_cond, _mutex); SDL_SemWait(_semBufferEmpty);
} }
else else
{ {
// Drop the remaining of the audio data // Drop the remaining of the audio data
SDL_mutexV(_mutex);
return; return;
} }
SDL_mutexP(_mutex);
} }
_rbuf.write(finalWave, samples * 2); _rbuf.write(finalWave, samples * 2);
@ -106,9 +118,10 @@ bool SoundSDL::init(long sampleRate)
_rbuf.reset(_delay * sampleRate * 2); _rbuf.reset(_delay * sampleRate * 2);
_cond = SDL_CreateCond(); _mutex = SDL_CreateMutex();
_mutex = SDL_CreateMutex(); _semBufferFull = SDL_CreateSemaphore (0);
_initialized = true; _semBufferEmpty = SDL_CreateSemaphore (1);
_initialized = true;
return true; return true;
} }
@ -121,11 +134,14 @@ SoundSDL::~SoundSDL()
SDL_mutexP(_mutex); SDL_mutexP(_mutex);
int iSave = emulating; int iSave = emulating;
emulating = 0; emulating = 0;
SDL_CondSignal(_cond); SDL_SemPost(_semBufferFull);
SDL_SemPost(_semBufferEmpty);
SDL_mutexV(_mutex); SDL_mutexV(_mutex);
SDL_DestroyCond(_cond); SDL_DestroySemaphore(_semBufferFull);
_cond = NULL; SDL_DestroySemaphore(_semBufferEmpty);
_semBufferFull = NULL;
_semBufferEmpty = NULL;
SDL_DestroyMutex(_mutex); SDL_DestroyMutex(_mutex);
_mutex = NULL; _mutex = NULL;

View File

@ -38,8 +38,9 @@ public:
private: private:
RingBuffer<u16> _rbuf; RingBuffer<u16> _rbuf;
SDL_cond * _cond;
SDL_mutex * _mutex; SDL_mutex * _mutex;
SDL_sem *_semBufferFull;
SDL_sem *_semBufferEmpty;
bool _initialized; bool _initialized;

View File

@ -234,7 +234,7 @@ void gbRenderLine()
if(y >= inUseRegister_WY) { if(y >= inUseRegister_WY) {
if (gbWindowLine>143) if ((gbWindowLine == -1) || (gbWindowLine>144))
gbWindowLine = 0; gbWindowLine = 0;
int wx = register_WX; int wx = register_WX;
@ -266,7 +266,7 @@ void gbRenderLine()
//bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7); //bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7);
if ((swx == 7)) if (swx == 7)
{ {
//wx = 0; //wx = 0;
if ((gbWindowLine>0) || (wy == 0)) if ((gbWindowLine>0) || (wy == 0))

View File

@ -121,6 +121,13 @@ static void reset_apu()
static void remake_stereo_buffer() static void remake_stereo_buffer()
{ {
// APU
if ( !gb_apu )
{
gb_apu = new Gb_Apu; // TODO: handle errors
reset_apu();
}
// Stereo_Buffer // Stereo_Buffer
delete stereo_buffer; delete stereo_buffer;
stereo_buffer = 0; stereo_buffer = 0;
@ -129,19 +136,14 @@ static void remake_stereo_buffer()
if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory if ( stereo_buffer->set_sample_rate( soundSampleRate ) ) { } // TODO: handle out of memory
stereo_buffer->clock_rate( gb_apu->clock_rate ); stereo_buffer->clock_rate( gb_apu->clock_rate );
// APU // Multi_Buffer
static int const chan_types [chan_count] = { static int const chan_types [chan_count] = {
Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2, Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2,
Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1 Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1
}; };
if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors
if ( !gb_apu ) // Volume Level
{
gb_apu = new Gb_Apu; // TODO: handle errors
reset_apu();
}
apply_effects(); apply_effects();
apply_volume(); apply_volume();
} }

View File

@ -1,3 +1,4 @@
#ifndef __LIBRETRO__
#include <memory.h> #include <memory.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
@ -2896,3 +2897,4 @@ void cheatsWriteByte(u32, u8)
#endif #endif
#endif #endif
} }
#endif

View File

@ -1,4 +1,5 @@
#include <memory.h> #include <memory.h>
#include <string.h>
#include "GBA.h" #include "GBA.h"
#include "EEprom.h" #include "EEprom.h"
#include "../Util.h" #include "../Util.h"
@ -9,7 +10,15 @@ int eepromMode = EEPROM_IDLE;
int eepromByte = 0; int eepromByte = 0;
int eepromBits = 0; int eepromBits = 0;
int eepromAddress = 0; int eepromAddress = 0;
#ifdef __LIBRETRO__
// Workaround for broken-by-design GBA save semantics
extern u8 libretro_save_buf[0x20000 + 0x2000];
u8 *eepromData = libretro_save_buf + 0x20000;
#else
u8 eepromData[0x2000]; u8 eepromData[0x2000];
#endif
u8 eepromBuffer[16]; u8 eepromBuffer[16];
bool eepromInUse = false; bool eepromInUse = false;
int eepromSize = 512; int eepromSize = 512;
@ -27,7 +36,11 @@ variable_desc eepromSaveData[] = {
void eepromInit() void eepromInit()
{ {
memset(eepromData, 255, sizeof(eepromData)); #ifdef __LIBRETRO__
memset(eepromData, 255, 0x2000);
#else
memset(eepromData, 255, sizeof(eepromData));
#endif
} }
void eepromReset() void eepromReset()
@ -40,6 +53,26 @@ void eepromReset()
eepromSize = 512; eepromSize = 512;
} }
#ifdef __LIBRETRO__
void eepromSaveGame(uint8_t *& data)
{
utilWriteDataMem(data, eepromSaveData);
utilWriteIntMem(data, eepromSize);
utilWriteMem(data, eepromData, 0x2000);
}
void eepromReadGame(const uint8_t *& data, int version)
{
utilReadDataMem(data, eepromSaveData);
if (version >= SAVE_GAME_VERSION_3) {
eepromSize = utilReadIntMem(data);
utilReadMem(eepromData, data, 0x2000);
} else {
// prior to 0.7.1, only 4K EEPROM was supported
eepromSize = 512;
}
}
#else
void eepromSaveGame(gzFile gzFile) void eepromSaveGame(gzFile gzFile)
{ {
utilWriteData(gzFile, eepromSaveData); utilWriteData(gzFile, eepromSaveData);
@ -68,6 +101,7 @@ void eepromReadGameSkip(gzFile gzFile, int version)
utilGzSeek(gzFile, 0x2000, SEEK_CUR); utilGzSeek(gzFile, 0x2000, SEEK_CUR);
} }
} }
#endif
int eepromRead(u32 /* address */) int eepromRead(u32 /* address */)
{ {

View File

@ -1,14 +1,23 @@
#ifndef EEPROM_H #ifndef EEPROM_H
#define EEPROM_H #define EEPROM_H
#ifdef __LIBRETRO__
extern void eepromSaveGame(u8* &data);
extern void eepromReadGame(const u8 *&data, int version);
#else
extern void eepromSaveGame(gzFile _gzFile); extern void eepromSaveGame(gzFile _gzFile);
extern void eepromReadGame(gzFile _gzFile, int version); extern void eepromReadGame(gzFile _gzFile, int version);
#endif
extern void eepromReadGameSkip(gzFile _gzFile, int version); extern void eepromReadGameSkip(gzFile _gzFile, int version);
extern int eepromRead(u32 address); extern int eepromRead(u32 address);
extern void eepromWrite(u32 address, u8 value); extern void eepromWrite(u32 address, u8 value);
extern void eepromInit(); extern void eepromInit();
extern void eepromReset(); extern void eepromReset();
#ifdef __LIBRETRO__
extern u8 *eepromData;
#else
extern u8 eepromData[0x2000]; extern u8 eepromData[0x2000];
#endif
extern bool eepromInUse; extern bool eepromInUse;
extern int eepromSize; extern int eepromSize;

View File

@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <memory.h> #include <memory.h>
#include "GBA.h" #include "GBA.h"
#include "Globals.h" #include "Globals.h"
@ -17,7 +18,13 @@
#define FLASH_PROGRAM 8 #define FLASH_PROGRAM 8
#define FLASH_SETBANK 9 #define FLASH_SETBANK 9
u8 flashSaveMemory[FLASH_128K_SZ]; #ifdef __LIBRETRO__
extern uint8_t libretro_save_buf[0x20000 + 0x2000];
uint8_t *flashSaveMemory = libretro_save_buf;
#else
uint8_t flashSaveMemory[FLASH_128K_SZ];
#endif
int flashState = FLASH_READ_ARRAY; int flashState = FLASH_READ_ARRAY;
int flashReadState = FLASH_READ_ARRAY; int flashReadState = FLASH_READ_ARRAY;
int flashSize = 0x10000; int flashSize = 0x10000;
@ -51,7 +58,11 @@ static variable_desc flashSaveData3[] = {
void flashInit() void flashInit()
{ {
memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory)); #ifdef __LIBRETRO__
memset(flashSaveMemory, 0xff, 0x20000);
#else
memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
#endif
} }
void flashReset() void flashReset()
@ -61,6 +72,17 @@ void flashReset()
flashBank = 0; flashBank = 0;
} }
#ifdef __LIBRETRO__
void flashSaveGame(uint8_t *& data)
{
utilWriteDataMem(data, flashSaveData3);
}
void flashReadGame(const uint8_t *& data, int)
{
utilReadDataMem(data, flashSaveData3);
}
#else
void flashSaveGame(gzFile gzFile) void flashSaveGame(gzFile gzFile)
{ {
utilWriteData(gzFile, flashSaveData3); utilWriteData(gzFile, flashSaveData3);
@ -90,6 +112,8 @@ void flashReadGameSkip(gzFile gzFile, int version)
utilReadDataSkip(gzFile, flashSaveData3); utilReadDataSkip(gzFile, flashSaveData3);
} }
} }
#endif
void flashSetSize(int size) void flashSetSize(int size)
{ {

View File

@ -3,13 +3,22 @@
#define FLASH_128K_SZ 0x20000 #define FLASH_128K_SZ 0x20000
#ifdef __LIBRETRO__
extern void flashSaveGame(u8 *& data);
extern void flashReadGame(const u8 *& data, int);
#else
extern void flashSaveGame(gzFile _gzFile); extern void flashSaveGame(gzFile _gzFile);
extern void flashReadGame(gzFile _gzFile, int version); extern void flashReadGame(gzFile _gzFile, int version);
#endif
extern void flashReadGameSkip(gzFile _gzFile, int version); extern void flashReadGameSkip(gzFile _gzFile, int version);
extern u8 flashRead(u32 address); extern u8 flashRead(u32 address);
extern void flashWrite(u32 address, u8 byte); extern void flashWrite(u32 address, u8 byte);
extern void flashDelayedWrite(u32 address, u8 byte); extern void flashDelayedWrite(u32 address, u8 byte);
#ifdef __LIBRETRO__
extern uint8_t *flashSaveMemory;
#else
extern u8 flashSaveMemory[FLASH_128K_SZ]; extern u8 flashSaveMemory[FLASH_128K_SZ];
#endif
extern void flashSaveDecide(u32 address, u8 byte); extern void flashSaveDecide(u32 address, u8 byte);
extern void flashReset(); extern void flashReset();
extern void flashSetSize(int size); extern void flashSetSize(int size);

View File

@ -356,7 +356,11 @@ static void count(u32 opcode, int cond_res)
EMIT2(and, KONST(0x1F), ecx) EMIT2(and, KONST(0x1F), ecx)
#define VALUE_LOAD_REG \ #define VALUE_LOAD_REG \
EMIT2(and, KONST(0x0F), eax) \ EMIT2(and, KONST(0x0F), eax) \
EMIT2(mov, REGREF2(eax,4), eax) \ EMIT2(cmp, KONST(0x0F), eax) \
EMIT2(mov, REGREF2(eax,4), eax) \
EMIT1(jne, LABELREF(3,f)) \
EMIT2(add, KONST(4), eax) \
LABEL(3) \
EMIT2(movzx, ch, ecx) \ EMIT2(movzx, ch, ecx) \
EMIT2(and, KONST(0x0F), ecx) \ EMIT2(and, KONST(0x0F), ecx) \
EMIT2(mov, REGREF2(ecx,4), ecx) EMIT2(mov, REGREF2(ecx,4), ecx)
@ -1533,7 +1537,7 @@ static INSN_REGPARM void arm121(u32 opcode)
#define OP_LDR reg[dest].I = CPUReadMemory(address) #define OP_LDR reg[dest].I = CPUReadMemory(address)
#define OP_LDRH reg[dest].I = CPUReadHalfWord(address) #define OP_LDRH reg[dest].I = CPUReadHalfWord(address)
#define OP_LDRB reg[dest].I = CPUReadByte(address) #define OP_LDRB reg[dest].I = CPUReadByte(address)
#define OP_LDRSH reg[dest].I = (s16)CPUReadHalfWordSigned(address) #define OP_LDRSH reg[dest].I = (u32)CPUReadHalfWordSigned(address)
#define OP_LDRSB reg[dest].I = (s8)CPUReadByte(address) #define OP_LDRSB reg[dest].I = (s8)CPUReadByte(address)
#define WRITEBACK_NONE /*nothing*/ #define WRITEBACK_NONE /*nothing*/
@ -2608,8 +2612,7 @@ static INSN_REGPARM void armA00(u32 opcode)
reg[15].I += 4; reg[15].I += 4;
ARM_PREFETCH; ARM_PREFETCH;
clockTicks = codeTicksAccessSeq32(armNextPC) + 1; clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
clockTicks += 2 + codeTicksAccess32(armNextPC) clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
+ codeTicksAccessSeq32(armNextPC);
busPrefetchCount = 0; busPrefetchCount = 0;
} }
@ -2625,8 +2628,7 @@ static INSN_REGPARM void armB00(u32 opcode)
reg[15].I += 4; reg[15].I += 4;
ARM_PREFETCH; ARM_PREFETCH;
clockTicks = codeTicksAccessSeq32(armNextPC) + 1; clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
clockTicks += 2 + codeTicksAccess32(armNextPC) clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
+ codeTicksAccessSeq32(armNextPC);
busPrefetchCount = 0; busPrefetchCount = 0;
} }
@ -2644,9 +2646,8 @@ static INSN_REGPARM void armE01(u32 opcode)
// SWI <comment> // SWI <comment>
static INSN_REGPARM void armF00(u32 opcode) static INSN_REGPARM void armF00(u32 opcode)
{ {
clockTicks = codeTicksAccessSeq32(armNextPC) + 1; clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
clockTicks += 2 + codeTicksAccess32(armNextPC) clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
+ codeTicksAccessSeq32(armNextPC);
busPrefetchCount = 0; busPrefetchCount = 0;
CPUSoftwareInterrupt(opcode & 0x00FFFFFF); CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
} }
@ -2700,7 +2701,7 @@ static insnfunc_t armInsnTable[4096] = {
arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0 arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0
arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8 arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8
arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0 arm0F0,arm0F1,arm0F2,arm0F3,arm0F4,arm0F5,arm0F6,arm0F7, // 0F0
arm0F0,arm0F9,arm0F2,arm_UI,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8 arm0F0,arm0F9,arm0F2,arm0DB,arm0F4,arm0DD,arm0F6,arm0DF, // 0F8
arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100 arm100,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI,arm_UI, // 100
arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108 arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108

View File

@ -1421,12 +1421,14 @@ static INSN_REGPARM void thumb45_3(u32 opcode)
static INSN_REGPARM void thumb46_0(u32 opcode) static INSN_REGPARM void thumb46_0(u32 opcode)
{ {
reg[opcode&7].I = reg[((opcode>>3)&7)].I; reg[opcode&7].I = reg[((opcode>>3)&7)].I;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
} }
// MOV Rd, Hs // MOV Rd, Hs
static INSN_REGPARM void thumb46_1(u32 opcode) static INSN_REGPARM void thumb46_1(u32 opcode)
{ {
reg[opcode&7].I = reg[((opcode>>3)&7)+8].I; reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
} }
// MOV Hd, Rs // MOV Hd, Rs
@ -1473,16 +1475,14 @@ static INSN_REGPARM void thumb47(u32 opcode)
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
+ codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
} else { } else {
armState = true; armState = true;
reg[15].I &= 0xFFFFFFFC; reg[15].I &= 0xFFFFFFFC;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 4; reg[15].I += 4;
ARM_PREFETCH; ARM_PREFETCH;
clockTicks = codeTicksAccessSeq32(armNextPC) clockTicks = codeTicksAccessSeq32(armNextPC)*2 + codeTicksAccess32(armNextPC) + 3;
+ codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
} }
} }
@ -1576,7 +1576,7 @@ static INSN_REGPARM void thumb5E(u32 opcode)
if (busPrefetchCount == 0) if (busPrefetchCount == 0)
busPrefetch = busPrefetchEnable; busPrefetch = busPrefetchEnable;
u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I; u32 address = reg[(opcode>>3)&7].I + reg[(opcode>>6)&7].I;
reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address); reg[opcode&7].I = (u32)CPUReadHalfWordSigned(address);
clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC); clockTicks = 3 + dataTicksAccess16(address) + codeTicksAccess16(armNextPC);
} }
@ -1669,6 +1669,7 @@ static INSN_REGPARM void thumbA0(u32 opcode)
{ {
u8 regist = (opcode >> 8) & 7; u8 regist = (opcode >> 8) & 7;
reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2); reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
clockTicks = 1 + codeTicksAccess16(armNextPC);
} }
// ADD R0~R7, SP, Imm // ADD R0~R7, SP, Imm
@ -1676,6 +1677,7 @@ static INSN_REGPARM void thumbA8(u32 opcode)
{ {
u8 regist = (opcode >> 8) & 7; u8 regist = (opcode >> 8) & 7;
reg[regist].I = reg[13].I + ((opcode&255)<<2); reg[regist].I = reg[13].I + ((opcode&255)<<2);
clockTicks = 1 + codeTicksAccess16(armNextPC);
} }
// ADD SP, Imm // ADD SP, Imm
@ -1685,6 +1687,7 @@ static INSN_REGPARM void thumbB0(u32 opcode)
if(opcode & 0x80) if(opcode & 0x80)
offset = -offset; offset = -offset;
reg[13].I += offset; reg[13].I += offset;
clockTicks = 1 + codeTicksAccess16(armNextPC);
} }
// Push and pop /////////////////////////////////////////////////////////// // Push and pop ///////////////////////////////////////////////////////////
@ -1882,13 +1885,13 @@ static INSN_REGPARM void thumbC8(u32 opcode)
static INSN_REGPARM void thumbD0(u32 opcode) static INSN_REGPARM void thumbD0(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(Z_FLAG) { if(Z_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -1897,13 +1900,13 @@ static INSN_REGPARM void thumbD0(u32 opcode)
static INSN_REGPARM void thumbD1(u32 opcode) static INSN_REGPARM void thumbD1(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(!Z_FLAG) { if(!Z_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -1912,13 +1915,13 @@ static INSN_REGPARM void thumbD1(u32 opcode)
static INSN_REGPARM void thumbD2(u32 opcode) static INSN_REGPARM void thumbD2(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(C_FLAG) { if(C_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -1927,13 +1930,13 @@ static INSN_REGPARM void thumbD2(u32 opcode)
static INSN_REGPARM void thumbD3(u32 opcode) static INSN_REGPARM void thumbD3(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(!C_FLAG) { if(!C_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -1942,13 +1945,13 @@ static INSN_REGPARM void thumbD3(u32 opcode)
static INSN_REGPARM void thumbD4(u32 opcode) static INSN_REGPARM void thumbD4(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(N_FLAG) { if(N_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -1957,13 +1960,13 @@ static INSN_REGPARM void thumbD4(u32 opcode)
static INSN_REGPARM void thumbD5(u32 opcode) static INSN_REGPARM void thumbD5(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(!N_FLAG) { if(!N_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -1972,13 +1975,13 @@ static INSN_REGPARM void thumbD5(u32 opcode)
static INSN_REGPARM void thumbD6(u32 opcode) static INSN_REGPARM void thumbD6(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(V_FLAG) { if(V_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -1987,13 +1990,13 @@ static INSN_REGPARM void thumbD6(u32 opcode)
static INSN_REGPARM void thumbD7(u32 opcode) static INSN_REGPARM void thumbD7(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(!V_FLAG) { if(!V_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -2002,13 +2005,13 @@ static INSN_REGPARM void thumbD7(u32 opcode)
static INSN_REGPARM void thumbD8(u32 opcode) static INSN_REGPARM void thumbD8(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(C_FLAG && !Z_FLAG) { if(C_FLAG && !Z_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -2017,13 +2020,13 @@ static INSN_REGPARM void thumbD8(u32 opcode)
static INSN_REGPARM void thumbD9(u32 opcode) static INSN_REGPARM void thumbD9(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(!C_FLAG || Z_FLAG) { if(!C_FLAG || Z_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -2032,13 +2035,13 @@ static INSN_REGPARM void thumbD9(u32 opcode)
static INSN_REGPARM void thumbDA(u32 opcode) static INSN_REGPARM void thumbDA(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(N_FLAG == V_FLAG) { if(N_FLAG == V_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -2047,13 +2050,13 @@ static INSN_REGPARM void thumbDA(u32 opcode)
static INSN_REGPARM void thumbDB(u32 opcode) static INSN_REGPARM void thumbDB(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(N_FLAG != V_FLAG) { if(N_FLAG != V_FLAG) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -2062,13 +2065,13 @@ static INSN_REGPARM void thumbDB(u32 opcode)
static INSN_REGPARM void thumbDC(u32 opcode) static INSN_REGPARM void thumbDC(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
if(!Z_FLAG && (N_FLAG == V_FLAG)) { if(!Z_FLAG && (N_FLAG == V_FLAG)) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -2077,13 +2080,13 @@ static INSN_REGPARM void thumbDC(u32 opcode)
static INSN_REGPARM void thumbDD(u32 opcode) static INSN_REGPARM void thumbDD(u32 opcode)
{ {
UPDATE_OLDREG; UPDATE_OLDREG;
clockTicks = codeTicksAccessSeq16(armNextPC);
if(Z_FLAG || (N_FLAG != V_FLAG)) { if(Z_FLAG || (N_FLAG != V_FLAG)) {
reg[15].I += ((s8)(opcode & 0xFF)) << 1; reg[15].I += ((s8)(opcode & 0xFF)) << 1;
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
codeTicksAccess16(armNextPC)+3;
busPrefetchCount=0; busPrefetchCount=0;
} }
} }
@ -2094,8 +2097,8 @@ static INSN_REGPARM void thumbDD(u32 opcode)
static INSN_REGPARM void thumbDF(u32 opcode) static INSN_REGPARM void thumbDF(u32 opcode)
{ {
u32 address = 0; u32 address = 0;
clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) + //clockTicks = codeTicksAccessSeq16(address)*2 + codeTicksAccess16(address)+3;
codeTicksAccess16(address)+3; clockTicks = 3;
busPrefetchCount=0; busPrefetchCount=0;
CPUSoftwareInterrupt(opcode & 0xFF); CPUSoftwareInterrupt(opcode & 0xFF);
} }
@ -2110,8 +2113,7 @@ static INSN_REGPARM void thumbE0(u32 opcode)
armNextPC = reg[15].I; armNextPC = reg[15].I;
reg[15].I += 2; reg[15].I += 2;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC)+3;
codeTicksAccess16(armNextPC) + 3;
busPrefetchCount=0; busPrefetchCount=0;
} }
@ -2141,8 +2143,7 @@ static INSN_REGPARM void thumbF8(u32 opcode)
reg[15].I += 2; reg[15].I += 2;
reg[14].I = temp|1; reg[14].I = temp|1;
THUMB_PREFETCH; THUMB_PREFETCH;
clockTicks = codeTicksAccessSeq16(armNextPC) + clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
codeTicksAccess16(armNextPC) + codeTicksAccessSeq16(armNextPC) + 3;
busPrefetchCount = 0; busPrefetchCount = 0;
} }

View File

@ -120,6 +120,9 @@ int capture = 0;
int capturePrevious = 0; int capturePrevious = 0;
int captureNumber = 0; int captureNumber = 0;
int armOpcodeCount = 0;
int thumbOpcodeCount = 0;
const int TIMER_TICKS[4] = { const int TIMER_TICKS[4] = {
0, 0,
6, 6,
@ -574,6 +577,44 @@ void CPUUpdateRenderBuffers(bool force)
} }
} }
#ifdef __LIBRETRO__
#include <cstddef>
unsigned int CPUWriteState(u8* data, unsigned size)
{
uint8_t *orig = data;
utilWriteIntMem(data, SAVE_GAME_VERSION);
utilWriteMem(data, &rom[0xa0], 16);
utilWriteIntMem(data, useBios);
utilWriteMem(data, &reg[0], sizeof(reg));
utilWriteDataMem(data, saveGameStruct);
utilWriteIntMem(data, stopState);
utilWriteIntMem(data, IRQTicks);
utilWriteMem(data, internalRAM, 0x8000);
utilWriteMem(data, paletteRAM, 0x400);
utilWriteMem(data, workRAM, 0x40000);
utilWriteMem(data, vram, 0x20000);
utilWriteMem(data, oam, 0x400);
utilWriteMem(data, pix, 4 * 241 * 162);
utilWriteMem(data, ioMem, 0x400);
eepromSaveGame(data);
flashSaveGame(data);
soundSaveGame(data);
rtcSaveGame(data);
return (ptrdiff_t)data - (ptrdiff_t)orig;
}
bool CPUWriteMemState(char *memory, int available)
{
return false;
}
#else
static bool CPUWriteState(gzFile gzFile) static bool CPUWriteState(gzFile gzFile)
{ {
utilWriteInt(gzFile, SAVE_GAME_VERSION); utilWriteInt(gzFile, SAVE_GAME_VERSION);
@ -627,6 +668,7 @@ bool CPUWriteState(const char *file)
return res; return res;
} }
bool CPUWriteMemState(char *memory, int available) bool CPUWriteMemState(char *memory, int available)
{ {
gzFile gzFile = utilMemGzOpen(memory, available, "w"); gzFile gzFile = utilMemGzOpen(memory, available, "w");
@ -646,7 +688,108 @@ bool CPUWriteMemState(char *memory, int available)
return res; return res;
} }
#endif
#ifdef __LIBRETRO__
bool CPUReadState(const u8* data, unsigned size)
{
// Don't really care about version.
int version = utilReadIntMem(data);
if (version != SAVE_GAME_VERSION)
return false;
char romname[16];
utilReadMem(romname, data, 16);
if (memcmp(&rom[0xa0], romname, 16) != 0)
return false;
// Don't care about use bios ...
utilReadIntMem(data);
utilReadMem(&reg[0], data, sizeof(reg));
utilReadDataMem(data, saveGameStruct);
stopState = utilReadIntMem(data) ? true : false;
IRQTicks = utilReadIntMem(data);
if (IRQTicks > 0)
intState = true;
else
{
intState = false;
IRQTicks = 0;
}
utilReadMem(internalRAM, data, 0x8000);
utilReadMem(paletteRAM, data, 0x400);
utilReadMem(workRAM, data, 0x40000);
utilReadMem(vram, data, 0x20000);
utilReadMem(oam, data, 0x400);
utilReadMem(pix, data, 4*241*162);
utilReadMem(ioMem, data, 0x400);
eepromReadGame(data, version);
flashReadGame(data, version);
soundReadGame(data, version);
rtcReadGame(data);
//// Copypasta stuff ...
// set pointers!
layerEnable = layerSettings & DISPCNT;
CPUUpdateRender();
// CPU Update Render Buffers set to true
CLEAR_ARRAY(line0);
CLEAR_ARRAY(line1);
CLEAR_ARRAY(line2);
CLEAR_ARRAY(line3);
// End of CPU Update Render Buffers set to true
CPUUpdateWindow0();
CPUUpdateWindow1();
gbaSaveType = 0;
switch(saveType) {
case 0:
cpuSaveGameFunc = flashSaveDecide;
break;
case 1:
cpuSaveGameFunc = sramWrite;
gbaSaveType = 1;
break;
case 2:
cpuSaveGameFunc = flashWrite;
gbaSaveType = 2;
break;
case 3:
break;
case 5:
gbaSaveType = 5;
break;
default:
#ifdef CELL_VBA_DEBUG
systemMessage(MSG_UNSUPPORTED_SAVE_TYPE,
N_("Unsupported save type %d"), saveType);
#endif
break;
}
if(eepromInUse)
gbaSaveType = 3;
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
if(armState) {
ARM_PREFETCH;
} else {
THUMB_PREFETCH;
}
CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
return true;
}
#else
static bool CPUReadState(gzFile gzFile) static bool CPUReadState(gzFile gzFile)
{ {
int version = utilReadInt(gzFile); int version = utilReadInt(gzFile);
@ -843,6 +986,7 @@ bool CPUReadState(const char * file)
return res; return res;
} }
#endif
bool CPUExportEepromFile(const char *fileName) bool CPUExportEepromFile(const char *fileName)
{ {
@ -934,7 +1078,7 @@ bool CPUReadGSASnapshot(const char *fileName)
fseek(file, 0x0, SEEK_SET); fseek(file, 0x0, SEEK_SET);
fread(&i, 1, 4, file); fread(&i, 1, 4, file);
fseek(file, i, SEEK_CUR); // Skip SharkPortSave fseek(file, i, SEEK_CUR); // Skip SharkPortSave
fseek(file, 4, SEEK_CUR); // skip some sort of flag // fseek(file, 4, SEEK_CUR); // skip some sort of flag
fread(&i, 1, 4, file); // name length fread(&i, 1, 4, file); // name length
fseek(file, i, SEEK_CUR); // skip name fseek(file, i, SEEK_CUR); // skip name
fread(&i, 1, 4, file); // desc length fread(&i, 1, 4, file); // desc length
@ -1806,8 +1950,8 @@ void CPUSoftwareInterrupt(int comment)
case 0x02: case 0x02:
#ifdef GBA_LOGGING #ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) { if(systemVerbose & VERBOSE_SWI) {
log("Halt: (VCOUNT = %2d)\n", /*log("Halt: (VCOUNT = %2d)\n",
VCOUNT); VCOUNT);*/
} }
#endif #endif
holdState = true; holdState = true;
@ -1817,8 +1961,8 @@ void CPUSoftwareInterrupt(int comment)
case 0x03: case 0x03:
#ifdef GBA_LOGGING #ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_SWI) { if(systemVerbose & VERBOSE_SWI) {
log("Stop: (VCOUNT = %2d)\n", /*log("Stop: (VCOUNT = %2d)\n",
VCOUNT); VCOUNT);*/
} }
#endif #endif
holdState = true; holdState = true;
@ -2073,6 +2217,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
int dw = 0; int dw = 0;
int sc = c; int sc = c;
cpuDmaHack = true;
cpuDmaCount = c; cpuDmaCount = c;
// This is done to get the correct waitstates. // This is done to get the correct waitstates.
if (sm>15) if (sm>15)
@ -2141,7 +2286,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
} }
cpuDmaTicksToUpdate += totalTicks; cpuDmaTicksToUpdate += totalTicks;
cpuDmaHack = false;
} }
void CPUCheckDMA(int reason, int dmamask) void CPUCheckDMA(int reason, int dmamask)
@ -2184,7 +2329,6 @@ void CPUCheckDMA(int reason, int dmamask)
doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement, doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement,
DM0CNT_L ? DM0CNT_L : 0x4000, DM0CNT_L ? DM0CNT_L : 0x4000,
DM0CNT_H & 0x0400); DM0CNT_H & 0x0400);
cpuDmaHack = true;
if(DM0CNT_H & 0x4000) { if(DM0CNT_H & 0x4000) {
IF |= 0x0100; IF |= 0x0100;
@ -2253,7 +2397,6 @@ void CPUCheckDMA(int reason, int dmamask)
DM1CNT_L ? DM1CNT_L : 0x4000, DM1CNT_L ? DM1CNT_L : 0x4000,
DM1CNT_H & 0x0400); DM1CNT_H & 0x0400);
} }
cpuDmaHack = true;
if(DM1CNT_H & 0x4000) { if(DM1CNT_H & 0x4000) {
IF |= 0x0200; IF |= 0x0200;
@ -2323,7 +2466,6 @@ void CPUCheckDMA(int reason, int dmamask)
DM2CNT_L ? DM2CNT_L : 0x4000, DM2CNT_L ? DM2CNT_L : 0x4000,
DM2CNT_H & 0x0400); DM2CNT_H & 0x0400);
} }
cpuDmaHack = true;
if(DM2CNT_H & 0x4000) { if(DM2CNT_H & 0x4000) {
IF |= 0x0400; IF |= 0x0400;
@ -2380,6 +2522,7 @@ void CPUCheckDMA(int reason, int dmamask)
doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement, doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement,
DM3CNT_L ? DM3CNT_L : 0x10000, DM3CNT_L ? DM3CNT_L : 0x10000,
DM3CNT_H & 0x0400); DM3CNT_H & 0x0400);
if(DM3CNT_H & 0x4000) { if(DM3CNT_H & 0x4000) {
IF |= 0x0800; IF |= 0x0800;
UPDATE_REG(0x202, IF); UPDATE_REG(0x202, IF);
@ -2426,7 +2569,7 @@ void CPUUpdateRegister(u32 address, u16 value)
windowOn = (layerEnable & 0x6000) ? true : false; windowOn = (layerEnable & 0x6000) ? true : false;
if(change && !((value & 0x80))) { if(change && !((value & 0x80))) {
if(!(DISPSTAT & 1)) { if(!(DISPSTAT & 1)) {
lcdTicks = 1008; //lcdTicks = 1008;
// VCOUNT = 0; // VCOUNT = 0;
// UPDATE_REG(0x06, VCOUNT); // UPDATE_REG(0x06, VCOUNT);
DISPSTAT &= 0xFFFC; DISPSTAT &= 0xFFFC;
@ -3479,9 +3622,11 @@ void CPULoop(int ticks)
if(!holdState && !SWITicks) { if(!holdState && !SWITicks) {
if(armState) { if(armState) {
armOpcodeCount++;
if (!armExecute()) if (!armExecute())
return; return;
} else { } else {
thumbOpcodeCount++;
if (!thumbExecute()) if (!thumbExecute())
return; return;
} }
@ -3504,7 +3649,6 @@ void CPULoop(int ticks)
clockTicks = cpuNextEvent; clockTicks = cpuNextEvent;
cpuTotalTicks = 0; cpuTotalTicks = 0;
cpuDmaHack = false;
updateLoop: updateLoop:
@ -3538,7 +3682,7 @@ void CPULoop(int ticks)
} }
} }
if(VCOUNT >= 228) { //Reaching last line if(VCOUNT > 227) { //Reaching last line
DISPSTAT &= 0xFFFC; DISPSTAT &= 0xFFFC;
UPDATE_REG(0x04, DISPSTAT); UPDATE_REG(0x04, DISPSTAT);
VCOUNT = 0; VCOUNT = 0;
@ -3903,7 +4047,6 @@ void CPULoop(int ticks)
cpuDmaTicksToUpdate -= clockTicks; cpuDmaTicksToUpdate -= clockTicks;
if(cpuDmaTicksToUpdate < 0) if(cpuDmaTicksToUpdate < 0)
cpuDmaTicksToUpdate = 0; cpuDmaTicksToUpdate = 0;
cpuDmaHack = true;
goto updateLoop; goto updateLoop;
} }
@ -3976,6 +4119,256 @@ void CPULoop(int ticks)
} }
} }
#ifdef TILED_RENDERING
union u8h
{
struct
{
/* 0*/ unsigned lo:4;
/* 4*/ unsigned hi:4;
} __attribute__ ((packed));
u8 val;
};
union TileEntry
{
struct
{
/* 0*/ unsigned tileNum:10;
/*12*/ unsigned hFlip:1;
/*13*/ unsigned vFlip:1;
/*14*/ unsigned palette:4;
};
u16 val;
};
struct TileLine
{
u32 pixels[8];
};
typedef const TileLine (*TileReader) (const u16 *, const int, const u8 *, u16 *, const u32);
static inline void gfxDrawPixel(u32 *dest, const u8 color, const u16 *palette, const u32 prio)
{
*dest = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
}
inline const TileLine gfxReadTile(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
{
TileEntry tile;
tile.val = READ16LE(screenSource);
int tileY = yyy & 7;
if (tile.vFlip) tileY = 7 - tileY;
TileLine tileLine;
const u8 *tileBase = &charBase[tile.tileNum * 64 + tileY * 8];
if (!tile.hFlip)
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[0], palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[1], palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[2], palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[3], palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[4], palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[5], palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[6], palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[7], palette, prio);
}
else
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[7], palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[6], palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[5], palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[4], palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[3], palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[2], palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[1], palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[0], palette, prio);
}
return tileLine;
}
inline const TileLine gfxReadTilePal(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
{
TileEntry tile;
tile.val = READ16LE(screenSource);
int tileY = yyy & 7;
if (tile.vFlip) tileY = 7 - tileY;
palette += tile.palette * 16;
TileLine tileLine;
const u8h *tileBase = (u8h*) &charBase[tile.tileNum * 32 + tileY * 4];
if (!tile.hFlip)
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[0].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[0].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[1].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[1].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[2].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[2].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[3].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[3].hi, palette, prio);
}
else
{
gfxDrawPixel(&tileLine.pixels[0], tileBase[3].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[1], tileBase[3].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[2], tileBase[2].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[3], tileBase[2].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[4], tileBase[1].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[5], tileBase[1].lo, palette, prio);
gfxDrawPixel(&tileLine.pixels[6], tileBase[0].hi, palette, prio);
gfxDrawPixel(&tileLine.pixels[7], tileBase[0].lo, palette, prio);
}
return tileLine;
}
static inline void gfxDrawTile(const TileLine &tileLine, u32 *line)
{
memcpy(line, tileLine.pixels, sizeof(tileLine.pixels));
}
static inline void gfxDrawTileClipped(const TileLine &tileLine, u32 *line, const int start, int w)
{
memcpy(line, tileLine.pixels + start, w * sizeof(u32));
}
template<TileReader readTile>
static void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
u32 *line)
{
u16 *palette = (u16 *)paletteRAM;
u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
u32 prio = ((control & 3)<<25) + 0x1000000;
int sizeX = 256;
int sizeY = 256;
switch ((control >> 14) & 3)
{
case 0:
break;
case 1:
sizeX = 512;
break;
case 2:
sizeY = 512;
break;
case 3:
sizeX = 512;
sizeY = 512;
break;
}
int maskX = sizeX-1;
int maskY = sizeY-1;
bool mosaicOn = (control & 0x40) ? true : false;
int xxx = hofs & maskX;
int yyy = (vofs + VCOUNT) & maskY;
int mosaicX = (MOSAIC & 0x000F)+1;
int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
if (mosaicOn)
{
if ((VCOUNT % mosaicY) != 0)
{
mosaicY = VCOUNT - (VCOUNT % mosaicY);
yyy = (vofs + mosaicY) & maskY;
}
}
if (yyy > 255 && sizeY > 256)
{
yyy &= 255;
screenBase += 0x400;
if (sizeX > 256)
screenBase += 0x400;
}
int yshift = ((yyy>>3)<<5);
u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
int x = 0;
const int firstTileX = xxx & 7;
// First tile, if clipped
if (firstTileX)
{
gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], firstTileX, 8 - firstTileX);
screenSource++;
x += 8 - firstTileX;
xxx += 8 - firstTileX;
if (xxx == 256 && sizeX > 256)
{
screenSource = screenBase + 0x400 + yshift;
}
else if (xxx >= sizeX)
{
xxx = 0;
screenSource = screenBase + yshift;
}
}
// Middle tiles, full
while (x < 240 - firstTileX)
{
gfxDrawTile(readTile(screenSource, yyy, charBase, palette, prio), &line[x]);
screenSource++;
xxx += 8;
x += 8;
if (xxx == 256 && sizeX > 256)
{
screenSource = screenBase + 0x400 + yshift;
}
else if (xxx >= sizeX)
{
xxx = 0;
screenSource = screenBase + yshift;
}
}
// Last tile, if clipped
if (firstTileX)
{
gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], 0, firstTileX);
}
if (mosaicOn)
{
if (mosaicX > 1)
{
int m = 1;
for (int i = 0; i < 239; i++)
{
line[i+1] = line[i];
m++;
if (m == mosaicX)
{
m = 1;
i++;
}
}
}
}
}
void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line)
{
if (control & 0x80) // 1 pal / 256 col
gfxDrawTextScreen<gfxReadTile>(control, hofs, vofs, line);
else // 16 pal / 16 col
gfxDrawTextScreen<gfxReadTilePal>(control, hofs, vofs, line);
}
#endif
struct EmulatedSystem GBASystem = { struct EmulatedSystem GBASystem = {
@ -3994,7 +4387,11 @@ struct EmulatedSystem GBASystem = {
// emuWriteState // emuWriteState
CPUWriteState, CPUWriteState,
// emuReadMemState // emuReadMemState
#ifdef __LIBRETRO__
NULL,
#else
CPUReadMemState, CPUReadMemState,
#endif
// emuWriteMemState // emuWriteMemState
CPUWriteMemState, CPUWriteMemState,
// emuWritePNG // emuWritePNG

View File

@ -90,9 +90,14 @@ extern void CPUCleanUp();
extern void CPUUpdateRender(); extern void CPUUpdateRender();
extern void CPUUpdateRenderBuffers(bool); extern void CPUUpdateRenderBuffers(bool);
extern bool CPUReadMemState(char *, int); extern bool CPUReadMemState(char *, int);
extern bool CPUReadState(const char *);
extern bool CPUWriteMemState(char *, int); extern bool CPUWriteMemState(char *, int);
#ifdef __LIBRETRO__
extern bool CPUReadState(const u8*, unsigned);
extern unsigned int CPUWriteState(u8 *data, unsigned int size);
#else
extern bool CPUReadState(const char *);
extern bool CPUWriteState(const char *); extern bool CPUWriteState(const char *);
#endif
extern int CPULoadRom(const char *); extern int CPULoadRom(const char *);
extern void doMirroring(bool); extern void doMirroring(bool);
extern void CPUUpdateRegister(u32, u16); extern void CPUUpdateRegister(u32, u16);

View File

@ -8,7 +8,11 @@
//#define SPRITE_DEBUG //#define SPRITE_DEBUG
#ifdef TILED_RENDERING
extern void gfxDrawTextScreen(u16, u16, u16, u32 *);
#else
static void gfxDrawTextScreen(u16, u16, u16, u32 *); static void gfxDrawTextScreen(u16, u16, u16, u32 *);
#endif
static void gfxDrawRotScreen(u16, static void gfxDrawRotScreen(u16,
u16, u16, u16, u16,
u16, u16, u16, u16,
@ -98,6 +102,7 @@ static inline void gfxClearArray(u32 *array)
} }
} }
#ifndef TILED_RENDERING
static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
u32 *line) u32 *line)
{ {
@ -238,6 +243,7 @@ static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
} }
} }
} }
#endif
static inline void gfxDrawRotScreen(u16 control, static inline void gfxDrawRotScreen(u16 control,
u16 x_l, u16 x_h, u16 x_l, u16 x_h,

View File

@ -49,11 +49,9 @@ static inline u32 CPUReadMemory(u32 address)
u32 value; u32 value;
u32 oldAddress = address; u32 oldAddress = address;
#ifdef C_CORE
if(address & 3) { if(address & 3) {
address &= ~0x03; address &= ~0x03;
} }
#endif
switch(address >> 24) { switch(address >> 24) {
case 0: case 0:
@ -79,18 +77,18 @@ static inline u32 CPUReadMemory(u32 address)
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
break; break;
case 4: case 4:
if((address < 0x4000400) && ioReadable[address & 0x3fc]) { if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
if(ioReadable[(address & 0x3fc) + 2]) { if(ioReadable[(address & 0x3fc) + 2]) {
value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
if ((address & 0x3fc) == COMM_JOY_RECV_L) if ((address & 0x3fc) == COMM_JOY_RECV_L)
UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV); UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV);
} else { } else {
value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
} }
} }
else else
goto unreadable; goto unreadable;
break; break;
case 5: case 5:
value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
break; break;
@ -116,14 +114,12 @@ static inline u32 CPUReadMemory(u32 address)
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
break; break;
case 13: case 13:
if(cpuEEPROMEnabled) value = eepromRead(address);
// no need to swap this break;
return eepromRead(address);
goto unreadable;
case 14: case 14:
if(cpuFlashEnabled | cpuSramEnabled) case 15:
// no need to swap this value = flashRead(address) * 0x01010101;
return flashRead(address); break;
// default // default
default: default:
unreadable: unreadable:
@ -133,18 +129,17 @@ unreadable:
armNextPC - 4 : armNextPC - 2); armNextPC - 4 : armNextPC - 2);
} }
#endif #endif
if(cpuDmaHack) {
if(cpuDmaHack) { value = cpuDmaLast;
value = cpuDmaLast; } else {
} else {
if(armState) { if(armState) {
value = CPUReadMemoryQuick(reg[15].I); return CPUReadMemoryQuick(reg[15].I);
} else { } else {
value = CPUReadHalfWordQuick(reg[15].I) | return CPUReadHalfWordQuick(reg[15].I) |
CPUReadHalfWordQuick(reg[15].I) << 16; CPUReadHalfWordQuick(reg[15].I) << 16;
} }
} }
return value; break;
} }
if(oldAddress & 3) { if(oldAddress & 3) {
@ -187,11 +182,9 @@ static inline u32 CPUReadHalfWord(u32 address)
u32 value; u32 value;
u32 oldAddress = address; u32 oldAddress = address;
//#ifdef C_CORE
if(address & 1) { if(address & 1) {
address &= ~0x01; address &= ~0x01;
} }
//#endif
switch(address >> 24) { switch(address >> 24) {
case 0: case 0:
@ -233,6 +226,10 @@ static inline u32 CPUReadHalfWord(u32 address)
value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
} }
} }
else if((address < 0x4000400) && ioReadable[address & 0x3fc])
{
value = 0;
}
else goto unreadable; else goto unreadable;
break; break;
case 5: case 5:
@ -263,34 +260,30 @@ static inline u32 CPUReadHalfWord(u32 address)
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
break; break;
case 13: case 13:
if(cpuEEPROMEnabled) value = eepromRead(address);
// no need to swap this break;
return eepromRead(address);
goto unreadable;
case 14: case 14:
if(cpuFlashEnabled | cpuSramEnabled) case 15:
// no need to swap this value = flashRead(address) * 0x0101;
return flashRead(address); break;
// default // default
default: default:
unreadable: unreadable:
#ifdef GBA_LOGGING if(cpuDmaHack) {
if(systemVerbose & VERBOSE_ILLEGAL_READ) { value = cpuDmaLast & 0xFFFF;
log("Illegal halfword read: %08x at %08x\n", oldAddress, armMode ? } else {
armNextPC - 4 : armNextPC - 2);
}
#endif
if(cpuDmaHack) {
value = cpuDmaLast & 0xFFFF;
} else {
if(armState) { if(armState) {
value = CPUReadMemoryQuick(reg[15].I); value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
} else { } else {
value = CPUReadHalfWordQuick(reg[15].I) | value = CPUReadHalfWordQuick(reg[15].I);
CPUReadHalfWordQuick(reg[15].I) << 16;
} }
} }
return value; #ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
log("Illegal halfword read: %08x at %08x (%08x)\n", oldAddress, reg[15].I, value);
}
#endif
return value;
} }
if(oldAddress & 1) { if(oldAddress & 1) {
@ -306,24 +299,19 @@ unreadable:
return value; return value;
} }
static inline u16 CPUReadHalfWordSigned(u32 address) static inline s16 CPUReadHalfWordSigned(u32 address)
{ {
u32 oldAddress = address; s32 value = (s32)CPUReadHalfWord(address);
if(address & 1) { if((address & 1))
address &= ~0x01;
}
u16 value = CPUReadHalfWord(address);
if((oldAddress & 1))
{ {
value = (s8)value;
#ifdef GBA_LOGGING #ifdef GBA_LOGGING
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
log("Unaligned signed halfword read from: %08x at %08x (%08x)\n", oldAddress, armMode ? log("Unaligned signed halfword read from: %08x at %08x (%08x)\n", address, armMode ?
armNextPC - 4 : armNextPC - 2, value); armNextPC - 4 : armNextPC - 2, value);
} }
#endif #endif
} }
return value; return (s16)value;
} }
static inline u8 CPUReadByte(u32 address) static inline u8 CPUReadByte(u32 address)
@ -368,24 +356,24 @@ static inline u8 CPUReadByte(u32 address)
case 12: case 12:
return rom[address & 0x1FFFFFF]; return rom[address & 0x1FFFFFF];
case 13: case 13:
if(cpuEEPROMEnabled) return eepromRead(address);
return eepromRead(address);
goto unreadable;
case 14: case 14:
if(cpuSramEnabled | cpuFlashEnabled) case 15:
return flashRead(address); {
if(cpuEEPROMSensorEnabled) { if (cpuEEPROMSensorEnabled) {
switch(address & 0x00008f00) { switch (address & 0x00008f00) {
case 0x8200: case 0x8200:
return systemGetSensorX() & 255; return systemGetSensorX() & 255;
case 0x8300: case 0x8300:
return (systemGetSensorX() >> 8)|0x80; return (systemGetSensorX() >> 8) | 0x80;
case 0x8400: case 0x8400:
return systemGetSensorY() & 255; return systemGetSensorY() & 255;
case 0x8500: case 0x8500:
return systemGetSensorY() >> 8; return systemGetSensorY() >> 8;
} }
} }
return flashRead(address);
}
// default // default
default: default:
unreadable: unreadable:
@ -395,17 +383,15 @@ unreadable:
armNextPC - 4 : armNextPC - 2); armNextPC - 4 : armNextPC - 2);
} }
#endif #endif
if(cpuDmaHack) { if(cpuDmaHack) {
return cpuDmaLast & 0xFF; return cpuDmaLast & 0xFF;
} else { } else {
if(armState) { if(armState) {
return CPUReadMemoryQuick(reg[15].I); return CPUReadByteQuick(reg[15].I + (address & 3));
} else { } else {
return CPUReadHalfWordQuick(reg[15].I) | return CPUReadByteQuick(reg[15].I + (address & 1));
CPUReadHalfWordQuick(reg[15].I) << 16;
} }
} }
break;
} }
} }
@ -423,6 +409,8 @@ static inline void CPUWriteMemory(u32 address, u32 value)
} }
#endif #endif
address &= 0xFFFFFFFC;
switch(address >> 24) { switch(address >> 24) {
case 0x02: case 0x02:
#ifdef BKPT_SUPPORT #ifdef BKPT_SUPPORT
@ -488,6 +476,7 @@ static inline void CPUWriteMemory(u32 address, u32 value)
} }
goto unwritable; goto unwritable;
case 0x0E: case 0x0E:
case 0x0F:
if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) { if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
(*cpuSaveGameFunc)(address, (u8)value); (*cpuSaveGameFunc)(address, (u8)value);
break; break;
@ -520,6 +509,8 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
} }
#endif #endif
address &= 0xFFFFFFFE;
switch(address >> 24) { switch(address >> 24) {
case 2: case 2:
#ifdef BKPT_SUPPORT #ifdef BKPT_SUPPORT
@ -590,6 +581,7 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
} }
goto unwritable; goto unwritable;
case 14: case 14:
case 15:
if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) { if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
(*cpuSaveGameFunc)(address, (u8)value); (*cpuSaveGameFunc)(address, (u8)value);
break; break;
@ -726,6 +718,7 @@ static inline void CPUWriteByte(u32 address, u8 b)
} }
goto unwritable; goto unwritable;
case 14: case 14:
case 15:
if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) { if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) {
//if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) { //if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) {

View File

@ -7,8 +7,15 @@
#include <time.h> #include <time.h>
#include <memory.h> #include <memory.h>
#include <string.h>
enum RTCSTATE { IDLE, COMMAND, DATA, READDATA }; enum RTCSTATE
{
IDLE = 0,
COMMAND,
DATA,
READDATA
};
typedef struct { typedef struct {
u8 byte0; u8 byte0;
@ -197,6 +204,17 @@ void rtcReset()
rtcClockData.state = IDLE; rtcClockData.state = IDLE;
} }
#ifdef __LIBRETRO__
void rtcSaveGame(u8 *&data)
{
utilWriteMem(data, &rtcClockData, sizeof(rtcClockData));
}
void rtcReadGame(const u8 *&data)
{
utilReadMem(&rtcClockData, data, sizeof(rtcClockData));
}
#else
void rtcSaveGame(gzFile gzFile) void rtcSaveGame(gzFile gzFile)
{ {
utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData)); utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
@ -206,3 +224,4 @@ void rtcReadGame(gzFile gzFile)
{ {
utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData)); utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
} }
#endif

View File

@ -7,7 +7,12 @@ void rtcEnable(bool);
bool rtcIsEnabled(); bool rtcIsEnabled();
void rtcReset(); void rtcReset();
#ifdef __LIBRETRO__
void rtcReadGame(const u8 *&data);
void rtcSaveGame(u8 *&data);
#else
void rtcReadGame(gzFile gzFile); void rtcReadGame(gzFile gzFile);
void rtcSaveGame(gzFile gzFile); void rtcSaveGame(gzFile gzFile);
#endif
#endif // RTC_H #endif // RTC_H

View File

@ -183,15 +183,19 @@ void Gba_Pcm_Fifo::timer_overflowed( int which_timer )
{ {
if ( which_timer == timer && enabled ) if ( which_timer == timer && enabled )
{ {
if ( count <= 16 ) /* Mother 3 fix, refined to not break Metroid Fusion */
if ( count == 16 || count == 0 )
{ {
// Need to fill FIFO // Need to fill FIFO
int saved_count = count;
CPUCheckDMA( 3, which ? 4 : 2 ); CPUCheckDMA( 3, which ? 4 : 2 );
if ( count <= 16 ) if ( saved_count == 0 && count == 16 )
CPUCheckDMA( 3, which ? 4 : 2 );
if ( count == 0 )
{ {
// Not filled by DMA, so fill with 16 bytes of silence // Not filled by DMA, so fill with 16 bytes of silence
int reg = which ? FIFOB_L : FIFOA_L; int reg = which ? FIFOB_L : FIFOA_L;
for ( int n = 4; n--; ) for ( int n = 8; n--; )
{ {
soundEvent(reg , (u16)0); soundEvent(reg , (u16)0);
soundEvent(reg+2, (u16)0); soundEvent(reg+2, (u16)0);
@ -348,6 +352,11 @@ static void end_frame( blip_time_t time )
void flush_samples(Multi_Buffer * buffer) void flush_samples(Multi_Buffer * buffer)
{ {
#ifdef __LIBRETRO__
int numSamples = buffer->read_samples( (blip_sample_t*) soundFinalWave, buffer->samples_avail() );
soundDriver->write(soundFinalWave, numSamples);
systemOnWriteDataToSoundBuffer(soundFinalWave, numSamples);
#else
// We want to write the data frame by frame to support legacy audio drivers // We want to write the data frame by frame to support legacy audio drivers
// that don't use the length parameter of the write method. // that don't use the length parameter of the write method.
// TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the // TODO: Update the Win32 audio drivers (DS, OAL, XA2), and flush all the
@ -370,6 +379,7 @@ void flush_samples(Multi_Buffer * buffer)
soundDriver->write(soundFinalWave, soundBufferLen); soundDriver->write(soundFinalWave, soundBufferLen);
systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen); systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
} }
#endif
} }
static void apply_filtering() static void apply_filtering()
@ -446,6 +456,13 @@ static void remake_stereo_buffer()
pcm [0].pcm.init(); pcm [0].pcm.init();
pcm [1].pcm.init(); pcm [1].pcm.init();
// APU
if ( !gb_apu )
{
gb_apu = new Gb_Apu; // TODO: handle out of memory
reset_apu();
}
// Stereo_Buffer // Stereo_Buffer
delete stereo_buffer; delete stereo_buffer;
stereo_buffer = 0; stereo_buffer = 0;
@ -459,13 +476,7 @@ static void remake_stereo_buffer()
pcm [1].which = 1; pcm [1].which = 1;
apply_filtering(); apply_filtering();
// APU // Volume Level
if ( !gb_apu )
{
gb_apu = new Gb_Apu; // TODO: handle out of memory
reset_apu();
}
apply_muting(); apply_muting();
apply_volume(); apply_volume();
} }
@ -743,16 +754,25 @@ static void skip_read( gzFile in, int count )
} }
} }
#ifdef __LIBRETRO__
void soundSaveGame( u8 *&out )
#else
void soundSaveGame( gzFile out ) void soundSaveGame( gzFile out )
#endif
{ {
gb_apu->save_state( &state.apu ); gb_apu->save_state( &state.apu );
// Be sure areas for expansion get written as zero // Be sure areas for expansion get written as zero
memset( dummy_state, 0, sizeof dummy_state ); memset( dummy_state, 0, sizeof dummy_state );
#ifdef __LIBRETRO__
utilWriteDataMem( out, gba_state );
#else
utilWriteData( out, gba_state ); utilWriteData( out, gba_state );
#endif
} }
#ifndef __LIBRETRO__
static void soundReadGameOld( gzFile in, int version ) static void soundReadGameOld( gzFile in, int version )
{ {
// Read main data // Read main data
@ -787,19 +807,28 @@ static void soundReadGameOld( gzFile in, int version )
(void) utilReadInt( in ); // ignore quality (void) utilReadInt( in ); // ignore quality
} }
#endif
#include <stdio.h> #include <stdio.h>
#ifdef __LIBRETRO__
void soundReadGame(const u8*& in, int version )
#else
void soundReadGame( gzFile in, int version ) void soundReadGame( gzFile in, int version )
#endif
{ {
// Prepare APU and default state // Prepare APU and default state
reset_apu(); reset_apu();
gb_apu->save_state( &state.apu ); gb_apu->save_state( &state.apu );
if ( version > SAVE_GAME_VERSION_9 ) if ( version > SAVE_GAME_VERSION_9 )
#ifdef __LIBRETRO__
utilReadDataMem( in, gba_state );
#else
utilReadData( in, gba_state ); utilReadData( in, gba_state );
else else
soundReadGameOld( in, version ); soundReadGameOld( in, version );
#endif
gb_apu->load_state( state.apu ); gb_apu->load_state( state.apu );
write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F ); write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F );

View File

@ -74,8 +74,13 @@ extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to so
extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called extern int soundTicks; // Number of 16.8 MHz clocks until soundTick() will be called
// Saves/loads emulator state // Saves/loads emulator state
#ifdef __LIBRETRO__
void soundSaveGame( u8 *& );
void soundReadGame(const u8*& in, int version );
#else
void soundSaveGame( gzFile ); void soundSaveGame( gzFile );
void soundReadGame( gzFile, int version ); void soundReadGame( gzFile, int version );
#endif
class Multi_Buffer; class Multi_Buffer;

View File

@ -1058,7 +1058,7 @@ void elfParseCFA(u8 *top)
if(id == 0xffffffff) { if(id == 0xffffffff) {
// skip version // skip version
*data++; (*data)++;
ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie)); ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));

View File

@ -1,3 +1,4 @@
#ifndef __LIBRETRO__
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -75,7 +76,11 @@ bool remoteTcpInit()
remoteListenSocket = s; remoteListenSocket = s;
#ifdef _WIN32
if(s == INVALID_SOCKET) {
#else
if(s < 0) { if(s < 0) {
#endif
fprintf(stderr,"Error opening socket\n"); fprintf(stderr,"Error opening socket\n");
exit(-1); exit(-1);
} }
@ -719,3 +724,4 @@ void remoteCleanUp()
if(remoteCleanUpFnc) if(remoteCleanUpFnc)
remoteCleanUpFnc(); remoteCleanUpFnc();
} }
#endif

View File

@ -30,6 +30,7 @@ const DirectoriesConfigDialog::SDirEntry DirectoriesConfigDialog::m_astDirs[] =
{ "gba_roms", N_("GBA roms :"), "GBARomsDirEntry" }, { "gba_roms", N_("GBA roms :"), "GBARomsDirEntry" },
{ "gb_roms", N_("GB roms :"), "GBRomsDirEntry" }, { "gb_roms", N_("GB roms :"), "GBRomsDirEntry" },
{ "batteries", N_("Batteries :"), "BatteriesDirEntry" }, { "batteries", N_("Batteries :"), "BatteriesDirEntry" },
{ "cheats", N_("Cheats :"), "CheatsDirEntry" },
{ "saves", N_("Saves :"), "SavesDirEntry" }, { "saves", N_("Saves :"), "SavesDirEntry" },
{ "captures", N_("Captures :"), "CapturesDirEntry" } { "captures", N_("Captures :"), "CapturesDirEntry" }
}; };

View File

@ -47,7 +47,7 @@ private:
Config::Section * m_poConfig; Config::Section * m_poConfig;
static const SDirEntry m_astDirs[]; static const SDirEntry m_astDirs[];
Gtk::FileChooserButton * m_poButtons[5]; Gtk::FileChooserButton * m_poButtons[6];
}; };
} // namespace VBA } // namespace VBA

View File

@ -27,6 +27,16 @@
namespace VBA namespace VBA
{ {
static const VBA::Window::EEmulatorType aEmulatorType[] =
{
VBA::Window::EmulatorAuto,
VBA::Window::EmulatorCGB,
VBA::Window::EmulatorSGB,
VBA::Window::EmulatorGB,
VBA::Window::EmulatorGBA,
VBA::Window::EmulatorSGB2
};
GameBoyConfigDialog::GameBoyConfigDialog(GtkDialog* _pstDialog, const Glib::RefPtr<Gtk::Builder>& refBuilder) : GameBoyConfigDialog::GameBoyConfigDialog(GtkDialog* _pstDialog, const Glib::RefPtr<Gtk::Builder>& refBuilder) :
Gtk::Dialog(_pstDialog), Gtk::Dialog(_pstDialog),
m_poConfig(0) m_poConfig(0)
@ -49,8 +59,6 @@ void GameBoyConfigDialog::vSetConfig(Config::Section * _poConfig, VBA::Window *
m_poConfig = _poConfig; m_poConfig = _poConfig;
m_poWindow = _poWindow; m_poWindow = _poWindow;
const int aEmulatorType[] = { 0, 2, 3, 5, 1, 4 };
VBA::Window::EEmulatorType eDefaultEmulatorType = (VBA::Window::EEmulatorType)m_poConfig->oGetKey<int>("emulator_type"); VBA::Window::EEmulatorType eDefaultEmulatorType = (VBA::Window::EEmulatorType)m_poConfig->oGetKey<int>("emulator_type");
m_poSystemComboBox->set_active(aEmulatorType[eDefaultEmulatorType]); m_poSystemComboBox->set_active(aEmulatorType[eDefaultEmulatorType]);
@ -70,16 +78,6 @@ void GameBoyConfigDialog::vSetConfig(Config::Section * _poConfig, VBA::Window *
void GameBoyConfigDialog::vOnSystemChanged() void GameBoyConfigDialog::vOnSystemChanged()
{ {
const VBA::Window::EEmulatorType aEmulatorType[] =
{
VBA::Window::EmulatorAuto,
VBA::Window::EmulatorCGB,
VBA::Window::EmulatorSGB,
VBA::Window::EmulatorGB,
VBA::Window::EmulatorGBA,
VBA::Window::EmulatorSGB2
};
int iSystem = m_poSystemComboBox->get_active_row_number(); int iSystem = m_poSystemComboBox->get_active_row_number();
m_poConfig->vSetKey("emulator_type", aEmulatorType[iSystem]); m_poConfig->vSetKey("emulator_type", aEmulatorType[iSystem]);

View File

@ -1,11 +1,10 @@
[Desktop Entry] [Desktop Entry]
Version=1.0 Version=1.0
Encoding=UTF-8
Type=Application Type=Application
Name=VBA-M Name=VBA-M
GenericName=GameBoy Advance Emulator GenericName=GameBoy Advance Emulator
Comment=Nindendo GameBoy Advance Emulator Comment=Nindendo GameBoy Advance Emulator
Exec=gvbam Exec=gvbam %f
Icon=vbam Icon=vbam
Categories=Application;Game;Emulator;GTK Categories=Game;Emulator;GTK;
MimeType=application/x-gameboy-rom;application/x-gameboy-advance-rom;application/x-dmg-rom;application/x-agb-rom;application/x-gb-rom;application/x-gba-rom MimeType=application/x-gameboy-rom;application/x-gameboy-advance-rom;application/x-dmg-rom;application/x-agb-rom;application/x-gb-rom;application/x-gba-rom;

View File

@ -49,10 +49,10 @@ JoypadConfigDialog::JoypadConfigDialog(Config::Section * _poConfig) :
m_oTitleLabel(_("Joypad :"), Gtk::ALIGN_RIGHT), m_oTitleLabel(_("Joypad :"), Gtk::ALIGN_RIGHT),
m_oDefaultJoypad(_("Default joypad")), m_oDefaultJoypad(_("Default joypad")),
m_oTable(G_N_ELEMENTS(m_astKeys), 2, false), m_oTable(G_N_ELEMENTS(m_astKeys), 2, false),
m_iCurrentEntry(-1),
m_bUpdating(false), m_bUpdating(false),
m_ePad(PAD_MAIN), m_ePad(PAD_MAIN),
m_poConfig(_poConfig), m_poConfig(_poConfig)
m_iCurrentEntry(-1)
{ {
// Joypad selection // Joypad selection
m_oTitleCombo.append_text("1"); m_oTitleCombo.append_text("1");
@ -115,7 +115,7 @@ void JoypadConfigDialog::vUpdateEntries()
for (guint i = 0; i < m_oEntries.size(); i++) for (guint i = 0; i < m_oEntries.size(); i++)
{ {
const char * csName = 0; std::string csName;
guint uiKeyval = inputGetKeymap(m_ePad, m_astKeys[i].m_eKeyFlag); guint uiKeyval = inputGetKeymap(m_ePad, m_astKeys[i].m_eKeyFlag);
int dev = uiKeyval >> 16; int dev = uiKeyval >> 16;
@ -158,10 +158,10 @@ void JoypadConfigDialog::vUpdateEntries()
} }
} }
csName = os.str().c_str(); csName = os.str();
} }
if (csName == 0) if (csName.empty())
{ {
m_oEntries[i]->set_text(_("<Undefined>")); m_oEntries[i]->set_text(_("<Undefined>"));
} }

View File

@ -504,6 +504,7 @@ void Window::vInitConfig()
m_poDirConfig->vSetKey("gb_roms", Glib::get_home_dir()); m_poDirConfig->vSetKey("gb_roms", Glib::get_home_dir());
m_poDirConfig->vSetKey("gba_roms", Glib::get_home_dir()); m_poDirConfig->vSetKey("gba_roms", Glib::get_home_dir());
m_poDirConfig->vSetKey("batteries", m_sUserDataDir); m_poDirConfig->vSetKey("batteries", m_sUserDataDir);
m_poDirConfig->vSetKey("cheats", m_sUserDataDir);
m_poDirConfig->vSetKey("saves", m_sUserDataDir); m_poDirConfig->vSetKey("saves", m_sUserDataDir);
m_poDirConfig->vSetKey("captures", m_sUserDataDir); m_poDirConfig->vSetKey("captures", m_sUserDataDir);
@ -588,6 +589,11 @@ void Window::vCheckConfig()
{ {
m_poDirConfig->vSetKey("batteries", m_sUserDataDir); m_poDirConfig->vSetKey("batteries", m_sUserDataDir);
} }
sValue = m_poDirConfig->sGetKey("cheats");
if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
{
m_poDirConfig->vSetKey("cheats", m_sUserDataDir);
}
sValue = m_poDirConfig->sGetKey("saves"); sValue = m_poDirConfig->sGetKey("saves");
if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR)) if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
{ {
@ -1078,6 +1084,7 @@ bool Window::bLoadROM(const std::string & _rsFile)
} }
vLoadBattery(); vLoadBattery();
vLoadCheats();
vUpdateScreen(); vUpdateScreen();
emulating = 1; emulating = 1;
@ -1342,6 +1349,30 @@ void Window::vLoadBattery()
} }
} }
void Window::vLoadCheats()
{
std::string sCheats;
std::string sDir = m_poDirConfig->sGetKey("cheats");
if (sDir == "")
{
sDir = m_sUserDataDir;
}
sCheats = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".clt";
if (Glib::file_test(sCheats, Glib::FILE_TEST_EXISTS))
{
if (m_eCartridge == CartridgeGB)
{
gbCheatsLoadCheatList(sCheats.c_str());
}
else if (m_eCartridge == CartridgeGBA)
{
cheatsLoadCheatList(sCheats.c_str());
}
}
}
void Window::vSaveBattery() void Window::vSaveBattery()
{ {
std::string sBattery; std::string sBattery;
@ -1359,6 +1390,27 @@ void Window::vSaveBattery()
} }
} }
void Window::vSaveCheats()
{
std::string sCheats;
std::string sDir = m_poDirConfig->sGetKey("cheats");
if (sDir == "")
{
sDir = m_sUserDataDir;
}
sCheats = sDir + "/" + sCutSuffix(Glib::path_get_basename(m_sRomFile)) + ".clt";
if (m_eCartridge == CartridgeGB)
{
gbCheatsSaveCheatList(sCheats.c_str());
}
else if (m_eCartridge == CartridgeGBA)
{
cheatsSaveCheatList(sCheats.c_str());
}
}
void Window::vStartEmu() void Window::vStartEmu()
{ {
if (m_oEmuSig.connected()) if (m_oEmuSig.connected())

View File

@ -272,7 +272,9 @@ private:
void vSetDefaultTitle(); void vSetDefaultTitle();
void vCreateFileOpenDialog(); void vCreateFileOpenDialog();
void vLoadBattery(); void vLoadBattery();
void vLoadCheats();
void vSaveBattery(); void vSaveBattery();
void vSaveCheats();
void vStartEmu(); void vStartEmu();
void vStopEmu(); void vStopEmu();
void vUpdateGameSlots(); void vUpdateGameSlots();

View File

@ -335,6 +335,7 @@ void Window::vOnFileClose()
vSetDefaultTitle(); vSetDefaultTitle();
vDrawDefaultScreen(); vDrawDefaultScreen();
vSaveBattery(); vSaveBattery();
vSaveCheats();
m_stEmulator.emuCleanUp(); m_stEmulator.emuCleanUp();
m_eCartridge = CartridgeNone; m_eCartridge = CartridgeNone;
emulating = 0; emulating = 0;

View File

@ -125,6 +125,7 @@ int desktopHeight = 0;
Filter filter = kStretch2x; Filter filter = kStretch2x;
u8 *delta = NULL; u8 *delta = NULL;
static const int delta_size = 322*242*4;
int filter_enlarge = 2; int filter_enlarge = 2;
@ -1395,7 +1396,7 @@ void sdlPollEvents()
soundPause(); soundPause();
} }
memset(delta,255,sizeof(delta)); memset(delta,255,delta_size);
} }
} }
break; break;
@ -2311,8 +2312,8 @@ int main(int argc, char **argv)
utilUpdateSystemColorMaps(); utilUpdateSystemColorMaps();
if(delta == NULL) { if(delta == NULL) {
delta = (u8*)malloc(322*242*4); delta = (u8*)malloc(delta_size);
memset(delta, 255, 322*242*4); memset(delta, 255, delta_size);
} }
ifbFunction = initIFBFilter(ifbType, systemColorDepth); ifbFunction = initIFBFilter(ifbType, systemColorDepth);

View File

@ -345,9 +345,9 @@ bool OpenGLDisplay::initialize()
cpu_mmx = 0; cpu_mmx = 0;
#endif #endif
systemRedShift = 3; systemRedShift = 19;
systemGreenShift = 11; systemGreenShift = 11;
systemBlueShift = 19; systemBlueShift = 3;
systemColorDepth = 32; systemColorDepth = 32;
theApp.fsColorDepth = 32; theApp.fsColorDepth = 32;
@ -401,7 +401,7 @@ void OpenGLDisplay::render()
} else { } else {
glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX + 1 ); glPixelStorei( GL_UNPACK_ROW_LENGTH, theApp.sizeX + 1 );
} }
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_RGBA,GL_UNSIGNED_BYTE,data ); glTexSubImage2D(GL_TEXTURE_2D,0,0,0,width,height,GL_BGRA,GL_UNSIGNED_BYTE,data );
glBegin( GL_QUADS ); glBegin( GL_QUADS );

View File

@ -287,9 +287,9 @@ bool XAudio2_Output::init(long sampleRate)
// Initialize XAudio2 // Initialize XAudio2
UINT32 flags = 0; UINT32 flags = 0;
#ifdef _DEBUG //#ifdef _DEBUG
flags = XAUDIO2_DEBUG_ENGINE; // flags = XAUDIO2_DEBUG_ENGINE;
#endif //#endif
hr = XAudio2Create( &xaud, flags ); hr = XAudio2Create( &xaud, flags );
if( hr != S_OK ) { if( hr != S_OK ) {

View File

@ -138,7 +138,7 @@ void rpiFilter(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch,
*(pOCur++) = ((*pICur & 0xF800) << rshiftDiff) | *(pOCur++) = ((*pICur & 0xF800) << rshiftDiff) |
((*pICur & 0x07E0) << gshiftDiff) | ((*pICur & 0x07E0) << gshiftDiff) |
((*pICur & 0x001F) << bshiftDiff); ((*pICur & 0x001F) << bshiftDiff);
*pICur++; *(pICur++);
} }
pI = pICur = (u16 *)((char *)pI + dstPitch); pI = pICur = (u16 *)((char *)pI + dstPitch);
pO = pOCur = (u32 *)((char *)pO + dstPitch); pO = pOCur = (u32 *)((char *)pO + dstPitch);
@ -157,7 +157,7 @@ void rpiFilter(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch,
*(pOCur++) = ((*pICur & 0xF800) >> rshiftDiff) | *(pOCur++) = ((*pICur & 0xF800) >> rshiftDiff) |
((*pICur & 0x07E0) << gshiftDiff) | ((*pICur & 0x07E0) << gshiftDiff) |
((*pICur & 0x001F) << bshiftDiff); ((*pICur & 0x001F) << bshiftDiff);
*pICur++; *(pICur++);
} }
pI = pICur = (u16 *)((char *)pI + dstPitch); pI = pICur = (u16 *)((char *)pI + dstPitch);
pO = pOCur = (u32 *)((char *)pO + dstPitch); pO = pOCur = (u32 *)((char *)pO + dstPitch);