Merge remote-tracking branch 'vbam-libretro/master'

This commit is contained in:
Rafael Kitover 2019-07-25 02:16:32 +00:00
commit 38561b5713
No known key found for this signature in database
GPG Key ID: 08AB596679D86240
6 changed files with 125 additions and 114 deletions

View File

@ -65,6 +65,17 @@ Solus and RHEL/CentOS) and Mac OS X (homebrew, macports or fink.)
The Ninja cmake generator is also now supported, including on msys2 and Visual Studio. The Ninja cmake generator is also now supported, including on msys2 and Visual Studio.
## Building a Libretro core
```
Clone this repo and then,
$ cd src
$ cd libretro
$ make
Copy vbam_libretro.so to your RetroArch cores directory.
```
### Visual Studio Support ### Visual Studio Support
For visual studio, dependency management is handled automatically with vcpkg, For visual studio, dependency management is handled automatically with vcpkg,

View File

@ -1232,7 +1232,7 @@ void gbWriteMemory(uint16_t address, uint8_t value)
case 0x3e: case 0x3e:
case 0x3f: case 0x3f:
// Sound registers handled by blargg // Sound registers handled by blargg
gbSoundEvent(address, value); gbSoundEvent(soundTicks, address, value);
//gbMemory[address] = value; //gbMemory[address] = value;
return; return;
@ -1967,7 +1967,7 @@ uint8_t gbReadMemory(uint16_t address)
case 0x3e: case 0x3e:
case 0x3f: case 0x3f:
// Sound registers read // Sound registers read
return gbSoundRead(address); return gbSoundRead(soundTicks, address);
case 0x40: case 0x40:
return register_LCDC; return register_LCDC;
case 0x41: case 0x41:
@ -4535,12 +4535,37 @@ void gbDrawLine()
} }
} }
static void gbUpdateJoypads(bool readSensors)
{
if (systemReadJoypads()) {
// read joystick
if (gbSgbMode && gbSgbMultiplayer) {
if (gbSgbFourPlayers) {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
gbJoymask[2] = systemReadJoypad(2);
gbJoymask[3] = systemReadJoypad(3);
} else {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
}
} else {
gbJoymask[0] = systemReadJoypad(-1);
}
}
if (readSensors && gbRomType == 0x22) {
systemUpdateMotionSensor();
}
}
void gbEmulate(int ticksToStop) void gbEmulate(int ticksToStop)
{ {
gbRegister tempRegister; gbRegister tempRegister;
uint8_t tempValue; uint8_t tempValue;
int8_t offset; int8_t offset;
clockTicks = 0; clockTicks = 0;
gbDmaTicks = 0; gbDmaTicks = 0;
@ -4549,6 +4574,9 @@ void gbEmulate(int ticksToStop)
int opcode1 = 0; int opcode1 = 0;
int opcode2 = 0; int opcode2 = 0;
bool execute = false; bool execute = false;
bool frameDone = false;
gbUpdateJoypads(true);
while (1) { while (1) {
uint16_t oldPCW = PC.W; uint16_t oldPCW = PC.W;
@ -4661,6 +4689,8 @@ void gbEmulate(int ticksToStop)
} }
ticksToStop -= clockTicks; ticksToStop -= clockTicks;
soundTicks += clockTicks;
if (!gbSpeed) soundTicks += clockTicks;
// DIV register emulation // DIV register emulation
gbDivTicks -= clockTicks; gbDivTicks -= clockTicks;
@ -4930,6 +4960,7 @@ void gbEmulate(int ticksToStop)
gbFrameCount++; gbFrameCount++;
systemFrame(); systemFrame();
gbSoundTick(soundTicks);
if ((gbFrameCount % 10) == 0) if ((gbFrameCount % 10) == 0)
system10Frames(60); system10Frames(60);
@ -4944,28 +4975,8 @@ void gbEmulate(int ticksToStop)
gbFrameCount = 0; gbFrameCount = 0;
} }
if (systemReadJoypads()) {
// read joystick
if (gbSgbMode && gbSgbMultiplayer) {
if (gbSgbFourPlayers) {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
gbJoymask[2] = systemReadJoypad(2);
gbJoymask[3] = systemReadJoypad(3);
} else {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
}
} else {
gbJoymask[0] = systemReadJoypad(-1);
}
}
int newmask = gbJoymask[0] & 255; int newmask = gbJoymask[0] & 255;
if (gbRomType == 0x22) {
systemUpdateMotionSensor();
}
if (newmask) { if (newmask) {
gbMemory[0xff0f] = register_IF |= 16; gbMemory[0xff0f] = register_IF |= 16;
} }
@ -5003,6 +5014,8 @@ void gbEmulate(int ticksToStop)
} else } else
gbFrameSkipCount++; gbFrameSkipCount++;
frameDone = true;
} else { } else {
// go the the OAM being accessed mode // go the the OAM being accessed mode
gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS; gbLcdTicksDelayed += GBLCD_MODE_2_CLOCK_TICKS;
@ -5151,25 +5164,11 @@ void gbEmulate(int ticksToStop)
ticksToStop = 0; ticksToStop = 0;
} }
} }
if (systemReadJoypads()) {
// read joystick
if (gbSgbMode && gbSgbMultiplayer) {
if (gbSgbFourPlayers) {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
gbJoymask[2] = systemReadJoypad(2);
gbJoymask[3] = systemReadJoypad(3);
} else {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
}
} else {
gbJoymask[0] = systemReadJoypad(-1);
}
}
gbFrameCount++; gbFrameCount++;
systemFrame(); systemFrame();
gbSoundTick(soundTicks);
if ((gbFrameCount % 10) == 0) if ((gbFrameCount % 10) == 0)
system10Frames(60); system10Frames(60);
@ -5183,6 +5182,7 @@ void gbEmulate(int ticksToStop)
gbLastTime = currentTime; gbLastTime = currentTime;
gbFrameCount = 0; gbFrameCount = 0;
} }
frameDone = true;
} }
} }
} }
@ -5279,15 +5279,14 @@ void gbEmulate(int ticksToStop)
#endif #endif
} }
#endif #endif
// TODO: evaluate and fix this
soundTicks -= clockTicks; // On VBA-M (gb core running twice as fast?), each vblank is uses 35112 cycles.
if (!gbSpeed) // on some cases no vblank is generated causing sound ticks to keep accumulating causing core to crash.
soundTicks -= clockTicks; // This forces core to flush sound buffers when expected sound ticks has passed and no frame is done yet.which then ends cpuloop
if ((soundTicks > SOUND_CLOCK_TICKS) && !frameDone) {
while (soundTicks < 0) { int last_st = soundTicks;
soundTicks += SOUND_CLOCK_TICKS; gbSoundTick(soundTicks);
soundTicks = (last_st - SOUND_CLOCK_TICKS);
gbSoundTick();
} }
// timer emulation // timer emulation
@ -5413,25 +5412,7 @@ void gbEmulate(int ticksToStop)
gbBlackScreen = false; gbBlackScreen = false;
if ((ticksToStop <= 0)) { if (ticksToStop <= 0 || frameDone) { // Stop loop
if (!(register_LCDC & 0x80)) {
if (systemReadJoypads()) {
// read joystick
if (gbSgbMode && gbSgbMultiplayer) {
if (gbSgbFourPlayers) {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
gbJoymask[2] = systemReadJoypad(2);
gbJoymask[3] = systemReadJoypad(3);
} else {
gbJoymask[0] = systemReadJoypad(0);
gbJoymask[1] = systemReadJoypad(1);
}
} else {
gbJoymask[0] = systemReadJoypad(-1);
}
}
}
return; return;
} }
} }
@ -5821,7 +5802,7 @@ struct EmulatedSystem GBSystem = {
false, false,
// emuCount // emuCount
#ifdef FINAL_VERSION #ifdef FINAL_VERSION
70000 / 4, 72000,
#else #else
1000, 1000,
#endif #endif

View File

@ -24,25 +24,20 @@ static bool declicking = false;
int const chan_count = 4; int const chan_count = 4;
int const ticks_to_time = 2 * GB_APU_OVERCLOCK; int const ticks_to_time = 2 * GB_APU_OVERCLOCK;
static inline blip_time_t blip_time() uint8_t gbSoundRead(int st, uint16_t address)
{
return (SOUND_CLOCK_TICKS - soundTicks) * ticks_to_time;
}
uint8_t gbSoundRead(uint16_t address)
{ {
if (gb_apu && address >= NR10 && address <= 0xFF3F) if (gb_apu && address >= NR10 && address <= 0xFF3F)
return gb_apu->read_register(blip_time(), address); return gb_apu->read_register((blip_time_t)(st * ticks_to_time), address);
return gbMemory[address]; return gbMemory[address];
} }
void gbSoundEvent(uint16_t address, int data) void gbSoundEvent(int st, uint16_t address, int data)
{ {
gbMemory[address] = data; gbMemory[address] = data;
if (gb_apu && address >= NR10 && address <= 0xFF3F) if (gb_apu && address >= NR10 && address <= 0xFF3F)
gb_apu->write_register(blip_time(), address, data); gb_apu->write_register((blip_time_t)(st * ticks_to_time), address, data);
} }
static void end_frame(blip_time_t time) static void end_frame(blip_time_t time)
@ -83,11 +78,11 @@ static void apply_volume()
gb_apu->volume(soundVolume_); gb_apu->volume(soundVolume_);
} }
void gbSoundTick() void gbSoundTick(int st)
{ {
if (gb_apu && stereo_buffer) { if (gb_apu && stereo_buffer) {
// Run sound hardware to present // Run sound hardware to present
end_frame(SOUND_CLOCK_TICKS * ticks_to_time); end_frame((blip_time_t)(st * ticks_to_time));
flush_samples(stereo_buffer); flush_samples(stereo_buffer);
@ -100,6 +95,8 @@ void gbSoundTick()
if (soundVolume_ != soundGetVolume()) if (soundVolume_ != soundGetVolume())
apply_volume(); apply_volume();
} }
soundTicks = 0;
} }
static void reset_apu() static void reset_apu()
@ -115,7 +112,7 @@ static void reset_apu()
if (stereo_buffer) if (stereo_buffer)
stereo_buffer->clear(); stereo_buffer->clear();
soundTicks = SOUND_CLOCK_TICKS; soundTicks = 0;
} }
static void remake_stereo_buffer() static void remake_stereo_buffer()
@ -171,42 +168,42 @@ bool gbSoundGetDeclicking()
void gbSoundReset() void gbSoundReset()
{ {
SOUND_CLOCK_TICKS = 20000; // 1/100 second SOUND_CLOCK_TICKS = 35112;
remake_stereo_buffer(); remake_stereo_buffer();
reset_apu(); reset_apu();
soundPaused = 1; soundPaused = 1;
gbSoundEvent(0xff10, 0x80); gbSoundEvent(0, 0xff10, 0x80);
gbSoundEvent(0xff11, 0xbf); gbSoundEvent(0, 0xff11, 0xbf);
gbSoundEvent(0xff12, 0xf3); gbSoundEvent(0, 0xff12, 0xf3);
gbSoundEvent(0xff14, 0xbf); gbSoundEvent(0, 0xff14, 0xbf);
gbSoundEvent(0xff16, 0x3f); gbSoundEvent(0, 0xff16, 0x3f);
gbSoundEvent(0xff17, 0x00); gbSoundEvent(0, 0xff17, 0x00);
gbSoundEvent(0xff19, 0xbf); gbSoundEvent(0, 0xff19, 0xbf);
gbSoundEvent(0xff1a, 0x7f); gbSoundEvent(0, 0xff1a, 0x7f);
gbSoundEvent(0xff1b, 0xff); gbSoundEvent(0, 0xff1b, 0xff);
gbSoundEvent(0xff1c, 0xbf); gbSoundEvent(0, 0xff1c, 0xbf);
gbSoundEvent(0xff1e, 0xbf); gbSoundEvent(0, 0xff1e, 0xbf);
gbSoundEvent(0xff20, 0xff); gbSoundEvent(0, 0xff20, 0xff);
gbSoundEvent(0xff21, 0x00); gbSoundEvent(0, 0xff21, 0x00);
gbSoundEvent(0xff22, 0x00); gbSoundEvent(0, 0xff22, 0x00);
gbSoundEvent(0xff23, 0xbf); gbSoundEvent(0, 0xff23, 0xbf);
gbSoundEvent(0xff24, 0x77); gbSoundEvent(0, 0xff24, 0x77);
gbSoundEvent(0xff25, 0xf3); gbSoundEvent(0, 0xff25, 0xf3);
if (gbHardware & 0x4) if (gbHardware & 0x4)
gbSoundEvent(0xff26, 0xf0); gbSoundEvent(0, 0xff26, 0xf0);
else else
gbSoundEvent(0xff26, 0xf1); gbSoundEvent(0, 0xff26, 0xf1);
/* workaround for game Beetlejuice */ /* workaround for game Beetlejuice */
if (gbHardware & 0x1) { if (gbHardware & 0x1) {
gbSoundEvent(0xff24, 0x77); gbSoundEvent(0, 0xff24, 0x77);
gbSoundEvent(0xff25, 0xf3); gbSoundEvent(0, 0xff25, 0xf3);
} }
int addr = 0xff30; int addr = 0xff30;
@ -399,7 +396,6 @@ static void gbSoundReadGameOld(int version, gzFile gzFile)
#endif #endif
// New state format // New state format
static variable_desc gb_state[] = { static variable_desc gb_state[] = {
LOAD(int, state.version), // room_for_expansion will be used by later versions LOAD(int, state.version), // room_for_expansion will be used by later versions
@ -427,7 +423,8 @@ static variable_desc gb_state[] = {
SKIP(int[13], room_for_expansion), SKIP(int[13], room_for_expansion),
// Emulator // Emulator
SKIP(int[16], room_for_expansion), LOAD(int, soundTicks),
SKIP(int[15], room_for_expansion),
{ NULL, 0 } { NULL, 0 }
}; };
@ -445,7 +442,7 @@ void gbSoundSaveGame(gzFile out)
state.version = 1; state.version = 1;
#ifdef __LIBRETRO__ #ifdef __LIBRETRO__
utilWriteDataMem(out, gb_state); utilWriteDataMem(out, gb_state);
#else #else
utilWriteData(out, gb_state); utilWriteData(out, gb_state);
#endif #endif
@ -461,10 +458,10 @@ void gbSoundReadGame(int version, gzFile in)
reset_apu(); reset_apu();
gb_apu->save_state(&state.apu); gb_apu->save_state(&state.apu);
if (version > 11)
#ifdef __LIBRETRO__ #ifdef __LIBRETRO__
utilReadDataMem(in, gb_state); utilReadDataMem(in, gb_state);
#else #else
if (version > 11)
utilReadData(in, gb_state); utilReadData(in, gb_state);
else else
gbSoundReadGameOld(version, in); gbSoundReadGameOld(version, in);

View File

@ -56,14 +56,14 @@ extern gb_effects_config_t gb_effects_config; // current configuration
void gbSoundReset(); void gbSoundReset();
// Emulates write to sound hardware // Emulates write to sound hardware
void gbSoundEvent(uint16_t address, int data); void gbSoundEvent(int st, uint16_t address, int data);
#define SOUND_EVENT gbSoundEvent #define SOUND_EVENT gbSoundEvent
// Emulates read from sound hardware // Emulates read from sound hardware
uint8_t gbSoundRead(uint16_t address); uint8_t gbSoundRead(int st, uint16_t address);
// Notifies emulator that SOUND_CLOCK_TICKS clocks have passed // Notifies emulator that SOUND_CLOCK_TICKS clocks have passed
void gbSoundTick(); void gbSoundTick(int st);
extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to gbSoundTick() extern int SOUND_CLOCK_TICKS; // Number of 16.8 MHz clocks between calls to gbSoundTick()
extern int soundTicks; // Number of 16.8 MHz clocks until gbSoundTick() will be called extern int soundTicks; // Number of 16.8 MHz clocks until gbSoundTick() will be called

View File

@ -718,8 +718,8 @@ static variable_desc gba_state[] = {
// Emulator // Emulator
LOAD(int, soundEnableFlag), LOAD(int, soundEnableFlag),
LOAD(int, soundTicks),
SKIP(int[15], room_for_expansion), SKIP(int[14], room_for_expansion),
{ NULL, 0 } { NULL, 0 }
}; };
@ -806,10 +806,10 @@ void soundReadGame(gzFile in, int version)
reset_apu(); reset_apu();
gb_apu->save_state(&state.apu); gb_apu->save_state(&state.apu);
if (version > SAVE_GAME_VERSION_9)
#ifdef __LIBRETRO__ #ifdef __LIBRETRO__
utilReadDataMem(in, gba_state); utilReadDataMem(in, gba_state);
#else #else
if (version > SAVE_GAME_VERSION_9)
utilReadData(in, gba_state); utilReadData(in, gba_state);
else else
soundReadGameOld(in, version); soundReadGameOld(in, version);

View File

@ -90,6 +90,8 @@ bool EmuReseted;
int winGbPrinterEnabled; int winGbPrinterEnabled;
bool gba_joybus_active = false; bool gba_joybus_active = false;
#define UPDATE_REG(address, value) WRITE16LE(((uint16_t*)&ioMem[address]), value)
LinkMode GetLinkMode() LinkMode GetLinkMode()
{ {
return LINK_DISCONNECTED; return LINK_DISCONNECTED;
@ -97,7 +99,10 @@ LinkMode GetLinkMode()
void StartGPLink(uint16_t value) void StartGPLink(uint16_t value)
{ {
WRITE16LE(((uint16_t*)&ioMem[COMM_RCNT]), value); if (!ioMem)
return;
UPDATE_REG(COMM_RCNT, value);
} }
void LinkUpdate(int ticks) void LinkUpdate(int ticks)
@ -106,6 +111,23 @@ void LinkUpdate(int ticks)
void StartLink(uint16_t siocnt) void StartLink(uint16_t siocnt)
{ {
/* log("'s' siocnt = %04x\n", siocnt); */
if (!ioMem)
return;
if(siocnt & 0x80)
{
siocnt &= 0xff7f;
if(siocnt & 1 && (siocnt & 0x4000))
{
UPDATE_REG(COMM_SIOCNT, 0xFF);
IF |= 0x80;
UPDATE_REG(0x202, IF);
siocnt &= 0x7f7f;
}
}
UPDATE_REG(COMM_SIOCNT, siocnt);
} }
void CheckLinkConnection() void CheckLinkConnection()