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:
parent
a604ebee68
commit
05435d0f34
|
@ -6,7 +6,7 @@ or when stated otherwise in the source file:
|
|||
|
||||
Copyright for the modifications to the files mentioned above:
|
||||
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
|
||||
|
|
|
@ -138,6 +138,7 @@ Spacy
|
|||
DJRobX
|
||||
Jonas Quinn
|
||||
kode54
|
||||
Normmatt
|
||||
|
||||
==============
|
||||
Special Thanks
|
||||
|
@ -171,4 +172,7 @@ kode64:
|
|||
|
||||
shuffle2:
|
||||
- SFML library
|
||||
- various build fixes
|
||||
- various build fixes
|
||||
|
||||
Squarepusher
|
||||
- Libretro merge
|
77
src/System.h
77
src/System.h
|
@ -1,45 +1,49 @@
|
|||
#ifndef SYSTEM_H
|
||||
#define SYSTEM_H
|
||||
|
||||
#include "common/Types.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
class SoundDriver;
|
||||
|
||||
struct EmulatedSystem {
|
||||
// main emulation function
|
||||
void (*emuMain)(int);
|
||||
// reset emulator
|
||||
void (*emuReset)();
|
||||
// clean up memory
|
||||
void (*emuCleanUp)();
|
||||
// load battery file
|
||||
bool (*emuReadBattery)(const char *);
|
||||
// write battery file
|
||||
bool (*emuWriteBattery)(const char *);
|
||||
// load state
|
||||
bool (*emuReadState)(const char *);
|
||||
// save state
|
||||
bool (*emuWriteState)(const char *);
|
||||
// load memory state (rewind)
|
||||
bool (*emuReadMemState)(char *, int);
|
||||
// write memory state (rewind)
|
||||
bool (*emuWriteMemState)(char *, int);
|
||||
// write PNG file
|
||||
bool (*emuWritePNG)(const char *);
|
||||
// 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;
|
||||
// main emulation function
|
||||
void (*emuMain)(int);
|
||||
// reset emulator
|
||||
void (*emuReset)();
|
||||
// clean up memory
|
||||
void (*emuCleanUp)();
|
||||
// load battery file
|
||||
bool (*emuReadBattery)(const char *);
|
||||
// write battery file
|
||||
bool (*emuWriteBattery)(const char *);
|
||||
#ifdef __LIBRETRO__
|
||||
// load state
|
||||
bool (*emuReadState)(const u8*, unsigned);
|
||||
// load state
|
||||
unsigned (*emuWriteState)(u8*, unsigned);
|
||||
#else
|
||||
// load state
|
||||
bool (*emuReadState)(const char *);
|
||||
// save state
|
||||
bool (*emuWriteState)(const char *);
|
||||
#endif
|
||||
// load memory state (rewind)
|
||||
bool (*emuReadMemState)(char *, int);
|
||||
// write memory state (rewind)
|
||||
bool (*emuWriteMemState)(char *, int);
|
||||
// write PNG file
|
||||
bool (*emuWritePNG)(const char *);
|
||||
// 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 bool systemPauseOnFrame();
|
||||
extern void systemGbPrint(u8 *,int,int,int,int,int);
|
||||
extern void systemScreenCapture(int);
|
||||
|
@ -56,14 +60,13 @@ extern void systemOnWriteDataToSoundBuffer(const u16 * finalWave, int length);
|
|||
extern void systemOnSoundShutdown();
|
||||
extern void systemScreenMessage(const char *);
|
||||
extern void systemUpdateMotionSensor();
|
||||
extern int systemGetSensorX();
|
||||
extern int systemGetSensorY();
|
||||
extern int systemGetSensorX();
|
||||
extern int systemGetSensorY();
|
||||
extern bool systemCanChangeSoundQuality();
|
||||
extern void systemShowSpeed(int);
|
||||
extern void system10Frames(int);
|
||||
extern void systemFrame();
|
||||
extern void systemGbBorderOn();
|
||||
|
||||
extern void Sm60FPS_Init();
|
||||
extern bool Sm60FPS_CanSkipFrame();
|
||||
extern void Sm60FPS_Sleep();
|
||||
|
@ -73,10 +76,8 @@ extern void DbgMsg(const char *msg, ...);
|
|||
#else
|
||||
extern void winlog(const char *,...);
|
||||
#endif
|
||||
|
||||
extern void (*dbgOutput)(const char *s, u32 addr);
|
||||
extern void (*dbgSignal)(int sig,int number);
|
||||
|
||||
extern u16 systemColorMap16[0x10000];
|
||||
extern u32 systemColorMap32[0x10000];
|
||||
extern u16 systemGbPalette[24];
|
||||
|
@ -89,8 +90,6 @@ extern int systemVerbose;
|
|||
extern int systemFrameSkip;
|
||||
extern int systemSaveUpdateCounter;
|
||||
extern int systemSpeed;
|
||||
|
||||
#define SYSTEM_SAVE_UPDATED 30
|
||||
#define SYSTEM_SAVE_NOT_UPDATED 0
|
||||
|
||||
#endif // SYSTEM_H
|
||||
#endif // SYSTEM_H
|
||||
|
|
|
@ -439,6 +439,8 @@ static bool utilIsImage(const char *file)
|
|||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048]);
|
||||
|
||||
IMAGE_TYPE utilFindType(const char *file)
|
||||
{
|
||||
char buffer [2048];
|
||||
|
@ -453,11 +455,10 @@ IMAGE_TYPE utilFindType(const char *file, char (&buffer)[2048])
|
|||
pwText = new wchar_t[dwNum];
|
||||
if(!pwText)
|
||||
{
|
||||
delete []pwText;
|
||||
return IMAGE_UNKNOWN;
|
||||
}
|
||||
MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
|
||||
char* file_conv = fex_wide_to_path( pwText);
|
||||
delete []pwText;
|
||||
// if ( !utilIsImage( file_conv ) ) // TODO: utilIsArchive() instead?
|
||||
// {
|
||||
fex_t* fe = scan_arc(file_conv,utilIsImage,buffer);
|
||||
|
@ -501,7 +502,7 @@ u8 *utilLoad(const char *file,
|
|||
pwText = new wchar_t[dwNum];
|
||||
if(!pwText)
|
||||
{
|
||||
delete []pwText;
|
||||
return NULL;
|
||||
}
|
||||
MultiByteToWideChar (CP_ACP, 0, file, -1, pwText, dwNum );
|
||||
char* file_conv = fex_wide_to_path( pwText);
|
||||
|
@ -718,4 +719,4 @@ bool utilFileExists( const char *filename )
|
|||
fclose( f );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
26
src/Util.h
26
src/Util.h
|
@ -11,23 +11,22 @@ enum IMAGE_TYPE {
|
|||
|
||||
// save game
|
||||
typedef struct {
|
||||
void *address;
|
||||
int size;
|
||||
void *address;
|
||||
int size;
|
||||
} variable_desc;
|
||||
|
||||
bool utilWritePNGFile(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 utilIsGBImage(const char *);
|
||||
bool utilIsGzipFile(const char *);
|
||||
bool utilIsZipFile(const char *);
|
||||
void utilStripDoubleExtension(const char *, char *);
|
||||
IMAGE_TYPE utilFindType(const char *);
|
||||
IMAGE_TYPE utilFindType(const char *, char (&)[2048]);
|
||||
u8 *utilLoad(const char *, bool (*)(const char*), u8 *, int &);
|
||||
uint8_t *utilLoad(const char *, bool (*)(const char*), uint8_t *, int &);
|
||||
|
||||
void utilPutDword(u8 *, u32);
|
||||
void utilPutWord(u8 *, u16);
|
||||
void utilPutDword(uint8_t *, uint32_t);
|
||||
void utilPutWord(uint8_t *, uint16_t);
|
||||
void utilWriteData(gzFile, variable_desc *);
|
||||
void utilReadData(gzFile, variable_desc *);
|
||||
void utilReadDataSkip(gzFile, variable_desc *);
|
||||
|
@ -44,4 +43,15 @@ void utilGBAFindSave(const u8 *, const int);
|
|||
void utilUpdateSystemColorMaps(bool lcd = false);
|
||||
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
|
||||
|
|
|
@ -276,7 +276,7 @@ static bool patchApplyUPS(const char *patchname, u8 **rom, int *size)
|
|||
static int ppfVersion(FILE *f)
|
||||
{
|
||||
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;
|
||||
switch(fgetc(f)){
|
||||
case '1': return 1;
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
#ifndef 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"
|
||||
|
||||
// swaps a 16-bit value
|
||||
|
|
|
@ -40,12 +40,22 @@ void SoundSDL::read(u16 * stream, int length)
|
|||
if (!_initialized || length <= 0 || !emulating)
|
||||
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);
|
||||
|
||||
_rbuf.read(stream, std::min(static_cast<std::size_t>(length) / 2, _rbuf.used()));
|
||||
|
||||
SDL_CondSignal(_cond);
|
||||
SDL_mutexV(_mutex);
|
||||
|
||||
SDL_SemPost (_semBufferEmpty);
|
||||
}
|
||||
|
||||
void SoundSDL::write(u16 * finalWave, int length)
|
||||
|
@ -63,23 +73,25 @@ void SoundSDL::write(u16 * finalWave, int length)
|
|||
std::size_t avail;
|
||||
while ((avail = _rbuf.avail() / 2) < samples)
|
||||
{
|
||||
bool lock = (emulating && !speedup) ? true : false;
|
||||
|
||||
_rbuf.write(finalWave, avail * 2);
|
||||
|
||||
finalWave += avail * 2;
|
||||
samples -= avail;
|
||||
|
||||
// If emulating and not in speed up mode, synchronize to audio
|
||||
// by waiting till there is enough room in the buffer
|
||||
if (emulating && !speedup)
|
||||
SDL_mutexV(_mutex);
|
||||
SDL_SemPost(_semBufferFull);
|
||||
if (lock)
|
||||
{
|
||||
SDL_CondWait(_cond, _mutex);
|
||||
SDL_SemWait(_semBufferEmpty);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Drop the remaining of the audio data
|
||||
SDL_mutexV(_mutex);
|
||||
return;
|
||||
}
|
||||
SDL_mutexP(_mutex);
|
||||
}
|
||||
|
||||
_rbuf.write(finalWave, samples * 2);
|
||||
|
@ -106,9 +118,10 @@ bool SoundSDL::init(long sampleRate)
|
|||
|
||||
_rbuf.reset(_delay * sampleRate * 2);
|
||||
|
||||
_cond = SDL_CreateCond();
|
||||
_mutex = SDL_CreateMutex();
|
||||
_initialized = true;
|
||||
_mutex = SDL_CreateMutex();
|
||||
_semBufferFull = SDL_CreateSemaphore (0);
|
||||
_semBufferEmpty = SDL_CreateSemaphore (1);
|
||||
_initialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -121,11 +134,14 @@ SoundSDL::~SoundSDL()
|
|||
SDL_mutexP(_mutex);
|
||||
int iSave = emulating;
|
||||
emulating = 0;
|
||||
SDL_CondSignal(_cond);
|
||||
SDL_SemPost(_semBufferFull);
|
||||
SDL_SemPost(_semBufferEmpty);
|
||||
SDL_mutexV(_mutex);
|
||||
|
||||
SDL_DestroyCond(_cond);
|
||||
_cond = NULL;
|
||||
SDL_DestroySemaphore(_semBufferFull);
|
||||
SDL_DestroySemaphore(_semBufferEmpty);
|
||||
_semBufferFull = NULL;
|
||||
_semBufferEmpty = NULL;
|
||||
|
||||
SDL_DestroyMutex(_mutex);
|
||||
_mutex = NULL;
|
||||
|
|
|
@ -38,8 +38,9 @@ public:
|
|||
private:
|
||||
RingBuffer<u16> _rbuf;
|
||||
|
||||
SDL_cond * _cond;
|
||||
SDL_mutex * _mutex;
|
||||
SDL_sem *_semBufferFull;
|
||||
SDL_sem *_semBufferEmpty;
|
||||
|
||||
bool _initialized;
|
||||
|
||||
|
|
|
@ -234,7 +234,7 @@ void gbRenderLine()
|
|||
|
||||
if(y >= inUseRegister_WY) {
|
||||
|
||||
if (gbWindowLine>143)
|
||||
if ((gbWindowLine == -1) || (gbWindowLine>144))
|
||||
gbWindowLine = 0;
|
||||
|
||||
int wx = register_WX;
|
||||
|
@ -266,7 +266,7 @@ void gbRenderLine()
|
|||
|
||||
//bx >>= ((gbSCXLine[0]+(((swx>1) && (swx != 7)) ? 1 : 0)) & 7);
|
||||
|
||||
if ((swx == 7))
|
||||
if (swx == 7)
|
||||
{
|
||||
//wx = 0;
|
||||
if ((gbWindowLine>0) || (wy == 0))
|
||||
|
|
|
@ -121,6 +121,13 @@ static void reset_apu()
|
|||
|
||||
static void remake_stereo_buffer()
|
||||
{
|
||||
// APU
|
||||
if ( !gb_apu )
|
||||
{
|
||||
gb_apu = new Gb_Apu; // TODO: handle errors
|
||||
reset_apu();
|
||||
}
|
||||
|
||||
// Stereo_Buffer
|
||||
delete stereo_buffer;
|
||||
stereo_buffer = 0;
|
||||
|
@ -128,20 +135,15 @@ static void remake_stereo_buffer()
|
|||
stereo_buffer = new Simple_Effects_Buffer; // 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 );
|
||||
|
||||
// APU
|
||||
|
||||
// Multi_Buffer
|
||||
static int const chan_types [chan_count] = {
|
||||
Multi_Buffer::wave_type+1, Multi_Buffer::wave_type+2,
|
||||
Multi_Buffer::wave_type+3, Multi_Buffer::mixed_type+1
|
||||
};
|
||||
if ( stereo_buffer->set_channel_count( chan_count, chan_types ) ) { } // TODO: handle errors
|
||||
|
||||
if ( !gb_apu )
|
||||
{
|
||||
gb_apu = new Gb_Apu; // TODO: handle errors
|
||||
reset_apu();
|
||||
}
|
||||
|
||||
// Volume Level
|
||||
apply_effects();
|
||||
apply_volume();
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#ifndef __LIBRETRO__
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -2896,3 +2897,4 @@ void cheatsWriteByte(u32, u8)
|
|||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include "GBA.h"
|
||||
#include "EEprom.h"
|
||||
#include "../Util.h"
|
||||
|
@ -9,7 +10,15 @@ int eepromMode = EEPROM_IDLE;
|
|||
int eepromByte = 0;
|
||||
int eepromBits = 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];
|
||||
#endif
|
||||
|
||||
u8 eepromBuffer[16];
|
||||
bool eepromInUse = false;
|
||||
int eepromSize = 512;
|
||||
|
@ -27,7 +36,11 @@ variable_desc eepromSaveData[] = {
|
|||
|
||||
void eepromInit()
|
||||
{
|
||||
memset(eepromData, 255, sizeof(eepromData));
|
||||
#ifdef __LIBRETRO__
|
||||
memset(eepromData, 255, 0x2000);
|
||||
#else
|
||||
memset(eepromData, 255, sizeof(eepromData));
|
||||
#endif
|
||||
}
|
||||
|
||||
void eepromReset()
|
||||
|
@ -40,6 +53,26 @@ void eepromReset()
|
|||
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)
|
||||
{
|
||||
utilWriteData(gzFile, eepromSaveData);
|
||||
|
@ -68,6 +101,7 @@ void eepromReadGameSkip(gzFile gzFile, int version)
|
|||
utilGzSeek(gzFile, 0x2000, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int eepromRead(u32 /* address */)
|
||||
{
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
#ifndef 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 eepromReadGame(gzFile _gzFile, int version);
|
||||
#endif
|
||||
extern void eepromReadGameSkip(gzFile _gzFile, int version);
|
||||
extern int eepromRead(u32 address);
|
||||
extern void eepromWrite(u32 address, u8 value);
|
||||
extern void eepromInit();
|
||||
extern void eepromReset();
|
||||
#ifdef __LIBRETRO__
|
||||
extern u8 *eepromData;
|
||||
#else
|
||||
extern u8 eepromData[0x2000];
|
||||
#endif
|
||||
extern bool eepromInUse;
|
||||
extern int eepromSize;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include "GBA.h"
|
||||
#include "Globals.h"
|
||||
|
@ -17,7 +18,13 @@
|
|||
#define FLASH_PROGRAM 8
|
||||
#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 flashReadState = FLASH_READ_ARRAY;
|
||||
int flashSize = 0x10000;
|
||||
|
@ -51,7 +58,11 @@ static variable_desc flashSaveData3[] = {
|
|||
|
||||
void flashInit()
|
||||
{
|
||||
memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
|
||||
#ifdef __LIBRETRO__
|
||||
memset(flashSaveMemory, 0xff, 0x20000);
|
||||
#else
|
||||
memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
|
||||
#endif
|
||||
}
|
||||
|
||||
void flashReset()
|
||||
|
@ -61,6 +72,17 @@ void flashReset()
|
|||
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)
|
||||
{
|
||||
utilWriteData(gzFile, flashSaveData3);
|
||||
|
@ -90,6 +112,8 @@ void flashReadGameSkip(gzFile gzFile, int version)
|
|||
utilReadDataSkip(gzFile, flashSaveData3);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void flashSetSize(int size)
|
||||
{
|
||||
|
|
|
@ -3,13 +3,22 @@
|
|||
|
||||
#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 flashReadGame(gzFile _gzFile, int version);
|
||||
#endif
|
||||
extern void flashReadGameSkip(gzFile _gzFile, int version);
|
||||
extern u8 flashRead(u32 address);
|
||||
extern void flashWrite(u32 address, u8 byte);
|
||||
extern void flashDelayedWrite(u32 address, u8 byte);
|
||||
#ifdef __LIBRETRO__
|
||||
extern uint8_t *flashSaveMemory;
|
||||
#else
|
||||
extern u8 flashSaveMemory[FLASH_128K_SZ];
|
||||
#endif
|
||||
extern void flashSaveDecide(u32 address, u8 byte);
|
||||
extern void flashReset();
|
||||
extern void flashSetSize(int size);
|
||||
|
|
|
@ -356,7 +356,11 @@ static void count(u32 opcode, int cond_res)
|
|||
EMIT2(and, KONST(0x1F), ecx)
|
||||
#define VALUE_LOAD_REG \
|
||||
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(and, KONST(0x0F), 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_LDRH reg[dest].I = CPUReadHalfWord(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 WRITEBACK_NONE /*nothing*/
|
||||
|
@ -2608,8 +2612,7 @@ static INSN_REGPARM void armA00(u32 opcode)
|
|||
reg[15].I += 4;
|
||||
ARM_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
||||
clockTicks += 2 + codeTicksAccess32(armNextPC)
|
||||
+ codeTicksAccessSeq32(armNextPC);
|
||||
clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
|
||||
|
@ -2625,8 +2628,7 @@ static INSN_REGPARM void armB00(u32 opcode)
|
|||
reg[15].I += 4;
|
||||
ARM_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
||||
clockTicks += 2 + codeTicksAccess32(armNextPC)
|
||||
+ codeTicksAccessSeq32(armNextPC);
|
||||
clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
|
||||
|
@ -2644,9 +2646,8 @@ static INSN_REGPARM void armE01(u32 opcode)
|
|||
// SWI <comment>
|
||||
static INSN_REGPARM void armF00(u32 opcode)
|
||||
{
|
||||
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
||||
clockTicks += 2 + codeTicksAccess32(armNextPC)
|
||||
+ codeTicksAccessSeq32(armNextPC);
|
||||
clockTicks = codeTicksAccessSeq32(armNextPC) + 1;
|
||||
clockTicks = (clockTicks * 2) + codeTicksAccess32(armNextPC) + 1;
|
||||
busPrefetchCount = 0;
|
||||
CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
|
||||
}
|
||||
|
@ -2700,7 +2701,7 @@ static insnfunc_t armInsnTable[4096] = {
|
|||
arm0E0,arm0E1,arm0E2,arm0E3,arm0E4,arm0E5,arm0E6,arm0E7, // 0E0
|
||||
arm0E0,arm0E9,arm0E2,arm0CB,arm0E4,arm_UI,arm0E6,arm_UI, // 0E8
|
||||
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
|
||||
arm_UI,arm109,arm_UI,arm10B,arm_UI,arm_UI,arm_UI,arm_UI, // 108
|
||||
|
|
|
@ -1421,12 +1421,14 @@ static INSN_REGPARM void thumb45_3(u32 opcode)
|
|||
static INSN_REGPARM void thumb46_0(u32 opcode)
|
||||
{
|
||||
reg[opcode&7].I = reg[((opcode>>3)&7)].I;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
}
|
||||
|
||||
// MOV Rd, Hs
|
||||
static INSN_REGPARM void thumb46_1(u32 opcode)
|
||||
{
|
||||
reg[opcode&7].I = reg[((opcode>>3)&7)+8].I;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
}
|
||||
|
||||
// MOV Hd, Rs
|
||||
|
@ -1473,16 +1475,14 @@ static INSN_REGPARM void thumb47(u32 opcode)
|
|||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC)
|
||||
+ codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 3;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
|
||||
} else {
|
||||
armState = true;
|
||||
reg[15].I &= 0xFFFFFFFC;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 4;
|
||||
ARM_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq32(armNextPC)
|
||||
+ codeTicksAccessSeq32(armNextPC) + codeTicksAccess32(armNextPC) + 3;
|
||||
clockTicks = codeTicksAccessSeq32(armNextPC)*2 + codeTicksAccess32(armNextPC) + 3;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1576,7 +1576,7 @@ static INSN_REGPARM void thumb5E(u32 opcode)
|
|||
if (busPrefetchCount == 0)
|
||||
busPrefetch = busPrefetchEnable;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1669,6 +1669,7 @@ static INSN_REGPARM void thumbA0(u32 opcode)
|
|||
{
|
||||
u8 regist = (opcode >> 8) & 7;
|
||||
reg[regist].I = (reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
|
||||
clockTicks = 1 + codeTicksAccess16(armNextPC);
|
||||
}
|
||||
|
||||
// ADD R0~R7, SP, Imm
|
||||
|
@ -1676,6 +1677,7 @@ static INSN_REGPARM void thumbA8(u32 opcode)
|
|||
{
|
||||
u8 regist = (opcode >> 8) & 7;
|
||||
reg[regist].I = reg[13].I + ((opcode&255)<<2);
|
||||
clockTicks = 1 + codeTicksAccess16(armNextPC);
|
||||
}
|
||||
|
||||
// ADD SP, Imm
|
||||
|
@ -1685,6 +1687,7 @@ static INSN_REGPARM void thumbB0(u32 opcode)
|
|||
if(opcode & 0x80)
|
||||
offset = -offset;
|
||||
reg[13].I += offset;
|
||||
clockTicks = 1 + codeTicksAccess16(armNextPC);
|
||||
}
|
||||
|
||||
// Push and pop ///////////////////////////////////////////////////////////
|
||||
|
@ -1882,13 +1885,13 @@ static INSN_REGPARM void thumbC8(u32 opcode)
|
|||
static INSN_REGPARM void thumbD0(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(Z_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -1897,13 +1900,13 @@ static INSN_REGPARM void thumbD0(u32 opcode)
|
|||
static INSN_REGPARM void thumbD1(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(!Z_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -1912,13 +1915,13 @@ static INSN_REGPARM void thumbD1(u32 opcode)
|
|||
static INSN_REGPARM void thumbD2(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(C_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -1927,13 +1930,13 @@ static INSN_REGPARM void thumbD2(u32 opcode)
|
|||
static INSN_REGPARM void thumbD3(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(!C_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -1942,13 +1945,13 @@ static INSN_REGPARM void thumbD3(u32 opcode)
|
|||
static INSN_REGPARM void thumbD4(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(N_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -1957,13 +1960,13 @@ static INSN_REGPARM void thumbD4(u32 opcode)
|
|||
static INSN_REGPARM void thumbD5(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(!N_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -1972,13 +1975,13 @@ static INSN_REGPARM void thumbD5(u32 opcode)
|
|||
static INSN_REGPARM void thumbD6(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(V_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -1987,13 +1990,13 @@ static INSN_REGPARM void thumbD6(u32 opcode)
|
|||
static INSN_REGPARM void thumbD7(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(!V_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -2002,13 +2005,13 @@ static INSN_REGPARM void thumbD7(u32 opcode)
|
|||
static INSN_REGPARM void thumbD8(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(C_FLAG && !Z_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -2017,13 +2020,13 @@ static INSN_REGPARM void thumbD8(u32 opcode)
|
|||
static INSN_REGPARM void thumbD9(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(!C_FLAG || Z_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -2032,13 +2035,13 @@ static INSN_REGPARM void thumbD9(u32 opcode)
|
|||
static INSN_REGPARM void thumbDA(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(N_FLAG == V_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -2047,13 +2050,13 @@ static INSN_REGPARM void thumbDA(u32 opcode)
|
|||
static INSN_REGPARM void thumbDB(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(N_FLAG != V_FLAG) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -2062,13 +2065,13 @@ static INSN_REGPARM void thumbDB(u32 opcode)
|
|||
static INSN_REGPARM void thumbDC(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + 1;
|
||||
if(!Z_FLAG && (N_FLAG == V_FLAG)) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -2077,13 +2080,13 @@ static INSN_REGPARM void thumbDC(u32 opcode)
|
|||
static INSN_REGPARM void thumbDD(u32 opcode)
|
||||
{
|
||||
UPDATE_OLDREG;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC);
|
||||
if(Z_FLAG || (N_FLAG != V_FLAG)) {
|
||||
reg[15].I += ((s8)(opcode & 0xFF)) << 1;
|
||||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC)+3;
|
||||
clockTicks += codeTicksAccessSeq16(armNextPC) + codeTicksAccess16(armNextPC) + 2;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
}
|
||||
|
@ -2094,8 +2097,8 @@ static INSN_REGPARM void thumbDD(u32 opcode)
|
|||
static INSN_REGPARM void thumbDF(u32 opcode)
|
||||
{
|
||||
u32 address = 0;
|
||||
clockTicks = codeTicksAccessSeq16(address) + codeTicksAccessSeq16(address) +
|
||||
codeTicksAccess16(address)+3;
|
||||
//clockTicks = codeTicksAccessSeq16(address)*2 + codeTicksAccess16(address)+3;
|
||||
clockTicks = 3;
|
||||
busPrefetchCount=0;
|
||||
CPUSoftwareInterrupt(opcode & 0xFF);
|
||||
}
|
||||
|
@ -2110,8 +2113,7 @@ static INSN_REGPARM void thumbE0(u32 opcode)
|
|||
armNextPC = reg[15].I;
|
||||
reg[15].I += 2;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) + codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC) + 3;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC)+3;
|
||||
busPrefetchCount=0;
|
||||
}
|
||||
|
||||
|
@ -2141,8 +2143,7 @@ static INSN_REGPARM void thumbF8(u32 opcode)
|
|||
reg[15].I += 2;
|
||||
reg[14].I = temp|1;
|
||||
THUMB_PREFETCH;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC) +
|
||||
codeTicksAccess16(armNextPC) + codeTicksAccessSeq16(armNextPC) + 3;
|
||||
clockTicks = codeTicksAccessSeq16(armNextPC)*2 + codeTicksAccess16(armNextPC) + 3;
|
||||
busPrefetchCount = 0;
|
||||
}
|
||||
|
||||
|
|
423
src/gba/GBA.cpp
423
src/gba/GBA.cpp
|
@ -120,6 +120,9 @@ int capture = 0;
|
|||
int capturePrevious = 0;
|
||||
int captureNumber = 0;
|
||||
|
||||
int armOpcodeCount = 0;
|
||||
int thumbOpcodeCount = 0;
|
||||
|
||||
const int TIMER_TICKS[4] = {
|
||||
0,
|
||||
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, ®[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)
|
||||
{
|
||||
utilWriteInt(gzFile, SAVE_GAME_VERSION);
|
||||
|
@ -627,6 +668,7 @@ bool CPUWriteState(const char *file)
|
|||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool CPUWriteMemState(char *memory, int available)
|
||||
{
|
||||
gzFile gzFile = utilMemGzOpen(memory, available, "w");
|
||||
|
@ -646,7 +688,108 @@ bool CPUWriteMemState(char *memory, int available)
|
|||
|
||||
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(®[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)
|
||||
{
|
||||
int version = utilReadInt(gzFile);
|
||||
|
@ -843,6 +986,7 @@ bool CPUReadState(const char * file)
|
|||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CPUExportEepromFile(const char *fileName)
|
||||
{
|
||||
|
@ -934,7 +1078,7 @@ bool CPUReadGSASnapshot(const char *fileName)
|
|||
fseek(file, 0x0, SEEK_SET);
|
||||
fread(&i, 1, 4, file);
|
||||
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
|
||||
fseek(file, i, SEEK_CUR); // skip name
|
||||
fread(&i, 1, 4, file); // desc length
|
||||
|
@ -1806,8 +1950,8 @@ void CPUSoftwareInterrupt(int comment)
|
|||
case 0x02:
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("Halt: (VCOUNT = %2d)\n",
|
||||
VCOUNT);
|
||||
/*log("Halt: (VCOUNT = %2d)\n",
|
||||
VCOUNT);*/
|
||||
}
|
||||
#endif
|
||||
holdState = true;
|
||||
|
@ -1817,8 +1961,8 @@ void CPUSoftwareInterrupt(int comment)
|
|||
case 0x03:
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("Stop: (VCOUNT = %2d)\n",
|
||||
VCOUNT);
|
||||
/*log("Stop: (VCOUNT = %2d)\n",
|
||||
VCOUNT);*/
|
||||
}
|
||||
#endif
|
||||
holdState = true;
|
||||
|
@ -2073,6 +2217,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
|
|||
int dw = 0;
|
||||
int sc = c;
|
||||
|
||||
cpuDmaHack = true;
|
||||
cpuDmaCount = c;
|
||||
// This is done to get the correct waitstates.
|
||||
if (sm>15)
|
||||
|
@ -2141,7 +2286,7 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32)
|
|||
}
|
||||
|
||||
cpuDmaTicksToUpdate += totalTicks;
|
||||
|
||||
cpuDmaHack = false;
|
||||
}
|
||||
|
||||
void CPUCheckDMA(int reason, int dmamask)
|
||||
|
@ -2184,7 +2329,6 @@ void CPUCheckDMA(int reason, int dmamask)
|
|||
doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement,
|
||||
DM0CNT_L ? DM0CNT_L : 0x4000,
|
||||
DM0CNT_H & 0x0400);
|
||||
cpuDmaHack = true;
|
||||
|
||||
if(DM0CNT_H & 0x4000) {
|
||||
IF |= 0x0100;
|
||||
|
@ -2253,7 +2397,6 @@ void CPUCheckDMA(int reason, int dmamask)
|
|||
DM1CNT_L ? DM1CNT_L : 0x4000,
|
||||
DM1CNT_H & 0x0400);
|
||||
}
|
||||
cpuDmaHack = true;
|
||||
|
||||
if(DM1CNT_H & 0x4000) {
|
||||
IF |= 0x0200;
|
||||
|
@ -2323,7 +2466,6 @@ void CPUCheckDMA(int reason, int dmamask)
|
|||
DM2CNT_L ? DM2CNT_L : 0x4000,
|
||||
DM2CNT_H & 0x0400);
|
||||
}
|
||||
cpuDmaHack = true;
|
||||
|
||||
if(DM2CNT_H & 0x4000) {
|
||||
IF |= 0x0400;
|
||||
|
@ -2380,6 +2522,7 @@ void CPUCheckDMA(int reason, int dmamask)
|
|||
doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement,
|
||||
DM3CNT_L ? DM3CNT_L : 0x10000,
|
||||
DM3CNT_H & 0x0400);
|
||||
|
||||
if(DM3CNT_H & 0x4000) {
|
||||
IF |= 0x0800;
|
||||
UPDATE_REG(0x202, IF);
|
||||
|
@ -2426,7 +2569,7 @@ void CPUUpdateRegister(u32 address, u16 value)
|
|||
windowOn = (layerEnable & 0x6000) ? true : false;
|
||||
if(change && !((value & 0x80))) {
|
||||
if(!(DISPSTAT & 1)) {
|
||||
lcdTicks = 1008;
|
||||
//lcdTicks = 1008;
|
||||
// VCOUNT = 0;
|
||||
// UPDATE_REG(0x06, VCOUNT);
|
||||
DISPSTAT &= 0xFFFC;
|
||||
|
@ -3479,9 +3622,11 @@ void CPULoop(int ticks)
|
|||
|
||||
if(!holdState && !SWITicks) {
|
||||
if(armState) {
|
||||
armOpcodeCount++;
|
||||
if (!armExecute())
|
||||
return;
|
||||
} else {
|
||||
thumbOpcodeCount++;
|
||||
if (!thumbExecute())
|
||||
return;
|
||||
}
|
||||
|
@ -3504,7 +3649,6 @@ void CPULoop(int ticks)
|
|||
|
||||
clockTicks = cpuNextEvent;
|
||||
cpuTotalTicks = 0;
|
||||
cpuDmaHack = false;
|
||||
|
||||
updateLoop:
|
||||
|
||||
|
@ -3538,7 +3682,7 @@ void CPULoop(int ticks)
|
|||
}
|
||||
}
|
||||
|
||||
if(VCOUNT >= 228) { //Reaching last line
|
||||
if(VCOUNT > 227) { //Reaching last line
|
||||
DISPSTAT &= 0xFFFC;
|
||||
UPDATE_REG(0x04, DISPSTAT);
|
||||
VCOUNT = 0;
|
||||
|
@ -3903,7 +4047,6 @@ void CPULoop(int ticks)
|
|||
cpuDmaTicksToUpdate -= clockTicks;
|
||||
if(cpuDmaTicksToUpdate < 0)
|
||||
cpuDmaTicksToUpdate = 0;
|
||||
cpuDmaHack = true;
|
||||
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 = {
|
||||
|
@ -3994,7 +4387,11 @@ struct EmulatedSystem GBASystem = {
|
|||
// emuWriteState
|
||||
CPUWriteState,
|
||||
// emuReadMemState
|
||||
#ifdef __LIBRETRO__
|
||||
NULL,
|
||||
#else
|
||||
CPUReadMemState,
|
||||
#endif
|
||||
// emuWriteMemState
|
||||
CPUWriteMemState,
|
||||
// emuWritePNG
|
||||
|
|
|
@ -90,9 +90,14 @@ extern void CPUCleanUp();
|
|||
extern void CPUUpdateRender();
|
||||
extern void CPUUpdateRenderBuffers(bool);
|
||||
extern bool CPUReadMemState(char *, int);
|
||||
extern bool CPUReadState(const char *);
|
||||
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 *);
|
||||
#endif
|
||||
extern int CPULoadRom(const char *);
|
||||
extern void doMirroring(bool);
|
||||
extern void CPUUpdateRegister(u32, u16);
|
||||
|
|
|
@ -8,7 +8,11 @@
|
|||
|
||||
//#define SPRITE_DEBUG
|
||||
|
||||
#ifdef TILED_RENDERING
|
||||
extern void gfxDrawTextScreen(u16, u16, u16, u32 *);
|
||||
#else
|
||||
static void gfxDrawTextScreen(u16, u16, u16, u32 *);
|
||||
#endif
|
||||
static void gfxDrawRotScreen(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,
|
||||
u32 *line)
|
||||
{
|
||||
|
@ -238,6 +243,7 @@ static inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void gfxDrawRotScreen(u16 control,
|
||||
u16 x_l, u16 x_h,
|
||||
|
|
|
@ -49,11 +49,9 @@ static inline u32 CPUReadMemory(u32 address)
|
|||
u32 value;
|
||||
u32 oldAddress = address;
|
||||
|
||||
#ifdef C_CORE
|
||||
if(address & 3) {
|
||||
address &= ~0x03;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch(address >> 24) {
|
||||
case 0:
|
||||
|
@ -79,18 +77,18 @@ static inline u32 CPUReadMemory(u32 address)
|
|||
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
|
||||
break;
|
||||
case 4:
|
||||
if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
|
||||
if(ioReadable[(address & 0x3fc) + 2]) {
|
||||
value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
|
||||
if ((address & 0x3fc) == COMM_JOY_RECV_L)
|
||||
UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV);
|
||||
} else {
|
||||
value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
|
||||
}
|
||||
}
|
||||
else
|
||||
goto unreadable;
|
||||
break;
|
||||
if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
|
||||
if(ioReadable[(address & 0x3fc) + 2]) {
|
||||
value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
|
||||
if ((address & 0x3fc) == COMM_JOY_RECV_L)
|
||||
UPDATE_REG(COMM_JOYSTAT, READ16LE(&ioMem[COMM_JOYSTAT]) & ~JOYSTAT_RECV);
|
||||
} else {
|
||||
value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
|
||||
}
|
||||
}
|
||||
else
|
||||
goto unreadable;
|
||||
break;
|
||||
case 5:
|
||||
value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
|
||||
break;
|
||||
|
@ -116,14 +114,12 @@ static inline u32 CPUReadMemory(u32 address)
|
|||
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
|
||||
break;
|
||||
case 13:
|
||||
if(cpuEEPROMEnabled)
|
||||
// no need to swap this
|
||||
return eepromRead(address);
|
||||
goto unreadable;
|
||||
value = eepromRead(address);
|
||||
break;
|
||||
case 14:
|
||||
if(cpuFlashEnabled | cpuSramEnabled)
|
||||
// no need to swap this
|
||||
return flashRead(address);
|
||||
case 15:
|
||||
value = flashRead(address) * 0x01010101;
|
||||
break;
|
||||
// default
|
||||
default:
|
||||
unreadable:
|
||||
|
@ -133,18 +129,17 @@ unreadable:
|
|||
armNextPC - 4 : armNextPC - 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(cpuDmaHack) {
|
||||
value = cpuDmaLast;
|
||||
} else {
|
||||
if(cpuDmaHack) {
|
||||
value = cpuDmaLast;
|
||||
} else {
|
||||
if(armState) {
|
||||
value = CPUReadMemoryQuick(reg[15].I);
|
||||
return CPUReadMemoryQuick(reg[15].I);
|
||||
} else {
|
||||
value = CPUReadHalfWordQuick(reg[15].I) |
|
||||
CPUReadHalfWordQuick(reg[15].I) << 16;
|
||||
return CPUReadHalfWordQuick(reg[15].I) |
|
||||
CPUReadHalfWordQuick(reg[15].I) << 16;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(oldAddress & 3) {
|
||||
|
@ -187,11 +182,9 @@ static inline u32 CPUReadHalfWord(u32 address)
|
|||
u32 value;
|
||||
u32 oldAddress = address;
|
||||
|
||||
//#ifdef C_CORE
|
||||
if(address & 1) {
|
||||
address &= ~0x01;
|
||||
}
|
||||
//#endif
|
||||
|
||||
switch(address >> 24) {
|
||||
case 0:
|
||||
|
@ -233,6 +226,10 @@ static inline u32 CPUReadHalfWord(u32 address)
|
|||
value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
|
||||
}
|
||||
}
|
||||
else if((address < 0x4000400) && ioReadable[address & 0x3fc])
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
else goto unreadable;
|
||||
break;
|
||||
case 5:
|
||||
|
@ -263,34 +260,30 @@ static inline u32 CPUReadHalfWord(u32 address)
|
|||
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
|
||||
break;
|
||||
case 13:
|
||||
if(cpuEEPROMEnabled)
|
||||
// no need to swap this
|
||||
return eepromRead(address);
|
||||
goto unreadable;
|
||||
value = eepromRead(address);
|
||||
break;
|
||||
case 14:
|
||||
if(cpuFlashEnabled | cpuSramEnabled)
|
||||
// no need to swap this
|
||||
return flashRead(address);
|
||||
case 15:
|
||||
value = flashRead(address) * 0x0101;
|
||||
break;
|
||||
// default
|
||||
default:
|
||||
unreadable:
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||
log("Illegal halfword read: %08x at %08x\n", oldAddress, armMode ?
|
||||
armNextPC - 4 : armNextPC - 2);
|
||||
}
|
||||
#endif
|
||||
if(cpuDmaHack) {
|
||||
value = cpuDmaLast & 0xFFFF;
|
||||
} else {
|
||||
if(cpuDmaHack) {
|
||||
value = cpuDmaLast & 0xFFFF;
|
||||
} else {
|
||||
if(armState) {
|
||||
value = CPUReadMemoryQuick(reg[15].I);
|
||||
value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
|
||||
} else {
|
||||
value = CPUReadHalfWordQuick(reg[15].I) |
|
||||
CPUReadHalfWordQuick(reg[15].I) << 16;
|
||||
value = CPUReadHalfWordQuick(reg[15].I);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
|
@ -306,24 +299,19 @@ unreadable:
|
|||
return value;
|
||||
}
|
||||
|
||||
static inline u16 CPUReadHalfWordSigned(u32 address)
|
||||
static inline s16 CPUReadHalfWordSigned(u32 address)
|
||||
{
|
||||
u32 oldAddress = address;
|
||||
if(address & 1) {
|
||||
address &= ~0x01;
|
||||
}
|
||||
u16 value = CPUReadHalfWord(address);
|
||||
if((oldAddress & 1))
|
||||
s32 value = (s32)CPUReadHalfWord(address);
|
||||
if((address & 1))
|
||||
{
|
||||
value = (s8)value;
|
||||
#ifdef GBA_LOGGING
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return value;
|
||||
return (s16)value;
|
||||
}
|
||||
|
||||
static inline u8 CPUReadByte(u32 address)
|
||||
|
@ -368,24 +356,24 @@ static inline u8 CPUReadByte(u32 address)
|
|||
case 12:
|
||||
return rom[address & 0x1FFFFFF];
|
||||
case 13:
|
||||
if(cpuEEPROMEnabled)
|
||||
return eepromRead(address);
|
||||
goto unreadable;
|
||||
return eepromRead(address);
|
||||
case 14:
|
||||
if(cpuSramEnabled | cpuFlashEnabled)
|
||||
return flashRead(address);
|
||||
if(cpuEEPROMSensorEnabled) {
|
||||
switch(address & 0x00008f00) {
|
||||
case 0x8200:
|
||||
return systemGetSensorX() & 255;
|
||||
case 0x8300:
|
||||
return (systemGetSensorX() >> 8)|0x80;
|
||||
case 0x8400:
|
||||
return systemGetSensorY() & 255;
|
||||
case 0x8500:
|
||||
return systemGetSensorY() >> 8;
|
||||
}
|
||||
}
|
||||
case 15:
|
||||
{
|
||||
if (cpuEEPROMSensorEnabled) {
|
||||
switch (address & 0x00008f00) {
|
||||
case 0x8200:
|
||||
return systemGetSensorX() & 255;
|
||||
case 0x8300:
|
||||
return (systemGetSensorX() >> 8) | 0x80;
|
||||
case 0x8400:
|
||||
return systemGetSensorY() & 255;
|
||||
case 0x8500:
|
||||
return systemGetSensorY() >> 8;
|
||||
}
|
||||
}
|
||||
return flashRead(address);
|
||||
}
|
||||
// default
|
||||
default:
|
||||
unreadable:
|
||||
|
@ -395,17 +383,15 @@ unreadable:
|
|||
armNextPC - 4 : armNextPC - 2);
|
||||
}
|
||||
#endif
|
||||
if(cpuDmaHack) {
|
||||
return cpuDmaLast & 0xFF;
|
||||
} else {
|
||||
if(cpuDmaHack) {
|
||||
return cpuDmaLast & 0xFF;
|
||||
} else {
|
||||
if(armState) {
|
||||
return CPUReadMemoryQuick(reg[15].I);
|
||||
return CPUReadByteQuick(reg[15].I + (address & 3));
|
||||
} else {
|
||||
return CPUReadHalfWordQuick(reg[15].I) |
|
||||
CPUReadHalfWordQuick(reg[15].I) << 16;
|
||||
return CPUReadByteQuick(reg[15].I + (address & 1));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,6 +409,8 @@ static inline void CPUWriteMemory(u32 address, u32 value)
|
|||
}
|
||||
#endif
|
||||
|
||||
address &= 0xFFFFFFFC;
|
||||
|
||||
switch(address >> 24) {
|
||||
case 0x02:
|
||||
#ifdef BKPT_SUPPORT
|
||||
|
@ -488,6 +476,7 @@ static inline void CPUWriteMemory(u32 address, u32 value)
|
|||
}
|
||||
goto unwritable;
|
||||
case 0x0E:
|
||||
case 0x0F:
|
||||
if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
|
||||
(*cpuSaveGameFunc)(address, (u8)value);
|
||||
break;
|
||||
|
@ -520,6 +509,8 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
|
|||
}
|
||||
#endif
|
||||
|
||||
address &= 0xFFFFFFFE;
|
||||
|
||||
switch(address >> 24) {
|
||||
case 2:
|
||||
#ifdef BKPT_SUPPORT
|
||||
|
@ -590,6 +581,7 @@ static inline void CPUWriteHalfWord(u32 address, u16 value)
|
|||
}
|
||||
goto unwritable;
|
||||
case 14:
|
||||
case 15:
|
||||
if((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled) {
|
||||
(*cpuSaveGameFunc)(address, (u8)value);
|
||||
break;
|
||||
|
@ -726,6 +718,7 @@ static inline void CPUWriteByte(u32 address, u8 b)
|
|||
}
|
||||
goto unwritable;
|
||||
case 14:
|
||||
case 15:
|
||||
if ((saveType != 5) && ((!eepromInUse) | cpuSramEnabled | cpuFlashEnabled)) {
|
||||
|
||||
//if(!cpuEEPROMEnabled && (cpuSramEnabled | cpuFlashEnabled)) {
|
||||
|
|
|
@ -7,8 +7,15 @@
|
|||
|
||||
#include <time.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
|
||||
enum RTCSTATE { IDLE, COMMAND, DATA, READDATA };
|
||||
enum RTCSTATE
|
||||
{
|
||||
IDLE = 0,
|
||||
COMMAND,
|
||||
DATA,
|
||||
READDATA
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u8 byte0;
|
||||
|
@ -197,6 +204,17 @@ void rtcReset()
|
|||
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)
|
||||
{
|
||||
utilGzWrite(gzFile, &rtcClockData, sizeof(rtcClockData));
|
||||
|
@ -206,3 +224,4 @@ void rtcReadGame(gzFile gzFile)
|
|||
{
|
||||
utilGzRead(gzFile, &rtcClockData, sizeof(rtcClockData));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -7,7 +7,12 @@ void rtcEnable(bool);
|
|||
bool rtcIsEnabled();
|
||||
void rtcReset();
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
void rtcReadGame(const u8 *&data);
|
||||
void rtcSaveGame(u8 *&data);
|
||||
#else
|
||||
void rtcReadGame(gzFile gzFile);
|
||||
void rtcSaveGame(gzFile gzFile);
|
||||
#endif
|
||||
|
||||
#endif // RTC_H
|
||||
|
|
|
@ -183,15 +183,19 @@ void Gba_Pcm_Fifo::timer_overflowed( int which_timer )
|
|||
{
|
||||
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
|
||||
int saved_count = count;
|
||||
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
|
||||
int reg = which ? FIFOB_L : FIFOA_L;
|
||||
for ( int n = 4; n--; )
|
||||
for ( int n = 8; n--; )
|
||||
{
|
||||
soundEvent(reg , (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)
|
||||
{
|
||||
#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
|
||||
// that don't use the length parameter of the write method.
|
||||
// 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);
|
||||
systemOnWriteDataToSoundBuffer(soundFinalWave, soundBufferLen);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void apply_filtering()
|
||||
|
@ -446,6 +456,13 @@ static void remake_stereo_buffer()
|
|||
pcm [0].pcm.init();
|
||||
pcm [1].pcm.init();
|
||||
|
||||
// APU
|
||||
if ( !gb_apu )
|
||||
{
|
||||
gb_apu = new Gb_Apu; // TODO: handle out of memory
|
||||
reset_apu();
|
||||
}
|
||||
|
||||
// Stereo_Buffer
|
||||
delete stereo_buffer;
|
||||
stereo_buffer = 0;
|
||||
|
@ -459,13 +476,7 @@ static void remake_stereo_buffer()
|
|||
pcm [1].which = 1;
|
||||
apply_filtering();
|
||||
|
||||
// APU
|
||||
if ( !gb_apu )
|
||||
{
|
||||
gb_apu = new Gb_Apu; // TODO: handle out of memory
|
||||
reset_apu();
|
||||
}
|
||||
|
||||
// Volume Level
|
||||
apply_muting();
|
||||
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 )
|
||||
#endif
|
||||
{
|
||||
gb_apu->save_state( &state.apu );
|
||||
|
||||
// Be sure areas for expansion get written as zero
|
||||
memset( dummy_state, 0, sizeof dummy_state );
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
utilWriteDataMem( out, gba_state );
|
||||
#else
|
||||
utilWriteData( out, gba_state );
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef __LIBRETRO__
|
||||
static void soundReadGameOld( gzFile in, int version )
|
||||
{
|
||||
// Read main data
|
||||
|
@ -787,19 +807,28 @@ static void soundReadGameOld( gzFile in, int version )
|
|||
|
||||
(void) utilReadInt( in ); // ignore quality
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
void soundReadGame(const u8*& in, int version )
|
||||
#else
|
||||
void soundReadGame( gzFile in, int version )
|
||||
#endif
|
||||
{
|
||||
// Prepare APU and default state
|
||||
reset_apu();
|
||||
gb_apu->save_state( &state.apu );
|
||||
|
||||
if ( version > SAVE_GAME_VERSION_9 )
|
||||
#ifdef __LIBRETRO__
|
||||
utilReadDataMem( in, gba_state );
|
||||
#else
|
||||
utilReadData( in, gba_state );
|
||||
else
|
||||
soundReadGameOld( in, version );
|
||||
#endif
|
||||
|
||||
gb_apu->load_state( state.apu );
|
||||
write_SGCNT0_H( READ16LE( &ioMem [SGCNT0_H] ) & 0x770F );
|
||||
|
|
|
@ -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
|
||||
|
||||
// Saves/loads emulator state
|
||||
#ifdef __LIBRETRO__
|
||||
void soundSaveGame( u8 *& );
|
||||
void soundReadGame(const u8*& in, int version );
|
||||
#else
|
||||
void soundSaveGame( gzFile );
|
||||
void soundReadGame( gzFile, int version );
|
||||
#endif
|
||||
|
||||
class Multi_Buffer;
|
||||
|
||||
|
|
|
@ -1058,7 +1058,7 @@ void elfParseCFA(u8 *top)
|
|||
|
||||
if(id == 0xffffffff) {
|
||||
// skip version
|
||||
*data++;
|
||||
(*data)++;
|
||||
|
||||
ELFcie *cie = (ELFcie *)calloc(1, sizeof(ELFcie));
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#ifndef __LIBRETRO__
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -75,7 +76,11 @@ bool remoteTcpInit()
|
|||
|
||||
remoteListenSocket = s;
|
||||
|
||||
#ifdef _WIN32
|
||||
if(s == INVALID_SOCKET) {
|
||||
#else
|
||||
if(s < 0) {
|
||||
#endif
|
||||
fprintf(stderr,"Error opening socket\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -719,3 +724,4 @@ void remoteCleanUp()
|
|||
if(remoteCleanUpFnc)
|
||||
remoteCleanUpFnc();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,7 @@ const DirectoriesConfigDialog::SDirEntry DirectoriesConfigDialog::m_astDirs[] =
|
|||
{ "gba_roms", N_("GBA roms :"), "GBARomsDirEntry" },
|
||||
{ "gb_roms", N_("GB roms :"), "GBRomsDirEntry" },
|
||||
{ "batteries", N_("Batteries :"), "BatteriesDirEntry" },
|
||||
{ "cheats", N_("Cheats :"), "CheatsDirEntry" },
|
||||
{ "saves", N_("Saves :"), "SavesDirEntry" },
|
||||
{ "captures", N_("Captures :"), "CapturesDirEntry" }
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ private:
|
|||
|
||||
Config::Section * m_poConfig;
|
||||
static const SDirEntry m_astDirs[];
|
||||
Gtk::FileChooserButton * m_poButtons[5];
|
||||
Gtk::FileChooserButton * m_poButtons[6];
|
||||
};
|
||||
|
||||
} // namespace VBA
|
||||
|
|
|
@ -27,6 +27,16 @@
|
|||
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) :
|
||||
Gtk::Dialog(_pstDialog),
|
||||
m_poConfig(0)
|
||||
|
@ -49,8 +59,6 @@ void GameBoyConfigDialog::vSetConfig(Config::Section * _poConfig, VBA::Window *
|
|||
m_poConfig = _poConfig;
|
||||
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");
|
||||
m_poSystemComboBox->set_active(aEmulatorType[eDefaultEmulatorType]);
|
||||
|
||||
|
@ -70,17 +78,7 @@ void GameBoyConfigDialog::vSetConfig(Config::Section * _poConfig, VBA::Window *
|
|||
|
||||
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_poWindow->vApplyConfigGBSystem();
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Encoding=UTF-8
|
||||
Type=Application
|
||||
Name=VBA-M
|
||||
GenericName=GameBoy Advance Emulator
|
||||
Comment=Nindendo GameBoy Advance Emulator
|
||||
Exec=gvbam
|
||||
Icon=vbam
|
||||
Categories=Application;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
|
||||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=VBA-M
|
||||
GenericName=GameBoy Advance Emulator
|
||||
Comment=Nindendo GameBoy Advance Emulator
|
||||
Exec=gvbam %f
|
||||
Icon=vbam
|
||||
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;
|
||||
|
|
|
@ -49,10 +49,10 @@ JoypadConfigDialog::JoypadConfigDialog(Config::Section * _poConfig) :
|
|||
m_oTitleLabel(_("Joypad :"), Gtk::ALIGN_RIGHT),
|
||||
m_oDefaultJoypad(_("Default joypad")),
|
||||
m_oTable(G_N_ELEMENTS(m_astKeys), 2, false),
|
||||
m_iCurrentEntry(-1),
|
||||
m_bUpdating(false),
|
||||
m_ePad(PAD_MAIN),
|
||||
m_poConfig(_poConfig),
|
||||
m_iCurrentEntry(-1)
|
||||
m_poConfig(_poConfig)
|
||||
{
|
||||
// Joypad selection
|
||||
m_oTitleCombo.append_text("1");
|
||||
|
@ -115,7 +115,7 @@ void JoypadConfigDialog::vUpdateEntries()
|
|||
|
||||
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);
|
||||
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>"));
|
||||
}
|
||||
|
|
|
@ -504,6 +504,7 @@ void Window::vInitConfig()
|
|||
m_poDirConfig->vSetKey("gb_roms", Glib::get_home_dir());
|
||||
m_poDirConfig->vSetKey("gba_roms", Glib::get_home_dir());
|
||||
m_poDirConfig->vSetKey("batteries", m_sUserDataDir);
|
||||
m_poDirConfig->vSetKey("cheats", m_sUserDataDir);
|
||||
m_poDirConfig->vSetKey("saves", m_sUserDataDir);
|
||||
m_poDirConfig->vSetKey("captures", m_sUserDataDir);
|
||||
|
||||
|
@ -588,6 +589,11 @@ void Window::vCheckConfig()
|
|||
{
|
||||
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");
|
||||
if (sValue != "" && ! Glib::file_test(sValue, Glib::FILE_TEST_IS_DIR))
|
||||
{
|
||||
|
@ -1078,6 +1084,7 @@ bool Window::bLoadROM(const std::string & _rsFile)
|
|||
}
|
||||
|
||||
vLoadBattery();
|
||||
vLoadCheats();
|
||||
vUpdateScreen();
|
||||
|
||||
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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
if (m_oEmuSig.connected())
|
||||
|
|
|
@ -272,7 +272,9 @@ private:
|
|||
void vSetDefaultTitle();
|
||||
void vCreateFileOpenDialog();
|
||||
void vLoadBattery();
|
||||
void vLoadCheats();
|
||||
void vSaveBattery();
|
||||
void vSaveCheats();
|
||||
void vStartEmu();
|
||||
void vStopEmu();
|
||||
void vUpdateGameSlots();
|
||||
|
|
|
@ -335,6 +335,7 @@ void Window::vOnFileClose()
|
|||
vSetDefaultTitle();
|
||||
vDrawDefaultScreen();
|
||||
vSaveBattery();
|
||||
vSaveCheats();
|
||||
m_stEmulator.emuCleanUp();
|
||||
m_eCartridge = CartridgeNone;
|
||||
emulating = 0;
|
||||
|
|
|
@ -125,6 +125,7 @@ int desktopHeight = 0;
|
|||
|
||||
Filter filter = kStretch2x;
|
||||
u8 *delta = NULL;
|
||||
static const int delta_size = 322*242*4;
|
||||
|
||||
int filter_enlarge = 2;
|
||||
|
||||
|
@ -1395,7 +1396,7 @@ void sdlPollEvents()
|
|||
soundPause();
|
||||
}
|
||||
|
||||
memset(delta,255,sizeof(delta));
|
||||
memset(delta,255,delta_size);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -2311,8 +2312,8 @@ int main(int argc, char **argv)
|
|||
utilUpdateSystemColorMaps();
|
||||
|
||||
if(delta == NULL) {
|
||||
delta = (u8*)malloc(322*242*4);
|
||||
memset(delta, 255, 322*242*4);
|
||||
delta = (u8*)malloc(delta_size);
|
||||
memset(delta, 255, delta_size);
|
||||
}
|
||||
|
||||
ifbFunction = initIFBFilter(ifbType, systemColorDepth);
|
||||
|
|
|
@ -345,9 +345,9 @@ bool OpenGLDisplay::initialize()
|
|||
cpu_mmx = 0;
|
||||
#endif
|
||||
|
||||
systemRedShift = 3;
|
||||
systemRedShift = 19;
|
||||
systemGreenShift = 11;
|
||||
systemBlueShift = 19;
|
||||
systemBlueShift = 3;
|
||||
systemColorDepth = 32;
|
||||
theApp.fsColorDepth = 32;
|
||||
|
||||
|
@ -401,7 +401,7 @@ void OpenGLDisplay::render()
|
|||
} else {
|
||||
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 );
|
||||
|
|
|
@ -287,9 +287,9 @@ bool XAudio2_Output::init(long sampleRate)
|
|||
|
||||
// Initialize XAudio2
|
||||
UINT32 flags = 0;
|
||||
#ifdef _DEBUG
|
||||
flags = XAUDIO2_DEBUG_ENGINE;
|
||||
#endif
|
||||
//#ifdef _DEBUG
|
||||
// flags = XAUDIO2_DEBUG_ENGINE;
|
||||
//#endif
|
||||
|
||||
hr = XAudio2Create( &xaud, flags );
|
||||
if( hr != S_OK ) {
|
||||
|
|
|
@ -138,7 +138,7 @@ void rpiFilter(u8 *srcPtr, u32 srcPitch, u8 *deltaPtr, u8 *dstPtr, u32 dstPitch,
|
|||
*(pOCur++) = ((*pICur & 0xF800) << rshiftDiff) |
|
||||
((*pICur & 0x07E0) << gshiftDiff) |
|
||||
((*pICur & 0x001F) << bshiftDiff);
|
||||
*pICur++;
|
||||
*(pICur++);
|
||||
}
|
||||
pI = pICur = (u16 *)((char *)pI + 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) |
|
||||
((*pICur & 0x07E0) << gshiftDiff) |
|
||||
((*pICur & 0x001F) << bshiftDiff);
|
||||
*pICur++;
|
||||
*(pICur++);
|
||||
}
|
||||
pI = pICur = (u16 *)((char *)pI + dstPitch);
|
||||
pO = pOCur = (u32 *)((char *)pO + dstPitch);
|
||||
|
|
Loading…
Reference in New Issue