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:
|
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
|
||||||
|
|
|
@ -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
|
75
src/System.h
75
src/System.h
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
26
src/Util.h
26
src/Util.h
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 */)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
423
src/gba/GBA.cpp
423
src/gba/GBA.cpp
|
@ -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, ®[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(®[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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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" }
|
||||||
};
|
};
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue