mirror of
https://github.com/libretro/FBNeo.git
synced 2026-11-07 02:55:59 -10:00
Add new console target: GBA
This commit is contained in:
1 parent
a85b0974d7
commit
cde78e9a72
28 files changed
+9887
-18
No files matched your search
+3
-1
@@ -1,5 +1,5 @@
|
||||
alldir = burn burn/devices burn/snd burn/drv burn/drv/atari burn/drv/capcom burn/drv/cave burn/drv/channelf burn/drv/coleco burn/drv/cps3 burn/drv/dataeast \
|
||||
burn/drv/galaxian burn/drv/irem burn/drv/konami burn/drv/megadrive burn/drv/midway burn/drv/pce burn/drv/pst90s burn/drv/pre90s burn/drv/neogeo burn/drv/nes burn/drv/snes \
|
||||
burn/drv/galaxian burn/drv/gba burn/drv/irem burn/drv/konami burn/drv/megadrive burn/drv/midway burn/drv/pce burn/drv/pst90s burn/drv/pre90s burn/drv/neogeo burn/drv/nes burn/drv/snes \
|
||||
burn/drv/pgm burn/drv/pgm2 burn/drv/psikyo burn/drv/sega burn/drv/sg1000 burn/drv/sms burn/drv/msx burn/drv/spectrum burn/drv/taito \
|
||||
burn/drv/toaplan cpu cpu/a68k cpu/arm cpu/arm7 cpu/arm9 cpu/e132xs cpu/f8 cpu/h6280 cpu/hd6309 cpu/hmcs40 cpu/i386 cpu/i8039 cpu/i8x41 cpu/i8051 cpu/i8085 cpu/adsp2100 cpu/konami cpu/m377 cpu/mips3 cpu/m68k \
|
||||
cpu/mb88xx cpu/m6502 cpu/m6800 cpu/m6805 cpu/m6809 cpu/nec cpu/pic16c5x cpu/s2650 cpu/tlcs90 cpu/tlcs900 cpu/sh2 cpu/sh4 cpu/t11 cpu/tms32010 cpu/tms34 cpu/upd7725 cpu/upd7810 \
|
||||
@@ -26,6 +26,8 @@ drvsrc = d_akkaarrh.o d_arcadecl.o d_atarig1.o d_atarisy1.o d_badlands.o d_batm
|
||||
\
|
||||
d_119.o d_galaxian.o \
|
||||
\
|
||||
d_gba.o gba.o \
|
||||
\
|
||||
d_m52.o d_m57.o d_m58.o d_m62.o d_m63.o d_m72.o d_m90.o d_m92.o d_m107.o d_travrusa.o d_vigilant.o \
|
||||
\
|
||||
d_88games.o d_ajax.o d_aliens.o d_asterix.o d_battlnts.o d_bishi.o d_bladestl.o d_blockhl.o d_bottom9.o d_chqflag.o d_circusc.o d_combatsc.o \
|
||||
|
||||
@@ -672,6 +672,9 @@ $(cave_tile_func.h): $(srcdir)dep/scripts/cave_tile_func.pl
|
||||
|
||||
cave_sprite.d cave_sprite.o: $(cave_sprite_func.h)
|
||||
|
||||
gba.d gba.o: $(srcdir)burn/drv/gba/gba.h $(srcdir)burn/drv/gba/gba_impl.h $(srcdir)burn/drv/gba/host.h $(srcdir)burn/drv/gba/arm7.h $(srcdir)burn/drv/gba/bios.h $(srcdir)burn/drv/gba/rtc.h
|
||||
d_gba.d d_gba.o: $(srcdir)burn/drv/gba/gba.h
|
||||
|
||||
$(cave_sprite_func.h): $(srcdir)dep/scripts/cave_sprite_func.pl
|
||||
@$(srcdir)dep/scripts/cave_sprite_func.pl -o $(cave_sprite_func.h)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ option('driver_list',
|
||||
'cps3',
|
||||
'dataeast',
|
||||
'galaxian',
|
||||
'gba',
|
||||
'irem',
|
||||
'konami',
|
||||
'megadrive',
|
||||
|
||||
@@ -555,6 +555,8 @@ del %(Filename).exe</Command>
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_run.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_sound.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m107.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m52.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m57.cpp" />
|
||||
|
||||
@@ -418,6 +418,12 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp">
|
||||
<Filter>burn\drv\galaxian</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m62.cpp">
|
||||
<Filter>burn\drv\irem</Filter>
|
||||
</ClCompile>
|
||||
@@ -3876,6 +3882,9 @@
|
||||
<Filter Include="burn\drv\galaxian">
|
||||
<UniqueIdentifier>{c4b93ffc-1f2a-4461-a73b-d7153fd1a1e6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\gba">
|
||||
<UniqueIdentifier>{6b17d54b-49ca-4e1f-9f6f-418472209f26}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\irem">
|
||||
<UniqueIdentifier>{0937431a-c5c3-4079-86ff-f553d99ef136}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
||||
@@ -555,6 +555,8 @@ del %(Filename).exe</Command>
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_run.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_sound.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m107.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m52.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m57.cpp" />
|
||||
|
||||
@@ -418,6 +418,12 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp">
|
||||
<Filter>burn\drv\galaxian</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m62.cpp">
|
||||
<Filter>burn\drv\irem</Filter>
|
||||
</ClCompile>
|
||||
@@ -3876,6 +3882,9 @@
|
||||
<Filter Include="burn\drv\galaxian">
|
||||
<UniqueIdentifier>{c4b93ffc-1f2a-4461-a73b-d7153fd1a1e6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\gba">
|
||||
<UniqueIdentifier>{6b17d54b-49ca-4e1f-9f6f-418472209f26}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\irem">
|
||||
<UniqueIdentifier>{0937431a-c5c3-4079-86ff-f553d99ef136}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
||||
@@ -555,6 +555,8 @@ del %(Filename).exe</Command>
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_run.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_sound.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m107.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m52.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m57.cpp" />
|
||||
|
||||
@@ -418,6 +418,12 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp">
|
||||
<Filter>burn\drv\galaxian</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m62.cpp">
|
||||
<Filter>burn\drv\irem</Filter>
|
||||
</ClCompile>
|
||||
@@ -3876,6 +3882,9 @@
|
||||
<Filter Include="burn\drv\galaxian">
|
||||
<UniqueIdentifier>{c4b93ffc-1f2a-4461-a73b-d7153fd1a1e6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\gba">
|
||||
<UniqueIdentifier>{6b17d54b-49ca-4e1f-9f6f-418472209f26}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\irem">
|
||||
<UniqueIdentifier>{0937431a-c5c3-4079-86ff-f553d99ef136}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
||||
@@ -243,6 +243,8 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_run.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_sound.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m107.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m52.cpp" />
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m57.cpp" />
|
||||
@@ -1443,7 +1445,7 @@ cd scripts
|
||||
|
||||
cl.exe /D "_UNICODE" %(Filename).cpp
|
||||
|
||||
.%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
.\%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
|
||||
del %(Filename).obj
|
||||
|
||||
@@ -1462,7 +1464,7 @@ cd scripts
|
||||
|
||||
cl.exe /D "_UNICODE" %(Filename).cpp
|
||||
|
||||
.%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
.\%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
|
||||
del %(Filename).obj
|
||||
|
||||
@@ -1481,7 +1483,7 @@ cd scripts
|
||||
|
||||
cl.exe /D "_UNICODE" /D "BUILD_X64_EXE" %(Filename).cpp
|
||||
|
||||
.%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
.\%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
|
||||
del %(Filename).obj
|
||||
|
||||
@@ -1500,7 +1502,7 @@ cd scripts
|
||||
|
||||
cl.exe /D "_UNICODE" /D "BUILD_X64_EXE" %(Filename).cpp
|
||||
|
||||
.%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
.\%(Filename).exe >../../../projectfiles/visualstudio-2026/generated/%(Filename).h
|
||||
|
||||
del %(Filename).obj
|
||||
|
||||
|
||||
@@ -637,6 +637,12 @@
|
||||
<ClCompile Include="..\..\src\burn\drv\galaxian\gal_stars.cpp">
|
||||
<Filter>burn\drv\galaxian</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\d_gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\gba\gba.cpp">
|
||||
<Filter>burn\drv\gba</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\burn\drv\irem\d_m107.cpp">
|
||||
<Filter>burn\drv\irem</Filter>
|
||||
</ClCompile>
|
||||
@@ -3876,6 +3882,9 @@
|
||||
<Filter Include="burn\drv\galaxian">
|
||||
<UniqueIdentifier>{c4b93ffc-1f2a-4461-a73b-d7153fd1a1e6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\gba">
|
||||
<UniqueIdentifier>{6b17d54b-49ca-4e1f-9f6f-418472209f26}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="burn\drv\irem">
|
||||
<UniqueIdentifier>{0937431a-c5c3-4079-86ff-f553d99ef136}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
||||
+28
-8
@@ -1741,8 +1741,20 @@ extern struct MovieExtInfo MovieInfo; // from replay.cpp
|
||||
struct MovieExtInfo MovieInfo = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
#endif
|
||||
|
||||
static INT32 BurnDayOfYear(INT32 year, INT32 month, INT32 day)
|
||||
{
|
||||
static const INT32 daysBeforeMonth[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
|
||||
INT32 result = daysBeforeMonth[month] + day - 1;
|
||||
if (month > 1 && year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) result++;
|
||||
return result;
|
||||
}
|
||||
|
||||
void BurnGetLocalTime(tm *nTime)
|
||||
{
|
||||
if (nTime == NULL) return;
|
||||
memset(nTime, 0, sizeof(*nTime));
|
||||
nTime->tm_isdst = -1;
|
||||
|
||||
if (is_netgame_or_recording()) {
|
||||
if (is_netgame_or_recording() & 2) { // recording/playback
|
||||
nTime->tm_sec = MovieInfo.second;
|
||||
@@ -1752,19 +1764,27 @@ void BurnGetLocalTime(tm *nTime)
|
||||
nTime->tm_wday = MovieInfo.dayofweek;
|
||||
nTime->tm_mon = MovieInfo.month;
|
||||
nTime->tm_year = MovieInfo.year;
|
||||
if (nTime->tm_mon >= 0 && nTime->tm_mon < 12 && nTime->tm_mday > 0) {
|
||||
nTime->tm_yday = BurnDayOfYear(nTime->tm_year + 1900, nTime->tm_mon, nTime->tm_mday);
|
||||
}
|
||||
} else {
|
||||
nTime->tm_sec = 0; // defaults for netgame
|
||||
nTime->tm_min = 0;
|
||||
nTime->tm_hour = 0;
|
||||
nTime->tm_mday = 1;
|
||||
nTime->tm_wday = 3;
|
||||
nTime->tm_mon = 6 - 1;
|
||||
nTime->tm_year = 2018;
|
||||
nTime->tm_mday = 1; // 2018-06-01 00:00:00 for netgame
|
||||
nTime->tm_wday = 5;
|
||||
nTime->tm_yday = 151;
|
||||
nTime->tm_mon = 5;
|
||||
nTime->tm_year = 2018 - 1900;
|
||||
}
|
||||
} else {
|
||||
time_t nLocalTime = time(NULL); // query current time from this machine
|
||||
tm* tmLocalTime = localtime(&nLocalTime);
|
||||
memcpy(nTime, tmLocalTime, sizeof(tm));
|
||||
if (tmLocalTime) {
|
||||
memcpy(nTime, tmLocalTime, sizeof(*nTime));
|
||||
} else {
|
||||
nTime->tm_mday = 1;
|
||||
nTime->tm_wday = 6;
|
||||
nTime->tm_mon = 0;
|
||||
nTime->tm_year = 2000 - 1900;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define BUILD_CPS3
|
||||
#define BUILD_DATAEAST
|
||||
#define BUILD_GALAXIAN
|
||||
#define BUILD_GBA
|
||||
#define BUILD_IREM
|
||||
#define BUILD_KONAMI
|
||||
#define BUILD_MEGADRIVE
|
||||
@@ -601,6 +602,7 @@ int BurnComputeSHA1(const UINT8 *buffer, int buffer_size, char *hash_str);
|
||||
#define HARDWARE_PREFIX_SNES (0x22000000)
|
||||
#define HARDWARE_PREFIX_IGS_PGM2 (0x23000000)
|
||||
#define HARDWARE_PREFIX_ASTROHOME (0x24000000)
|
||||
#define HARDWARE_PREFIX_GBA (0x25000000)
|
||||
|
||||
#define HARDWARE_SNK_NGP (HARDWARE_PREFIX_NGP | 0x00000000)
|
||||
#define HARDWARE_SNK_NGPC (HARDWARE_PREFIX_NGP | 0x00000001) // must not be 0x10000
|
||||
@@ -852,6 +854,8 @@ int BurnComputeSHA1(const UINT8 *buffer, int buffer_size, char *hash_str);
|
||||
|
||||
#define HARDWARE_ASTROHOME (HARDWARE_PREFIX_ASTROHOME)
|
||||
|
||||
#define HARDWARE_GBA (HARDWARE_PREFIX_GBA)
|
||||
|
||||
// flags for the genre member
|
||||
#define GBF_HORSHOOT (1 << 0)
|
||||
#define GBF_VERSHOOT (1 << 1)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,527 @@
|
||||
// FBNeo Game Boy Advance driver
|
||||
|
||||
#include "burnint.h"
|
||||
#include "gba.h"
|
||||
|
||||
static GbaCore* Gba;
|
||||
static UINT8* DrvRom;
|
||||
static UINT8* DrvBios;
|
||||
static UINT8* DrvState;
|
||||
static UINT8* DrvBattery;
|
||||
static INT32 DrvStateSize;
|
||||
static INT32 DrvBatterySize;
|
||||
|
||||
static UINT8 DrvJoy[10];
|
||||
static UINT8 DrvReset;
|
||||
static UINT8 DrvRecalc;
|
||||
static UINT16 DrvSolar;
|
||||
static UINT8 DrvSolarUp;
|
||||
static UINT8 DrvSolarDown;
|
||||
static UINT8 DrvSolarUpLast;
|
||||
static UINT8 DrvSolarDownLast;
|
||||
static UINT16 DrvGyroZ;
|
||||
static UINT16 DrvTiltX;
|
||||
static UINT16 DrvTiltY;
|
||||
|
||||
#define GBA_BUTTON_INPUTS \
|
||||
{ "P1 Up", BIT_DIGITAL, DrvJoy + GBA_BUTTON_UP, "p1 up" }, \
|
||||
{ "P1 Down", BIT_DIGITAL, DrvJoy + GBA_BUTTON_DOWN, "p1 down" }, \
|
||||
{ "P1 Left", BIT_DIGITAL, DrvJoy + GBA_BUTTON_LEFT, "p1 left" }, \
|
||||
{ "P1 Right", BIT_DIGITAL, DrvJoy + GBA_BUTTON_RIGHT, "p1 right" }, \
|
||||
{ "P1 Button A", BIT_DIGITAL, DrvJoy + GBA_BUTTON_A, "p1 fire 1" }, \
|
||||
{ "P1 Button B", BIT_DIGITAL, DrvJoy + GBA_BUTTON_B, "p1 fire 2" }, \
|
||||
{ "P1 Button L", BIT_DIGITAL, DrvJoy + GBA_BUTTON_L, "p1 fire 3" }, \
|
||||
{ "P1 Button R", BIT_DIGITAL, DrvJoy + GBA_BUTTON_R, "p1 fire 4" },
|
||||
|
||||
#define GBA_RESET_INPUTS \
|
||||
{ "P1 Select", BIT_DIGITAL, DrvJoy + GBA_BUTTON_SELECT, "p1 select" }, \
|
||||
{ "P1 Start", BIT_DIGITAL, DrvJoy + GBA_BUTTON_START, "p1 start" }, \
|
||||
{ "Reset", BIT_DIGITAL, &DrvReset, "reset" },
|
||||
|
||||
#define GBA_SOLAR_INPUTS \
|
||||
{ "Solar Brighter", BIT_DIGITAL, &DrvSolarUp, "p1 fire 5" }, \
|
||||
{ "Solar Darker", BIT_DIGITAL, &DrvSolarDown, "p1 fire 6" },
|
||||
|
||||
#define GBA_GYRO_INPUTS \
|
||||
{ "Gyro Z", BIT_ANALOG_ABS, (UINT8*)&DrvGyroZ, "p1 gyro z-axis" },
|
||||
|
||||
#define GBA_TILT_INPUTS \
|
||||
{ "Tilt X", BIT_ANALOG_ABS, (UINT8*)&DrvTiltX, "p1 tilt x-axis" }, \
|
||||
{ "Tilt Y", BIT_ANALOG_ABS, (UINT8*)&DrvTiltY, "p1 tilt y-axis" },
|
||||
|
||||
static struct BurnInputInfo GbaInputList[] = {
|
||||
GBA_BUTTON_INPUTS
|
||||
GBA_RESET_INPUTS
|
||||
};
|
||||
|
||||
STDINPUTINFO(Gba)
|
||||
|
||||
static struct BurnInputInfo SolarInputList[] = { // Solar sensor
|
||||
GBA_BUTTON_INPUTS
|
||||
GBA_SOLAR_INPUTS
|
||||
GBA_RESET_INPUTS
|
||||
};
|
||||
|
||||
STDINPUTINFO(Solar)
|
||||
|
||||
static struct BurnInputInfo GyroInputList[] = { // Gyroscope
|
||||
GBA_BUTTON_INPUTS
|
||||
GBA_GYRO_INPUTS
|
||||
GBA_RESET_INPUTS
|
||||
};
|
||||
|
||||
STDINPUTINFO(Gyro)
|
||||
|
||||
static struct BurnInputInfo TiltInputList[] = { // Tilt sensor
|
||||
GBA_BUTTON_INPUTS
|
||||
GBA_TILT_INPUTS
|
||||
GBA_RESET_INPUTS
|
||||
};
|
||||
|
||||
STDINPUTINFO(Tilt)
|
||||
|
||||
static struct BurnInputInfo AioInputList[] = { // All-in-one
|
||||
GBA_BUTTON_INPUTS
|
||||
GBA_SOLAR_INPUTS
|
||||
GBA_GYRO_INPUTS
|
||||
GBA_TILT_INPUTS
|
||||
GBA_RESET_INPUTS
|
||||
};
|
||||
|
||||
STDINPUTINFO(Aio)
|
||||
|
||||
#undef GBA_BUTTON_INPUTS
|
||||
#undef GBA_SOLAR_INPUTS
|
||||
#undef GBA_GYRO_INPUTS
|
||||
#undef GBA_TILT_INPUTS
|
||||
#undef GBA_RESET_INPUTS
|
||||
|
||||
static INT32 DrvDoReset()
|
||||
{
|
||||
return GbaCoreReset(Gba);
|
||||
}
|
||||
|
||||
static INT32 DrvInit()
|
||||
{
|
||||
struct BurnRomInfo ri;
|
||||
memset(&ri, 0, sizeof(ri));
|
||||
if (BurnDrvGetRomInfo(&ri, 0) || ri.nLen == 0 || ri.nLen > 32 * 1024 * 1024)
|
||||
return 1;
|
||||
|
||||
BurnSetRefreshRate(59.72750057);
|
||||
|
||||
UINT32 romSize = ri.nLen;
|
||||
DrvRom = (UINT8 *)BurnMalloc((INT32)romSize);
|
||||
if (DrvRom == NULL)
|
||||
return 1;
|
||||
if (BurnLoadRom(DrvRom, 0, 1))
|
||||
return 1;
|
||||
if (GbaCoreInit(&Gba))
|
||||
return 1;
|
||||
|
||||
memset(&ri, 0, sizeof(ri));
|
||||
if (BurnDrvGetRomInfo(&ri, 0x80) == 0 && ri.nType && ri.nLen == 0x4000) {
|
||||
DrvBios = (UINT8 *)BurnMalloc(0x4000);
|
||||
if (DrvBios && BurnLoadRom(DrvBios, 0x80, 1) == 0) {
|
||||
if (GbaCoreLoadBios(Gba, DrvBios, 0x4000))
|
||||
return 1;
|
||||
} else {
|
||||
BurnFree(DrvBios);
|
||||
}
|
||||
}
|
||||
|
||||
tm localTime;
|
||||
memset(&localTime, 0, sizeof(localTime));
|
||||
BurnGetLocalTime(&localTime);
|
||||
GbaRtcSeed rtcSeed;
|
||||
rtcSeed.year = (UINT16)(localTime.tm_year + 1900);
|
||||
rtcSeed.month = (UINT8) (localTime.tm_mon + 1);
|
||||
rtcSeed.day = (UINT8) localTime.tm_mday;
|
||||
rtcSeed.weekday = (UINT8) localTime.tm_wday;
|
||||
rtcSeed.hour = (UINT8) localTime.tm_hour;
|
||||
rtcSeed.minute = (UINT8) localTime.tm_min;
|
||||
rtcSeed.second = (UINT8) localTime.tm_sec;
|
||||
bprintf(PRINT_NORMAL, _T("GBA RTC seed: %04d-%02d-%02d %02d:%02d:%02d (wday %d)\n"),
|
||||
rtcSeed.year, rtcSeed.month, rtcSeed.day, rtcSeed.hour, rtcSeed.minute, rtcSeed.second, rtcSeed.weekday);
|
||||
if (GbaCoreLoadRom(Gba, DrvRom, romSize, &rtcSeed)) return 1;
|
||||
|
||||
DrvStateSize = (INT32)GbaCoreStateSize();
|
||||
DrvState = (UINT8*)BurnMalloc(DrvStateSize);
|
||||
DrvBattery = (UINT8*)BurnMalloc((INT32)GbaCoreGetBatteryCapacity());
|
||||
if (DrvState == NULL || DrvBattery == NULL)
|
||||
return 1;
|
||||
|
||||
DrvBatterySize = (INT32)GbaCoreGetBatterySize(Gba);
|
||||
bprintf(PRINT_NORMAL, _T("GBA cartridge features: %08x, battery: %d\n"), GbaCoreGetCartridgeFeatures(Gba), DrvBatterySize);
|
||||
if (DrvBatterySize > 0) {
|
||||
memcpy(DrvBattery, GbaCoreGetBatteryDataConst(Gba), DrvBatterySize);
|
||||
}
|
||||
|
||||
GbaCoreClearAudio(Gba);
|
||||
DrvRecalc = 1;
|
||||
DrvSolar = 0;
|
||||
DrvSolarUpLast = 0;
|
||||
DrvSolarDownLast = 0;
|
||||
DrvGyroZ = 0x8000;
|
||||
DrvTiltX = 0x8000;
|
||||
DrvTiltY = 0x8000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvExit()
|
||||
{
|
||||
GbaCoreExit(&Gba);
|
||||
BurnFree(DrvRom);
|
||||
BurnFree(DrvBios);
|
||||
BurnFree(DrvState);
|
||||
BurnFree(DrvBattery);
|
||||
|
||||
DrvStateSize = 0;
|
||||
DrvBatterySize = 0;
|
||||
DrvSolar = 0;
|
||||
DrvSolarUpLast = 0;
|
||||
DrvSolarDownLast = 0;
|
||||
DrvGyroZ = 0x8000;
|
||||
DrvTiltX = 0x8000;
|
||||
DrvTiltY = 0x8000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static double DrvAudioRate()
|
||||
{
|
||||
return nBurnSoundLen * (GBA_MASTER_CLOCK / 280896.0);
|
||||
}
|
||||
|
||||
static INT32 DrvDraw()
|
||||
{
|
||||
const UINT32 *framebuffer = GbaCoreGetFramebuffer(Gba);
|
||||
if (framebuffer == NULL || pBurnDraw == NULL)
|
||||
return 0;
|
||||
|
||||
for (INT32 y = 0; y < GBA_HEIGHT; y++) {
|
||||
UINT8 *dest = pBurnDraw + y * nBurnPitch;
|
||||
const UINT32 *source = framebuffer + y * GBA_WIDTH;
|
||||
for (INT32 x = 0; x < GBA_WIDTH; x++) {
|
||||
UINT32 pixel = source[x];
|
||||
PutPix(dest + x * nBurnBpp, BurnHighCol(pixel & 0xff, (pixel >> 8) & 0xff, (pixel >> 16) & 0xff, 0));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvFrame()
|
||||
{
|
||||
if (DrvReset && !bBurnRunAheadFrame && DrvDoReset()) return 1;
|
||||
|
||||
GbaInput input;
|
||||
memset(&input, 0, sizeof(input));
|
||||
input.gyroZ = GbaMotionAxisToInput(DrvGyroZ);
|
||||
input.tiltX = GbaMotionAxisToInput(DrvTiltX);
|
||||
input.tiltY = GbaMotionAxisToInput(DrvTiltY);
|
||||
if (DrvSolarUp && !DrvSolarDown && !DrvSolarUpLast && DrvSolar < GBA_SOLAR_LEVEL_MAX) {
|
||||
DrvSolar++;
|
||||
} else if (DrvSolarDown && !DrvSolarUp && !DrvSolarDownLast && DrvSolar > 0) {
|
||||
DrvSolar--;
|
||||
}
|
||||
DrvSolarUpLast = DrvSolarUp;
|
||||
DrvSolarDownLast = DrvSolarDown;
|
||||
input.solar = GbaSolarLevelToInput((UINT8)DrvSolar);
|
||||
for (INT32 i = 0; i < 10; i++) {
|
||||
input.buttons |= (DrvJoy[i] & 1) << i;
|
||||
}
|
||||
GbaCoreSetInput(Gba, &input);
|
||||
|
||||
INT32 runAhead = bBurnRunAheadFrame != 0;
|
||||
double audioRate = nBurnSoundLen > 0 ? DrvAudioRate() : 0.0;
|
||||
if (GbaCoreConfigureAudio(Gba, audioRate, nBurnSoundLen, !runAhead && nBurnSoundLen > 0))
|
||||
return 1;
|
||||
if (GbaCoreRunFrame(Gba))
|
||||
return 1;
|
||||
if (!runAhead && GbaCoreRenderAudio(Gba, pBurnSoundOut, nBurnSoundLen) != nBurnSoundLen)
|
||||
return 1;
|
||||
|
||||
if (pBurnDraw) {
|
||||
DrvDraw();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 DrvScan(INT32 nAction, INT32 *pnMin)
|
||||
{
|
||||
if (pnMin) {
|
||||
*pnMin = 0x029698;
|
||||
}
|
||||
|
||||
if ((nAction & ACB_VOLATILE) && Gba && DrvState) {
|
||||
SCAN_VAR(DrvSolar);
|
||||
if (nAction & ACB_WRITE) {
|
||||
if (DrvSolar > GBA_SOLAR_LEVEL_MAX)
|
||||
DrvSolar = GbaSolarLegacyToLevel(DrvSolar);
|
||||
DrvSolarUpLast = DrvSolarUp;
|
||||
DrvSolarDownLast = DrvSolarDown;
|
||||
ScanVar(DrvState, DrvStateSize, "gba_machine");
|
||||
if (GbaCoreLoadState(Gba, DrvState, DrvStateSize, (nAction & ACB_RUNAHEAD) != 0))
|
||||
return 1;
|
||||
} else {
|
||||
if (GbaCoreSaveState(Gba, DrvState, DrvStateSize))
|
||||
return 1;
|
||||
ScanVar(DrvState, DrvStateSize, "gba_machine");
|
||||
}
|
||||
}
|
||||
|
||||
if ((nAction & ACB_NVRAM) && Gba && DrvBattery && DrvBatterySize > 0) {
|
||||
if (nAction & ACB_WRITE) {
|
||||
ScanVar(DrvBattery, DrvBatterySize, "gba_battery");
|
||||
if (GbaCoreLoadBattery(Gba, DrvBattery, DrvBatterySize))
|
||||
return 1;
|
||||
} else {
|
||||
memcpy(DrvBattery, GbaCoreGetBatteryDataConst(Gba), DrvBatterySize);
|
||||
ScanVar(DrvBattery, DrvBatterySize, "gba_battery");
|
||||
if (!(nAction & ACB_RUNAHEAD))
|
||||
GbaCoreClearBatteryDirty(Gba);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT32 GbaGetZipName(char **pszName, UINT32 i)
|
||||
{
|
||||
static char szFilename[MAX_PATH];
|
||||
char *pszGameName = NULL;
|
||||
|
||||
if (pszName == NULL)
|
||||
return 1;
|
||||
|
||||
if (i == 0) {
|
||||
pszGameName = BurnDrvGetTextA(DRV_NAME);
|
||||
} else if (i == 1 && BurnDrvGetTextA(DRV_BOARDROM)) {
|
||||
pszGameName = BurnDrvGetTextA(DRV_BOARDROM);
|
||||
} else {
|
||||
pszGameName = BurnDrvGetTextA(DRV_PARENT);
|
||||
}
|
||||
|
||||
if (pszGameName == NULL || i > 2) {
|
||||
*pszName = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
strncpy(szFilename, pszGameName, MAX_PATH - 1);
|
||||
szFilename[MAX_PATH - 1] = 0;
|
||||
if (strncmp(szFilename, "gba_", 4) == 0) {
|
||||
memmove(szFilename, szFilename + 4, strlen(szFilename + 4) + 1);
|
||||
}
|
||||
*pszName = szFilename;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct BurnRomInfo emptyRomDesc[] = {
|
||||
{ "", 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct BurnRomInfo gba_gbaRomDesc[] = {
|
||||
{ "gba_gba.bin", 0x4000, 0x81977335, BRF_PRG | BRF_BIOS | BRF_OPT },
|
||||
};
|
||||
|
||||
STD_ROM_PICK(gba_gba)
|
||||
STD_ROM_FN(gba_gba)
|
||||
|
||||
struct BurnDriver BurnDrvgba_gba = {
|
||||
"gba_gba", NULL, NULL, NULL, "2001",
|
||||
"Game Boy Advance BIOS\0", "Optional BIOS, bundled replacement is used when absent", "Nintendo", "Game Boy Advance",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_BOARDROM, 0, HARDWARE_GBA, GBF_BIOS, 0,
|
||||
GbaGetZipName, gba_gbaRomInfo, gba_gbaRomName, NULL, NULL, NULL, NULL, GbaInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
|
||||
// =========================================================================================
|
||||
// Please use short names from the MAME softwarelist/gba set wherever possible.
|
||||
// Avoid excessively‑long titles that contradict the intent of the short‑name identifiers.
|
||||
// [Example] Fire Emblem : The Sacred Stones(USA, Australia)
|
||||
// ShortName: gba_firembssu
|
||||
// =========================================================================================
|
||||
|
||||
|
||||
// Fire Emblem: The Sacred Stones (USA, Australia)
|
||||
|
||||
static struct BurnRomInfo gba_firembssuRomDesc[] = {
|
||||
{ "Fire Emblem - The Sacred Stones (U, A)(2005)(Nintendo).gba", 0x1000000, 0xa47246ae, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_firembssu, gba_firembssu, gba_gba)
|
||||
STD_ROM_FN(gba_firembssu)
|
||||
|
||||
struct BurnDriver BurnDrvgba_firembssu = {
|
||||
"gba_firembssu", NULL, "gba_gba", NULL, "2005",
|
||||
"Fire Emblem: The Sacred Stones (USA, Australia)\0", NULL, "Nintendo", "Game Boy Advance",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_RPG | GBF_STRATEGY, 0,
|
||||
GbaGetZipName, gba_firembssuRomInfo, gba_firembssuRomName, NULL, NULL, NULL, NULL, GbaInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// Fire Emblem: Seima no Kouseki (Japan)
|
||||
|
||||
static struct BurnRomInfo gba_firembssjRomDesc[] = {
|
||||
{ "Fire Emblem - Seima no Kouseki (J)(2004)(Nintendo).gba", 0x1000000, 0x9d76826f, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_firembssj, gba_firembssj, gba_gba)
|
||||
STD_ROM_FN(gba_firembssj)
|
||||
|
||||
struct BurnDriver BurnDrvgba_firembssj = {
|
||||
"gba_firembssj", "gba_firembssu", "gba_gba", NULL, "2004",
|
||||
"Fire Emblem: Seima no Kouseki (Japan)\0", NULL, "Nintendo", "Game Boy Advance",
|
||||
L"Fire Emblem: Seima no Kouseki (Japan)\0\u30d5\u30a1\u30a4\u30a2\u30fc\u30a8\u30e0\u30d6\u30ec\u30e0 \u8056\u9b54\u306e\u5149\u77f3\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_RPG | GBF_STRATEGY, 0,
|
||||
GbaGetZipName, gba_firembssjRomInfo, gba_firembssjRomName, NULL, NULL, NULL, NULL, GbaInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// Fire Emblem: Sheng Xie De Yi Zhi (Hack, v1.4)
|
||||
|
||||
static struct BurnRomInfo gba_firembssxRomDesc[] = {
|
||||
{ "Fire Emblem - Sheng Xie De Yi Zhi (C)(2006)(ChinaFE & Wolf Group).gba", 0x1000000, 0x9cbb923e, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_firembssx, gba_firembssx, gba_gba)
|
||||
STD_ROM_FN(gba_firembssx)
|
||||
|
||||
struct BurnDriver BurnDrvgba_firembssx = {
|
||||
"gba_firembssx", "gba_firembssu", "gba_gba", NULL, "2006",
|
||||
"Fire Emblem: Sheng Xie De Yi Zhi (Hack, v1.4)\0", NULL, "ChinaFE & Wolf Group", "Game Boy Advance",
|
||||
L"Fire Emblem: Sheng Xie De Yi Zhi (Hack, v1.4)\0\u706b\u7130\u4e4b\u7eb9\u7ae0: \u5723\u90aa\u7684\u610f\u5fd7\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE | BDF_HACK, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_RPG | GBF_STRATEGY, 0,
|
||||
GbaGetZipName, gba_firembssxRomInfo, gba_firembssxRomName, NULL, NULL, NULL, NULL, GbaInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// WarioWare: Twisted! (USA, Australia)
|
||||
// Gyro sensor
|
||||
|
||||
static struct BurnRomInfo gba_wariotwsRomDesc[] = {
|
||||
{ "WarioWare ‑ Twisted! (U, A)(2005)(Nintendo).gba", 0x1000000, 0xcb4e844b, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_wariotws, gba_wariotws, gba_gba)
|
||||
STD_ROM_FN(gba_wariotws)
|
||||
|
||||
struct BurnDriver BurnDrvgba_wariotws = {
|
||||
"gba_wariotws", NULL, "gba_gba", NULL, "2005",
|
||||
"WarioWare: Twisted! (USA, Australia)\0", NULL, "Nintendo", "Game Boy Advance",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_MISC, 0,
|
||||
GbaGetZipName, gba_wariotwsRomInfo, gba_wariotwsRomName, NULL, NULL, NULL, NULL, GyroInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// Mawaru: Made in Wario (Japan)
|
||||
// Gyro sensor
|
||||
|
||||
static struct BurnRomInfo gba_wariotwjRomDesc[] = {
|
||||
{"Mawaru - Made in Wario (J)(2005)(Nintendo).gba", 0x1000000, 0xe69964f1, BRF_ESS | BRF_PRG},
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_wariotwj, gba_wariotwj, gba_gba)
|
||||
STD_ROM_FN(gba_wariotwj)
|
||||
|
||||
struct BurnDriver BurnDrvGbaMawaruWario = {
|
||||
"gba_wariotwj", "gba_wariotws", "gba_gba", NULL, "2005",
|
||||
"Mawaru: Made in Wario (Japan)\0", NULL, "Nintendo", "Game Boy Advance",
|
||||
L"Mawaru: Made in Wario (Japan)\0\u307e\u308f\u308b\u30e1\u30a4\u30c9\u30a4\u30f3\u30ef\u30ea\u30aa\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_MISC, 0,
|
||||
GbaGetZipName, gba_wariotwjRomInfo, gba_wariotwjRomName, NULL, NULL, NULL, NULL, GyroInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// Yoshi Topsy: Turvy (USA)
|
||||
|
||||
static struct BurnRomInfo gba_yoshittRomDesc[] = {
|
||||
{ "Yoshi Topsy ‑ Turvy (U)(2005)(Nintendo).gba", 0x800000, 0xe64c265c, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_yoshitt, gba_yoshitt, gba_gba)
|
||||
STD_ROM_FN(gba_yoshitt)
|
||||
|
||||
struct BurnDriver BurnDrvgba_yoshitt = {
|
||||
"gba_yoshitt", NULL, "gba_gba", NULL, "2005",
|
||||
"Yoshi Topsy: Turvy (USA)\0", NULL, "Nintendo", "Game Boy Advance",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_PLATFORM, 0,
|
||||
GbaGetZipName, gba_yoshittRomInfo, gba_yoshittRomName, NULL, NULL, NULL, NULL, TiltInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// Yoshi no Banyuuinryoku (Japan)
|
||||
// Tilt sensor
|
||||
|
||||
static struct BurnRomInfo gba_yoshibanRomDesc[] = {
|
||||
{ "Yoshi no Banyuuinryoku (J)(2005)(Nintendo).gba", 0x800000, 0x31594b7a, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_yoshiban, gba_yoshiban, gba_gba)
|
||||
STD_ROM_FN(gba_yoshiban)
|
||||
|
||||
struct BurnDriver BurnDrvgba_yoshiban = {
|
||||
"gba_yoshiban", "gba_yoshitt", "gba_gba", NULL, "2005",
|
||||
"Yoshi no Banyuuinryoku (Japan)\0", NULL, "Nintendo", "Game Boy Advance",
|
||||
L"Yoshi no Banyuuinryoku (Japan)\0\u30e8\u30c3\u30b7\u30fc\u306e\u4e07\u6709\u5f15\u529b\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_PLATFORM, 0,
|
||||
GbaGetZipName, gba_yoshibanRomInfo, gba_yoshibanRomName, NULL, NULL, NULL, NULL, TiltInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// Boktai 2: Solar Boy Django (USA)
|
||||
// Solar sensor + RTC clock
|
||||
|
||||
static struct BurnRomInfo gba_boktai2uRomDesc[] = {
|
||||
{ "Boktai 2 ‑ Solar Boy Django (U)(2004)(Konami).gba", 0x1000000, 0xe1ffb2d1, BRF_ESS | BRF_PRG },
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_boktai2u, gba_boktai2u, gba_gba)
|
||||
STD_ROM_FN(gba_boktai2u)
|
||||
|
||||
struct BurnDriver BurnDrvgba_boktai2u = {
|
||||
"gba_boktai2u", NULL, "gba_gba", NULL, "2004",
|
||||
"Boktai 2: Solar Boy Django (USA)\0", NULL, "Konami", "Game Boy Advance",
|
||||
NULL, NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_ACTION | GBF_RPG, 0,
|
||||
GbaGetZipName, gba_boktai2uRomInfo, gba_boktai2uRomName, NULL, NULL, NULL, NULL, SolarInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
|
||||
// Zoku Bokura no Taiyou: Taiyou Shounen Django (Japan, Rev 1)
|
||||
// Solar light‑sensor + RTC clock
|
||||
|
||||
static struct BurnRomInfo gba_boktai2jRomDesc[] = {
|
||||
{"Zoku Bokura no Taiyou - Taiyou Shounen Django (J, Rev 1)(2004)(Konami).gba", 0x1000000, 0x71e2cd01, BRF_ESS | BRF_PRG},
|
||||
};
|
||||
|
||||
STDROMPICKEXT(gba_boktai2j, gba_boktai2j, gba_gba)
|
||||
STD_ROM_FN(gba_boktai2j)
|
||||
|
||||
struct BurnDriver BurnDrvGbaBoktai2j = {
|
||||
"gba_boktai2j", "gba_boktai2u", "gba_gba", NULL, "2004",
|
||||
"Zoku Bokura no Taiyou: Taiyou Shounen Django (Japan, Rev 1)\0", NULL, "Konami", "Game Boy Advance",
|
||||
L"Zoku Bokura no Taiyou: Taiyou Shounen Django (Japan, Rev 1)\0\u7d9a \u30dc\u30af\u3089\u306e\u592a\u967d \u592a\u967d\u5c11\u5e74\u30b8\u30e3\u30f3\u30b4\0", NULL, NULL, NULL,
|
||||
BDF_GAME_WORKING | BDF_CLONE, 1, HARDWARE_PREFIX_CARTRIDGE | HARDWARE_GBA, GBF_ACTION | GBF_RPG, 0,
|
||||
GbaGetZipName, gba_boktai2jRomInfo, gba_boktai2jRomName, NULL, NULL, NULL, NULL, SolarInputInfo, NULL,
|
||||
DrvInit, DrvExit, DrvFrame, DrvDraw, DrvScan, &DrvRecalc, 0,
|
||||
GBA_WIDTH, GBA_HEIGHT, 3, 2
|
||||
};
|
||||
@@ -0,0 +1,498 @@
|
||||
#ifndef GBA_STANDALONE
|
||||
#include "burnint.h"
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#define BurnMalloc(x) malloc(x)
|
||||
#define BurnFree(x) do { free(x); (x) = NULL; } while (0)
|
||||
#endif
|
||||
#include "gba.h"
|
||||
#include "gba_impl.h"
|
||||
|
||||
struct GbaCore {
|
||||
gba_t state;
|
||||
gba_scratch_t scratch;
|
||||
sb_emu_state_t host;
|
||||
UINT8* rom;
|
||||
size_t romSize;
|
||||
bool ownsRom;
|
||||
UINT8 externalBios[16 * 1024];
|
||||
bool externalBiosLoaded;
|
||||
UINT32 cartridgeFeatures;
|
||||
UINT8 cartridgeBackupType;
|
||||
double sourceRate;
|
||||
INT32 outputFrames;
|
||||
};
|
||||
|
||||
struct GbaCartridgeProfile {
|
||||
UINT8 gameCode[4];
|
||||
UINT32 features;
|
||||
UINT8 backupType;
|
||||
};
|
||||
|
||||
static const UINT8 GbaSolarCounts[GBA_SOLAR_LEVEL_MAX + 1] = {
|
||||
233, 228, 222, 215, 206, 191, 171, 149, 124, 94, 50
|
||||
};
|
||||
|
||||
INT32 GbaMotionAxisToInput(UINT16 axis)
|
||||
{
|
||||
return (INT32)(((INT64)(INT32(axis) - 0x8000)) * 0x10000);
|
||||
}
|
||||
|
||||
UINT8 GbaSolarLevelToInput(UINT8 level)
|
||||
{
|
||||
if (level > GBA_SOLAR_LEVEL_MAX)
|
||||
level = GBA_SOLAR_LEVEL_MAX;
|
||||
return (UINT8)(((233 - GbaSolarCounts[level]) * 255) / 183);
|
||||
}
|
||||
|
||||
UINT8 GbaSolarLegacyToLevel(UINT16 legacy)
|
||||
{
|
||||
UINT8 input = legacy >> 8;
|
||||
INT32 count = 233 - (input * 183) / 255;
|
||||
UINT8 closest = 0;
|
||||
INT32 closestDistance = count - GbaSolarCounts[0];
|
||||
if (closestDistance < 0)
|
||||
closestDistance = -closestDistance;
|
||||
|
||||
for (UINT8 level = 1; level <= GBA_SOLAR_LEVEL_MAX; level++) {
|
||||
INT32 distance = count - GbaSolarCounts[level];
|
||||
if (distance < 0)
|
||||
distance = -distance;
|
||||
if (distance < closestDistance) {
|
||||
closest = level;
|
||||
closestDistance = distance;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
static const GbaCartridgeProfile GbaCartridgeProfiles[] = {
|
||||
{{'U', '3', 'I', 'J'}, GBA_CART_RTC | GBA_CART_SOLAR, GBA_BACKUP_EEPROM },
|
||||
{{'U', '3', 'I', 'E'}, GBA_CART_RTC | GBA_CART_SOLAR, GBA_BACKUP_EEPROM },
|
||||
{{'U', '3', 'I', 'P'}, GBA_CART_RTC | GBA_CART_SOLAR, GBA_BACKUP_EEPROM },
|
||||
{{'U', '3', '2', 'J'}, GBA_CART_RTC | GBA_CART_SOLAR, GBA_BACKUP_EEPROM },
|
||||
{{'U', '3', '2', 'E'}, GBA_CART_RTC | GBA_CART_SOLAR, GBA_BACKUP_EEPROM },
|
||||
{{'U', '3', '2', 'P'}, GBA_CART_RTC | GBA_CART_SOLAR, GBA_BACKUP_EEPROM },
|
||||
{{'U', '3', '3', 'J'}, GBA_CART_RTC | GBA_CART_SOLAR, GBA_BACKUP_EEPROM },
|
||||
{{'V', '4', '9', 'J'}, GBA_CART_RUMBLE, GBA_BACKUP_SRAM },
|
||||
{{'V', '4', '9', 'E'}, GBA_CART_RUMBLE, GBA_BACKUP_SRAM },
|
||||
{{'V', '4', '9', 'P'}, GBA_CART_RUMBLE, GBA_BACKUP_SRAM },
|
||||
{{'2', 'G', 'B', 'P'}, GBA_CART_RUMBLE, GBA_BACKUP_SRAM },
|
||||
{{'R', 'Z', 'W', 'J'}, GBA_CART_RUMBLE | GBA_CART_GYRO, GBA_BACKUP_SRAM },
|
||||
{{'R', 'Z', 'W', 'E'}, GBA_CART_RUMBLE | GBA_CART_GYRO, GBA_BACKUP_SRAM },
|
||||
{{'R', 'Z', 'W', 'P'}, GBA_CART_RUMBLE | GBA_CART_GYRO, GBA_BACKUP_SRAM },
|
||||
{{'K', 'H', 'P', 'J'}, GBA_CART_TILT, GBA_BACKUP_EEPROM },
|
||||
{{'K', 'Y', 'G', 'J'}, GBA_CART_TILT, GBA_BACKUP_EEPROM },
|
||||
{{'K', 'Y', 'G', 'E'}, GBA_CART_TILT, GBA_BACKUP_EEPROM },
|
||||
{{'K', 'Y', 'G', 'P'}, GBA_CART_TILT, GBA_BACKUP_EEPROM },
|
||||
{{'B', 'L', 'J', 'J'}, GBA_CART_RTC, GBA_BACKUP_FLASH_64K },
|
||||
{{'B', 'L', 'J', 'K'}, GBA_CART_RTC, GBA_BACKUP_FLASH_64K },
|
||||
{{'B', 'L', 'V', 'J'}, GBA_CART_RTC, GBA_BACKUP_FLASH_64K },
|
||||
{{'A', 'X', 'V', 'J'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'V', 'E'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'V', 'P'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'V', 'I'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'V', 'S'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'V', 'D'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'V', 'F'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'P', 'J'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'P', 'E'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'P', 'P'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'P', 'I'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'P', 'S'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'P', 'D'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'A', 'X', 'P', 'F'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'P', 'E', 'J'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'P', 'E', 'E'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'P', 'E', 'P'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'P', 'E', 'I'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'P', 'E', 'S'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'P', 'E', 'D'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'P', 'E', 'F'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
{{'B', 'R', '4', 'J'}, GBA_CART_RTC, GBA_BACKUP_FLASH_64K },
|
||||
{{'B', 'K', 'A', 'J'}, GBA_CART_RTC, GBA_BACKUP_FLASH_128K},
|
||||
};
|
||||
|
||||
static const GbaCartridgeProfile *GbaFindCartridgeProfile(const UINT8 *rom, size_t romSize)
|
||||
{
|
||||
if (rom == NULL || romSize < 0xb3 || rom[0xb2] != 0x96)
|
||||
return NULL;
|
||||
|
||||
for (UINT32 i = 0; i < sizeof(GbaCartridgeProfiles) / sizeof(GbaCartridgeProfiles[0]); i++) {
|
||||
if (memcmp(rom + 0xac, GbaCartridgeProfiles[i].gameCode, 4) == 0) {
|
||||
return &GbaCartridgeProfiles[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static UINT32 GbaDetectCartridgeFeatures(const UINT8 *rom, size_t romSize)
|
||||
{
|
||||
const GbaCartridgeProfile *profile = GbaFindCartridgeProfile(rom, romSize);
|
||||
return profile ? profile->features : 0;
|
||||
}
|
||||
|
||||
static UINT8 GbaDetectCartridgeBackupType(const UINT8 *rom, size_t romSize)
|
||||
{
|
||||
const GbaCartridgeProfile *profile = GbaFindCartridgeProfile(rom, romSize);
|
||||
return profile ? profile->backupType : 0;
|
||||
}
|
||||
|
||||
static void GbaCoreClearPresentation(GbaCore *core)
|
||||
{
|
||||
if (core == NULL)
|
||||
return;
|
||||
core->host.audio_ring_buff.read_ptr = 0;
|
||||
core->host.audio_ring_buff.write_ptr = 0;
|
||||
}
|
||||
|
||||
static void GbaCoreApplyCartridgeFeatures(GbaCore *core)
|
||||
{
|
||||
core->state.cart.features = core->cartridgeFeatures;
|
||||
if (core->cartridgeBackupType != GBA_BACKUP_NONE) {
|
||||
core->state.cart.backup_type = core->cartridgeBackupType;
|
||||
gba_setup_flash_id(&core->state);
|
||||
}
|
||||
gba_gpio_update_rumble(&core->state);
|
||||
core->host.joy.rumble = core->state.cart.gpio.rumble;
|
||||
}
|
||||
|
||||
static void GbaCoreApplyInput(GbaCore *core, const GbaInput *input)
|
||||
{
|
||||
memset(core->host.joy.inputs, 0, sizeof(core->host.joy.inputs));
|
||||
core->host.joy.gyro_z = 0;
|
||||
core->host.joy.tilt_x = 0;
|
||||
core->host.joy.tilt_y = 0;
|
||||
if (input == NULL)
|
||||
return;
|
||||
core->host.joy.inputs[SE_KEY_A ] = (input->buttons >> GBA_BUTTON_A ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_B ] = (input->buttons >> GBA_BUTTON_B ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_SELECT] = (input->buttons >> GBA_BUTTON_SELECT) & 1;
|
||||
core->host.joy.inputs[SE_KEY_START ] = (input->buttons >> GBA_BUTTON_START ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_RIGHT ] = (input->buttons >> GBA_BUTTON_RIGHT ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_LEFT ] = (input->buttons >> GBA_BUTTON_LEFT ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_UP ] = (input->buttons >> GBA_BUTTON_UP ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_DOWN ] = (input->buttons >> GBA_BUTTON_DOWN ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_R ] = (input->buttons >> GBA_BUTTON_R ) & 1;
|
||||
core->host.joy.inputs[SE_KEY_L ] = (input->buttons >> GBA_BUTTON_L ) & 1;
|
||||
core->host.joy.solar_sensor = input->solar / 255.0f;
|
||||
core->host.joy.gyro_z = input->gyroZ;
|
||||
core->host.joy.tilt_x = input->tiltX;
|
||||
core->host.joy.tilt_y = input->tiltY;
|
||||
}
|
||||
|
||||
INT32 GbaCoreInit(GbaCore **core)
|
||||
{
|
||||
if (core == NULL)
|
||||
return 1;
|
||||
*core = (GbaCore *)BurnMalloc(sizeof(GbaCore));
|
||||
if (*core == NULL)
|
||||
return 1;
|
||||
memset(*core, 0, sizeof(GbaCore));
|
||||
(*core)->host.render_frame = true;
|
||||
(*core)->host.capture_audio = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GbaCoreExit(GbaCore **core)
|
||||
{
|
||||
if (core == NULL || *core == NULL)
|
||||
return;
|
||||
gba_unload(&(*core)->state, &(*core)->scratch);
|
||||
if ((*core)->ownsRom)
|
||||
BurnFree((*core)->rom);
|
||||
BurnFree(*core);
|
||||
}
|
||||
|
||||
INT32 GbaCoreLoadRom(GbaCore *core, const UINT8 *rom, size_t romSize, const GbaRtcSeed *rtcSeed)
|
||||
{
|
||||
if (core == NULL || rom == NULL || romSize == 0 || romSize > 32 * 1024 * 1024)
|
||||
return 1;
|
||||
const size_t allocSize = romSize < 0x100 ? 0x100 : romSize;
|
||||
UINT8 *romCopy = (UINT8 *)BurnMalloc((INT32)allocSize);
|
||||
if (romCopy == NULL)
|
||||
return 1;
|
||||
memset(romCopy, 0xff, allocSize);
|
||||
memcpy(romCopy, rom, romSize);
|
||||
if (core->ownsRom)
|
||||
BurnFree(core->rom);
|
||||
core->rom = romCopy;
|
||||
core->romSize = romSize;
|
||||
core->ownsRom = true;
|
||||
core->cartridgeFeatures = GbaDetectCartridgeFeatures(core->rom, core->romSize);
|
||||
core->cartridgeBackupType = GbaDetectCartridgeBackupType(core->rom, core->romSize);
|
||||
rom = core->rom;
|
||||
core->host.rom_data = core->rom;
|
||||
core->host.rom_size = romSize;
|
||||
core->host.bios_data = core->externalBiosLoaded ? core->externalBios : NULL;
|
||||
core->host.bios_size = core->externalBiosLoaded ? sizeof(core->externalBios) : 0;
|
||||
core->host.rom_loaded = true;
|
||||
strcpy(core->host.rom_path, "fbneo.gba");
|
||||
gba_host_loading = &core->host;
|
||||
const bool loaded = gba_load_rom(&core->host, &core->state, &core->scratch);
|
||||
gba_host_loading = NULL;
|
||||
if (!loaded)
|
||||
return 1;
|
||||
gba_rtc_civil_t seed;
|
||||
memset(&seed, 0, sizeof(seed));
|
||||
if (rtcSeed) {
|
||||
seed.year = rtcSeed->year;
|
||||
seed.month = rtcSeed->month;
|
||||
seed.day = rtcSeed->day;
|
||||
seed.weekday = rtcSeed->weekday;
|
||||
seed.hour = rtcSeed->hour;
|
||||
seed.minute = rtcSeed->minute;
|
||||
seed.second = rtcSeed->second;
|
||||
}
|
||||
gba_rtc_cold_init(&core->state.rtc, rtcSeed ? &seed : NULL);
|
||||
GbaCoreApplyCartridgeFeatures(core);
|
||||
GbaCoreRebind(core);
|
||||
GbaCoreClearPresentation(core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 GbaCoreLoadBios(GbaCore *core, const UINT8 *bios, size_t biosSize)
|
||||
{
|
||||
if (core == NULL || bios == NULL || biosSize != sizeof(core->externalBios))
|
||||
return 1;
|
||||
memcpy(core->externalBios, bios, sizeof(core->externalBios));
|
||||
core->externalBiosLoaded = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 GbaCoreReset(GbaCore *core)
|
||||
{
|
||||
if (core == NULL || core->rom == NULL)
|
||||
return 1;
|
||||
UINT8 battery[GBA_BATTERY_CAPACITY];
|
||||
INT64 rtcSeconds = core->state.rtc.rtc_seconds;
|
||||
INT64 rtcHostSeconds = core->state.rtc.host_seconds;
|
||||
UINT8 rtcStatus = core->state.rtc.status;
|
||||
memcpy(battery, core->state.mem.cart_backup, sizeof(battery));
|
||||
core->host.rom_data = core->rom;
|
||||
core->host.rom_size = core->romSize;
|
||||
core->host.bios_data = core->externalBiosLoaded ? core->externalBios : NULL;
|
||||
core->host.bios_size = core->externalBiosLoaded ? sizeof(core->externalBios) : 0;
|
||||
gba_host_loading = &core->host;
|
||||
const bool loaded = gba_load_rom(&core->host, &core->state, &core->scratch);
|
||||
gba_host_loading = NULL;
|
||||
if (!loaded)
|
||||
return 1;
|
||||
memcpy(core->state.mem.cart_backup, battery, sizeof(battery));
|
||||
core->state.rtc.rtc_seconds = rtcSeconds;
|
||||
core->state.rtc.host_seconds = rtcHostSeconds;
|
||||
core->state.rtc.status = rtcStatus;
|
||||
gba_rtc_transport_reset(&core->state.rtc);
|
||||
core->state.rtc.last_pins = 0;
|
||||
GbaCoreApplyCartridgeFeatures(core);
|
||||
GbaCoreRebind(core);
|
||||
GbaCoreClearAudio(core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GbaCoreSetInput(GbaCore *core, const GbaInput *input)
|
||||
{
|
||||
if (core != NULL)
|
||||
GbaCoreApplyInput(core, input);
|
||||
}
|
||||
|
||||
INT32 GbaCoreConfigureAudio(GbaCore *core, double sourceRate, INT32 outputFrames, INT32 captureAudio)
|
||||
{
|
||||
if (core == NULL)
|
||||
return 1;
|
||||
if (sourceRate < 0.0 || outputFrames < 0)
|
||||
return 1;
|
||||
if ((sourceRate <= 0.0) != (outputFrames <= 0))
|
||||
return 1;
|
||||
core->host.capture_audio = captureAudio != 0;
|
||||
if (sourceRate != core->sourceRate || outputFrames != core->outputFrames) {
|
||||
core->sourceRate = sourceRate;
|
||||
core->outputFrames = outputFrames;
|
||||
core->host.audio_sample_rate = sourceRate;
|
||||
GbaCoreClearPresentation(core);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 GbaCoreRunFrame(GbaCore *core)
|
||||
{
|
||||
if (core == NULL || core->rom == NULL)
|
||||
return 1;
|
||||
core->host.render_frame = true;
|
||||
gba_tick(&core->host, &core->state, &core->scratch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT32 GbaCoreGetCartridgeFeatures(const GbaCore *core)
|
||||
{
|
||||
return core == NULL ? 0 : core->cartridgeFeatures;
|
||||
}
|
||||
|
||||
UINT8 GbaCoreGetRumbleOutput(const GbaCore *core)
|
||||
{
|
||||
if (core == NULL || !(core->state.cart.features & GBA_CART_RUMBLE))
|
||||
return 0;
|
||||
return core->state.cart.gpio.rumble;
|
||||
}
|
||||
|
||||
const UINT32 *GbaCoreGetFramebuffer(const GbaCore *core)
|
||||
{
|
||||
return core == NULL ? NULL : (const UINT32 *)core->scratch.framebuffer;
|
||||
}
|
||||
|
||||
UINT32 GbaCoreGetFramebufferPitch()
|
||||
{
|
||||
return GBA_WIDTH * sizeof(UINT32);
|
||||
}
|
||||
|
||||
static INT32 GbaCoreSourceFramesAvailable(GbaCore *core)
|
||||
{
|
||||
return (INT32)(sb_ring_buffer_size(&core->host.audio_ring_buff) / 2);
|
||||
}
|
||||
|
||||
INT32 GbaCoreRenderAudio(GbaCore *core, INT16 *stereo, INT32 frames)
|
||||
{
|
||||
if (core == NULL || frames <= 0)
|
||||
return 0;
|
||||
if (core->sourceRate <= 0.0) {
|
||||
if (stereo != NULL)
|
||||
memset(stereo, 0, frames * 2 * sizeof(INT16));
|
||||
return frames;
|
||||
}
|
||||
|
||||
sb_ring_buffer_t *ring = &core->host.audio_ring_buff;
|
||||
INT32 available = GbaCoreSourceFramesAvailable(core);
|
||||
INT32 produced = available < frames ? available : frames;
|
||||
for (INT32 i = 0; i < produced; i++) {
|
||||
UINT32 left = ring->read_ptr++ % SB_AUDIO_RING_BUFFER_SIZE;
|
||||
UINT32 right = ring->read_ptr++ % SB_AUDIO_RING_BUFFER_SIZE;
|
||||
if (stereo != NULL) {
|
||||
stereo[i * 2 + 0] = ring->data[left];
|
||||
stereo[i * 2 + 1] = ring->data[right];
|
||||
}
|
||||
}
|
||||
if (produced < frames) {
|
||||
INT32 missing = frames - produced;
|
||||
if (stereo != NULL)
|
||||
memset(stereo + produced * 2, 0, missing * 2 * sizeof(INT16));
|
||||
ring->read_ptr += (UINT32)missing * 2;
|
||||
ring->write_ptr += (UINT32)missing * 2;
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
void GbaCoreClearAudio(GbaCore *core)
|
||||
{
|
||||
GbaCoreClearPresentation(core);
|
||||
}
|
||||
|
||||
UINT8 *GbaCoreGetBatteryData(GbaCore *core)
|
||||
{
|
||||
return core == NULL ? NULL : core->state.mem.cart_backup;
|
||||
}
|
||||
|
||||
const UINT8 *GbaCoreGetBatteryDataConst(const GbaCore *core)
|
||||
{
|
||||
return core == NULL ? NULL : core->state.mem.cart_backup;
|
||||
}
|
||||
|
||||
size_t GbaCoreGetBatteryCapacity()
|
||||
{
|
||||
return GBA_BATTERY_CAPACITY;
|
||||
}
|
||||
|
||||
size_t GbaCoreGetBatterySize(const GbaCore *core)
|
||||
{
|
||||
if (core == NULL) return 0;
|
||||
switch (core->state.cart.backup_type) {
|
||||
case GBA_BACKUP_EEPROM_512B: return 512;
|
||||
case GBA_BACKUP_EEPROM:
|
||||
case GBA_BACKUP_EEPROM_8KB: return 8 * 1024;
|
||||
case GBA_BACKUP_SRAM: return 32 * 1024;
|
||||
case GBA_BACKUP_FLASH_64K: return 64 * 1024;
|
||||
case GBA_BACKUP_FLASH_128K: return 128 * 1024;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
INT32 GbaCoreLoadBattery(GbaCore *core, const UINT8 *data, size_t size)
|
||||
{
|
||||
if (core == NULL || data == NULL || size > GBA_BATTERY_CAPACITY)
|
||||
return 1;
|
||||
memset(core->state.mem.cart_backup, 0xff, GBA_BATTERY_CAPACITY);
|
||||
memcpy(core->state.mem.cart_backup, data, size);
|
||||
core->state.cart.backup_is_dirty = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 GbaCoreBatteryDirty(const GbaCore *core)
|
||||
{
|
||||
return core != NULL && core->state.cart.backup_is_dirty;
|
||||
}
|
||||
|
||||
void GbaCoreClearBatteryDirty(GbaCore *core)
|
||||
{
|
||||
if (core != NULL) core->state.cart.backup_is_dirty = false;
|
||||
}
|
||||
|
||||
size_t GbaCoreStateSize()
|
||||
{
|
||||
return sizeof(gba_t);
|
||||
}
|
||||
|
||||
INT32 GbaCoreSaveState(const GbaCore *core, void *data, size_t size)
|
||||
{
|
||||
if (core == NULL || data == NULL || size < sizeof(gba_t))
|
||||
return 1;
|
||||
memcpy(data, &core->state, sizeof(gba_t));
|
||||
UINT8 *state = (UINT8 *)data;
|
||||
#define GBA_CLEAR_STATE_FIELD(type, base, field) memset(state + (base) + offsetof(type, field), 0, sizeof(((type *)0)->field))
|
||||
const size_t mem = offsetof(gba_t, mem);
|
||||
const size_t cpu = offsetof(gba_t, cpu);
|
||||
GBA_CLEAR_STATE_FIELD(gba_mem_t, mem, bios);
|
||||
GBA_CLEAR_STATE_FIELD(gba_mem_t, mem, cart_rom);
|
||||
GBA_CLEAR_STATE_FIELD(gba_mem_t, mem, cart_backup);
|
||||
GBA_CLEAR_STATE_FIELD(gba_t, 0, framebuffer);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, user_data);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, log_cmp_file);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, read8);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, read16);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, read32);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, read16_seq);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, read32_seq);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, write8);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, write16);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, write32);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, coprocessor_read);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, coprocessor_write);
|
||||
GBA_CLEAR_STATE_FIELD(arm7_t, cpu, trigger_breakpoint);
|
||||
#undef GBA_CLEAR_STATE_FIELD
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 GbaCoreLoadState(GbaCore *core, const void *data, size_t size, INT32 preserveAudio)
|
||||
{
|
||||
if (core == NULL || data == NULL || size < sizeof(gba_t) || core->rom == NULL)
|
||||
return 1;
|
||||
UINT8 battery[GBA_BATTERY_CAPACITY];
|
||||
memcpy(battery, core->state.mem.cart_backup, sizeof(battery));
|
||||
memcpy(&core->state, data, sizeof(gba_t));
|
||||
memcpy(core->state.mem.cart_backup, battery, sizeof(battery));
|
||||
GbaCoreApplyCartridgeFeatures(core);
|
||||
GbaCoreRebind(core);
|
||||
if (!preserveAudio)
|
||||
GbaCoreClearAudio(core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GbaCoreRebind(GbaCore *core)
|
||||
{
|
||||
if (core == NULL)
|
||||
return;
|
||||
core->host.rom_data = core->rom;
|
||||
core->host.rom_size = core->romSize;
|
||||
core->host.bios_data = core->externalBiosLoaded ? core->externalBios : NULL;
|
||||
core->host.bios_size = core->externalBiosLoaded ? sizeof(core->externalBios) : 0;
|
||||
gba_ptrs_init(&core->state, &core->scratch, core->rom);
|
||||
core->state.cpu.trigger_breakpoint = gba_cpu_trigger_breakpoint;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
// FBNeo GBA core host API.
|
||||
// Core implementation derived from SkyEmu/Cult-of-GBA; see license.txt.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef GBA_CORE_H
|
||||
#define GBA_CORE_H
|
||||
|
||||
#ifndef GBA_STANDALONE_TYPES
|
||||
#include "burn.h"
|
||||
#else
|
||||
#include <stdint.h>
|
||||
typedef uint8_t UINT8;
|
||||
typedef int8_t INT8;
|
||||
typedef int16_t INT16;
|
||||
typedef uint16_t UINT16;
|
||||
typedef int32_t INT32;
|
||||
typedef uint32_t UINT32;
|
||||
typedef int64_t INT64;
|
||||
typedef uint64_t UINT64;
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
|
||||
#define GBA_WIDTH 240
|
||||
#define GBA_HEIGHT 160
|
||||
#define GBA_MASTER_CLOCK 16777216
|
||||
#define GBA_BATTERY_CAPACITY (128 * 1024)
|
||||
#define GBA_SOLAR_LEVEL_MAX 10
|
||||
|
||||
struct GbaCore;
|
||||
|
||||
enum GbaButton {
|
||||
GBA_BUTTON_A = 0,
|
||||
GBA_BUTTON_B,
|
||||
GBA_BUTTON_SELECT,
|
||||
GBA_BUTTON_START,
|
||||
GBA_BUTTON_RIGHT,
|
||||
GBA_BUTTON_LEFT,
|
||||
GBA_BUTTON_UP,
|
||||
GBA_BUTTON_DOWN,
|
||||
GBA_BUTTON_R,
|
||||
GBA_BUTTON_L,
|
||||
};
|
||||
|
||||
enum GbaCartridgeFeature {
|
||||
GBA_CART_RTC = 1 << 0,
|
||||
GBA_CART_SOLAR = 1 << 1,
|
||||
GBA_CART_RUMBLE = 1 << 2,
|
||||
GBA_CART_GYRO = 1 << 3,
|
||||
GBA_CART_TILT = 1 << 4,
|
||||
};
|
||||
|
||||
struct GbaInput {
|
||||
UINT16 buttons;
|
||||
UINT8 solar;
|
||||
INT32 gyroZ;
|
||||
INT32 tiltX;
|
||||
INT32 tiltY;
|
||||
};
|
||||
|
||||
INT32 GbaMotionAxisToInput(UINT16 axis);
|
||||
UINT8 GbaSolarLevelToInput(UINT8 level);
|
||||
UINT8 GbaSolarLegacyToLevel(UINT16 legacy);
|
||||
|
||||
struct GbaRtcSeed {
|
||||
UINT16 year;
|
||||
UINT8 month;
|
||||
UINT8 day;
|
||||
UINT8 weekday;
|
||||
UINT8 hour;
|
||||
UINT8 minute;
|
||||
UINT8 second;
|
||||
};
|
||||
|
||||
INT32 GbaCoreInit(GbaCore **core);
|
||||
void GbaCoreExit(GbaCore **core);
|
||||
INT32 GbaCoreLoadRom(GbaCore *core, const UINT8 *rom, size_t romSize, const GbaRtcSeed *rtcSeed);
|
||||
INT32 GbaCoreLoadBios(GbaCore *core, const UINT8 *bios, size_t biosSize);
|
||||
INT32 GbaCoreReset(GbaCore *core);
|
||||
void GbaCoreSetInput(GbaCore *core, const GbaInput *input);
|
||||
INT32 GbaCoreConfigureAudio(GbaCore *core, double sourceRate, INT32 outputFrames, INT32 captureAudio);
|
||||
INT32 GbaCoreRunFrame(GbaCore *core);
|
||||
UINT32 GbaCoreGetCartridgeFeatures(const GbaCore *core);
|
||||
UINT8 GbaCoreGetRumbleOutput(const GbaCore *core);
|
||||
|
||||
const UINT32* GbaCoreGetFramebuffer(const GbaCore* core);
|
||||
UINT32 GbaCoreGetFramebufferPitch();
|
||||
INT32 GbaCoreRenderAudio(GbaCore *core, INT16 *stereo, INT32 frames);
|
||||
void GbaCoreClearAudio(GbaCore *core);
|
||||
|
||||
UINT8* GbaCoreGetBatteryData(GbaCore* core);
|
||||
const UINT8* GbaCoreGetBatteryDataConst(const GbaCore* core);
|
||||
size_t GbaCoreGetBatteryCapacity();
|
||||
size_t GbaCoreGetBatterySize(const GbaCore *core);
|
||||
INT32 GbaCoreLoadBattery(GbaCore *core, const UINT8 *data, size_t size);
|
||||
INT32 GbaCoreBatteryDirty(const GbaCore *core);
|
||||
void GbaCoreClearBatteryDirty(GbaCore *core);
|
||||
|
||||
size_t GbaCoreStateSize();
|
||||
INT32 GbaCoreSaveState(const GbaCore *core, void *data, size_t size);
|
||||
INT32 GbaCoreLoadState(GbaCore *core, const void *data, size_t size, INT32 preserveAudio = 0);
|
||||
void GbaCoreRebind(GbaCore *core);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,162 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef GBA_HOST_H
|
||||
#define GBA_HOST_H
|
||||
|
||||
#ifndef GBA_STANDALONE_TYPES
|
||||
#include "burn.h"
|
||||
#else
|
||||
#include "gba.h"
|
||||
#endif
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||
#define SB_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#define SB_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#elif defined(_MSC_VER)
|
||||
#define FORCE_INLINE __forceinline
|
||||
#define SB_UNLIKELY(x) (x)
|
||||
#define SB_LIKELY(x) (x)
|
||||
#else
|
||||
#define FORCE_INLINE inline
|
||||
#define SB_UNLIKELY(x) (x)
|
||||
#define SB_LIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#define SB_FILE_PATH_SIZE 1024
|
||||
#define SB_BFE(VALUE, BITOFFSET, SIZE) (((VALUE) >> (BITOFFSET)) & ((1llu << (SIZE)) - 1))
|
||||
#define SB_AUDIO_RING_BUFFER_SIZE (2048 * 8)
|
||||
#define SE_NUM_KEYBINDS 36
|
||||
#define SE_KEY_A 0
|
||||
#define SE_KEY_B 1
|
||||
#define SE_KEY_X 2
|
||||
#define SE_KEY_Y 3
|
||||
#define SE_KEY_UP 4
|
||||
#define SE_KEY_DOWN 5
|
||||
#define SE_KEY_LEFT 6
|
||||
#define SE_KEY_RIGHT 7
|
||||
#define SE_KEY_L 8
|
||||
#define SE_KEY_R 9
|
||||
#define SE_KEY_START 10
|
||||
#define SE_KEY_SELECT 11
|
||||
#define SB_MODE_PAUSE 0
|
||||
|
||||
typedef struct {
|
||||
float inputs[SE_NUM_KEYBINDS];
|
||||
float touch_pos[2];
|
||||
float rumble;
|
||||
float solar_sensor;
|
||||
INT32 gyro_z;
|
||||
INT32 tilt_x;
|
||||
INT32 tilt_y;
|
||||
} sb_joy_t;
|
||||
|
||||
typedef struct {
|
||||
INT16 data[SB_AUDIO_RING_BUFFER_SIZE];
|
||||
UINT32 read_ptr;
|
||||
UINT32 write_ptr;
|
||||
} sb_ring_buffer_t;
|
||||
|
||||
static FORCE_INLINE UINT32 sb_ring_buffer_size(sb_ring_buffer_t* buff)
|
||||
{
|
||||
if (buff->read_ptr > SB_AUDIO_RING_BUFFER_SIZE) {
|
||||
buff->write_ptr -= SB_AUDIO_RING_BUFFER_SIZE;
|
||||
buff->read_ptr -= SB_AUDIO_RING_BUFFER_SIZE;
|
||||
}
|
||||
return (buff->write_ptr - buff->read_ptr) % SB_AUDIO_RING_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
INT32 run_mode;
|
||||
INT32 step_instructions;
|
||||
INT32 step_frames;
|
||||
bool rom_loaded;
|
||||
INT32 system;
|
||||
sb_joy_t joy;
|
||||
sb_joy_t prev_frame_joy;
|
||||
INT32 frame;
|
||||
bool render_frame;
|
||||
bool capture_audio;
|
||||
double audio_sample_rate;
|
||||
sb_ring_buffer_t audio_ring_buff;
|
||||
UINT32 frames_since_rewind_push;
|
||||
char save_file_path[SB_FILE_PATH_SIZE];
|
||||
float screen_ghosting_strength;
|
||||
size_t rom_size;
|
||||
UINT8* rom_data;
|
||||
const UINT8* bios_data;
|
||||
size_t bios_size;
|
||||
char rom_path[SB_FILE_PATH_SIZE];
|
||||
} sb_emu_state_t;
|
||||
|
||||
typedef struct {
|
||||
bool read_since_reset;
|
||||
bool read_in_tick;
|
||||
bool write_since_reset;
|
||||
bool write_in_tick;
|
||||
bool trigger_breakpoint;
|
||||
} sb_debug_mmio_access_t;
|
||||
|
||||
typedef struct {
|
||||
UINT32 addr;
|
||||
const char* name;
|
||||
struct {
|
||||
UINT8 start;
|
||||
UINT8 size;
|
||||
const char* name;
|
||||
} bits[32];
|
||||
} mmio_reg_t;
|
||||
|
||||
static inline bool sb_path_has_file_ext(const char* path, const char* ext)
|
||||
{
|
||||
if (ext[0] == '*')
|
||||
ext++;
|
||||
if (ext[0] == '.')
|
||||
ext++;
|
||||
if (ext[0] == '*')
|
||||
return true;
|
||||
const size_t extLen = strlen(ext);
|
||||
const size_t pathLen = strlen(path);
|
||||
if (pathLen < extLen)
|
||||
return false;
|
||||
for (size_t i = 0; i < extLen; i++) {
|
||||
if (tolower((unsigned char)path[pathLen - extLen + i]) != tolower((unsigned char)ext[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static UINT8* sb_load_file_data(const char*, size_t* fileSize)
|
||||
{
|
||||
if (fileSize)
|
||||
*fileSize = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sb_free_file_data(UINT8 *data)
|
||||
{
|
||||
free(data);
|
||||
}
|
||||
|
||||
static sb_emu_state_t *gba_host_loading;
|
||||
|
||||
static bool se_load_bios_file(const char*, const char*, const char*, UINT8* data, size_t dataSize)
|
||||
{
|
||||
if (gba_host_loading == NULL || gba_host_loading->bios_data == NULL || gba_host_loading->bios_size != dataSize)
|
||||
return false;
|
||||
memcpy(data, gba_host_loading->bios_data, dataSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
static FILE* se_load_log_file(const char*, const char*)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Skyler "Sky" Saleh
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,9 @@
|
||||
# Nintendo Game Boy Advance drivers
|
||||
|
||||
group_desc = 'Nintendo Game Boy Advance drivers'
|
||||
group_srcs = [
|
||||
'gba.cpp',
|
||||
]
|
||||
drivers = {
|
||||
'd_gba.cpp': [],
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef GBA_RTC_H
|
||||
#define GBA_RTC_H
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define GBA_RTC_DAYS_1970_TO_2000 10957
|
||||
#define GBA_RTC_STATUS_MASK 0x6a
|
||||
|
||||
#if defined(GBA_STANDALONE)
|
||||
extern INT64 gba_rtc_test_now;
|
||||
#define GBA_RTC_NOW_SECONDS() (gba_rtc_test_now)
|
||||
#else
|
||||
#define GBA_RTC_NOW_SECONDS() ((INT64)time(NULL))
|
||||
#endif
|
||||
|
||||
enum gba_rtc_phase {
|
||||
GBA_RTC_IDLE = 0,
|
||||
GBA_RTC_COMMAND,
|
||||
GBA_RTC_RECEIVE,
|
||||
GBA_RTC_SEND,
|
||||
GBA_RTC_COMPLETE,
|
||||
};
|
||||
|
||||
enum gba_rtc_register {
|
||||
GBA_RTC_RESET = 0,
|
||||
GBA_RTC_UNUSED = 1,
|
||||
GBA_RTC_DATE_TIME = 2,
|
||||
GBA_RTC_FORCE_IRQ = 3,
|
||||
GBA_RTC_STATUS = 4,
|
||||
GBA_RTC_UNUSED2 = 5,
|
||||
GBA_RTC_TIME = 6,
|
||||
GBA_RTC_UNUSED3 = 7,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
UINT16 year;
|
||||
UINT8 month;
|
||||
UINT8 day;
|
||||
UINT8 weekday;
|
||||
UINT8 hour;
|
||||
UINT8 minute;
|
||||
UINT8 second;
|
||||
} gba_rtc_civil_t;
|
||||
|
||||
typedef struct {
|
||||
INT64 rtc_seconds;
|
||||
INT64 host_seconds;
|
||||
UINT8 status;
|
||||
UINT8 phase;
|
||||
UINT8 command;
|
||||
UINT8 command_register;
|
||||
UINT8 command_read;
|
||||
UINT8 bit_index;
|
||||
UINT8 byte_index;
|
||||
UINT8 byte_count;
|
||||
UINT8 buffer[7];
|
||||
UINT8 last_pins;
|
||||
UINT8 sio_out;
|
||||
} gba_rtc_t;
|
||||
|
||||
// Howard Hinnant's days_from_civil / civil_from_days (public domain). Proleptic
|
||||
// Gregorian, handles any date including 2100 (not a leap year).
|
||||
static FORCE_INLINE INT32 gba_rtc_days_from_civil(INT32 y, UINT32 m, UINT32 d)
|
||||
{
|
||||
y -= (m <= 2);
|
||||
INT32 era = (y >= 0 ? y : y - 399) / 400;
|
||||
UINT32 yoe = (UINT32)(y - era * 400);
|
||||
UINT32 doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
|
||||
UINT32 doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
|
||||
return era * 146097 + (INT32)doe - 719468;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_civil_from_days(INT32 z, INT32 *y, UINT32 *m, UINT32 *d)
|
||||
{
|
||||
z += 719468;
|
||||
INT32 era = (z >= 0 ? z : z - 146096) / 146097;
|
||||
UINT32 doe = (UINT32)(z - era * 146097);
|
||||
UINT32 yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
UINT32 y0 = yoe + (UINT32)era * 400;
|
||||
UINT32 doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
UINT32 mp = (5 * doy + 2) / 153;
|
||||
*d = doy - (153 * mp + 2) / 5 + 1;
|
||||
*m = mp + (mp < 10 ? 3 : -9);
|
||||
*y = (INT32)y0 + (*m <= 2);
|
||||
}
|
||||
|
||||
static FORCE_INLINE INT64 gba_rtc_civil_to_seconds(const gba_rtc_civil_t *c)
|
||||
{
|
||||
INT32 days = gba_rtc_days_from_civil((INT32)c->year, c->month, c->day) - GBA_RTC_DAYS_1970_TO_2000;
|
||||
return (INT64)days * 86400 + c->hour * 3600 + c->minute * 60 + c->second;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_seconds_to_civil(INT64 sec, gba_rtc_civil_t *c)
|
||||
{
|
||||
INT64 day = sec / 86400;
|
||||
INT32 into_day = (INT32)(sec - day * 86400);
|
||||
if (into_day < 0) { into_day += 86400; day -= 1; }
|
||||
INT32 y;
|
||||
UINT32 m, d;
|
||||
gba_rtc_civil_from_days((INT32)day + GBA_RTC_DAYS_1970_TO_2000, &y, &m, &d);
|
||||
if (y < 2000) y = 2000 + ((y - 2000) % 100 + 100) % 100;
|
||||
else if (y > 2099) y = 2000 + ((y - 2000) % 100 + 100) % 100;
|
||||
c->year = (UINT16)y;
|
||||
c->month = (UINT8)m;
|
||||
c->day = (UINT8)d;
|
||||
c->weekday = (UINT8)(((day % 7) + 7 + 6) % 7); // 2000-01-01 = Saturday (6, 0=Sun)
|
||||
c->hour = (UINT8)(into_day / 3600);
|
||||
c->minute = (UINT8)((into_day % 3600) / 60);
|
||||
c->second = (UINT8)(into_day % 60);
|
||||
}
|
||||
|
||||
static FORCE_INLINE INT64 gba_rtc_current_seconds(const gba_rtc_t *rtc)
|
||||
{
|
||||
return rtc->rtc_seconds + (GBA_RTC_NOW_SECONDS() - rtc->host_seconds);
|
||||
}
|
||||
|
||||
static FORCE_INLINE UINT8 gba_rtc_bcd_encode(UINT8 value)
|
||||
{
|
||||
return (value % 10) | ((value / 10) << 4);
|
||||
}
|
||||
|
||||
static FORCE_INLINE INT32 gba_rtc_bcd_decode(UINT8 value, UINT8 maximum, UINT8 *result)
|
||||
{
|
||||
UINT8 low = value & 0x0f;
|
||||
UINT8 high = (value >> 4) & 0x0f;
|
||||
if (low > 9 || high > 9) return 1;
|
||||
UINT8 decoded = high * 10 + low;
|
||||
if (decoded > maximum) return 1;
|
||||
*result = decoded;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCE_INLINE UINT8 gba_rtc_hour_encode(UINT8 hour_24, UINT8 status)
|
||||
{
|
||||
if (status & 0x40) return gba_rtc_bcd_encode(hour_24);
|
||||
return gba_rtc_bcd_encode(hour_24 % 12) | (hour_24 >= 12 ? 0x80 : 0);
|
||||
}
|
||||
|
||||
static FORCE_INLINE INT32 gba_rtc_hour_decode(UINT8 status, UINT8 value, UINT8 *hour)
|
||||
{
|
||||
if (status & 0x40) {
|
||||
if (value & 0xc0) return 1;
|
||||
return gba_rtc_bcd_decode(value, 23, hour);
|
||||
}
|
||||
UINT8 decoded;
|
||||
if (gba_rtc_bcd_decode(value & 0x3f, 11, &decoded)) return 1;
|
||||
*hour = decoded + ((value & 0x80) ? 12 : 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_transport_reset(gba_rtc_t *rtc)
|
||||
{
|
||||
rtc->phase = GBA_RTC_IDLE;
|
||||
rtc->command = 0;
|
||||
rtc->command_register = 0;
|
||||
rtc->command_read = 0;
|
||||
rtc->bit_index = 0;
|
||||
rtc->byte_index = 0;
|
||||
rtc->byte_count = 0;
|
||||
memset(rtc->buffer, 0, sizeof(rtc->buffer));
|
||||
rtc->sio_out = 1;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_cold_init(gba_rtc_t *rtc, const gba_rtc_civil_t *seed)
|
||||
{
|
||||
memset(rtc, 0, sizeof(*rtc));
|
||||
gba_rtc_civil_t fallback = { 2000, 1, 1, 0, 0, 0, 0 };
|
||||
const gba_rtc_civil_t *s = (seed && seed->year >= 2000 && seed->year <= 2099 &&
|
||||
seed->month >= 1 && seed->month <= 12 && seed->day >= 1 &&
|
||||
seed->day <= 31 && seed->hour <= 23 && seed->minute <= 59 && seed->second <= 59) ? seed : &fallback;
|
||||
rtc->rtc_seconds = gba_rtc_civil_to_seconds(s);
|
||||
rtc->host_seconds = GBA_RTC_NOW_SECONDS();
|
||||
rtc->status = 0x40;
|
||||
gba_rtc_transport_reset(rtc);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_reanchor(gba_rtc_t *rtc, INT64 rtc_seconds)
|
||||
{
|
||||
rtc->rtc_seconds = rtc_seconds;
|
||||
rtc->host_seconds = GBA_RTC_NOW_SECONDS();
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_latch_read(gba_rtc_t *rtc)
|
||||
{
|
||||
memset(rtc->buffer, 0xff, sizeof(rtc->buffer));
|
||||
switch (rtc->command_register) {
|
||||
case GBA_RTC_STATUS:
|
||||
rtc->byte_count = 1;
|
||||
rtc->buffer[0] = rtc->status;
|
||||
break;
|
||||
case GBA_RTC_DATE_TIME: {
|
||||
gba_rtc_civil_t c;
|
||||
gba_rtc_seconds_to_civil(gba_rtc_current_seconds(rtc), &c);
|
||||
rtc->byte_count = 7;
|
||||
rtc->buffer[0] = gba_rtc_bcd_encode((UINT8)(c.year % 100));
|
||||
rtc->buffer[1] = gba_rtc_bcd_encode(c.month);
|
||||
rtc->buffer[2] = gba_rtc_bcd_encode(c.day);
|
||||
rtc->buffer[3] = gba_rtc_bcd_encode(c.weekday);
|
||||
rtc->buffer[4] = gba_rtc_hour_encode(c.hour, rtc->status);
|
||||
rtc->buffer[5] = gba_rtc_bcd_encode(c.minute);
|
||||
rtc->buffer[6] = gba_rtc_bcd_encode(c.second);
|
||||
break;
|
||||
}
|
||||
case GBA_RTC_TIME: {
|
||||
gba_rtc_civil_t c;
|
||||
gba_rtc_seconds_to_civil(gba_rtc_current_seconds(rtc), &c);
|
||||
rtc->byte_count = 3;
|
||||
rtc->buffer[0] = gba_rtc_hour_encode(c.hour, rtc->status);
|
||||
rtc->buffer[1] = gba_rtc_bcd_encode(c.minute);
|
||||
rtc->buffer[2] = gba_rtc_bcd_encode(c.second);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rtc->byte_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE INT32 gba_rtc_commit_datetime(gba_rtc_t *rtc)
|
||||
{
|
||||
gba_rtc_civil_t c;
|
||||
gba_rtc_seconds_to_civil(gba_rtc_current_seconds(rtc), &c);
|
||||
UINT8 year;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[0], 99, &year)) return 1;
|
||||
c.year = 2000 + year;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[1], 12, &c.month) || c.month == 0) return 1;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[2], 31, &c.day) || c.day == 0) return 1;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[3], 6, &c.weekday)) return 1;
|
||||
if (gba_rtc_hour_decode(rtc->status, rtc->buffer[4], &c.hour)) return 1;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[5], 59, &c.minute)) return 1;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[6], 59, &c.second)) return 1;
|
||||
if (c.year < 2000 || c.year > 2099 || c.month < 1 || c.month > 12 ||
|
||||
c.day < 1 || c.day > 31 || c.hour > 23) return 1;
|
||||
gba_rtc_reanchor(rtc, gba_rtc_civil_to_seconds(&c));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCE_INLINE INT32 gba_rtc_commit_time(gba_rtc_t *rtc)
|
||||
{
|
||||
gba_rtc_civil_t c;
|
||||
gba_rtc_seconds_to_civil(gba_rtc_current_seconds(rtc), &c);
|
||||
if (gba_rtc_hour_decode(rtc->status, rtc->buffer[0], &c.hour)) return 1;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[1], 59, &c.minute)) return 1;
|
||||
if (gba_rtc_bcd_decode(rtc->buffer[2], 59, &c.second)) return 1;
|
||||
gba_rtc_reanchor(rtc, gba_rtc_civil_to_seconds(&c));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_commit_write(gba_rtc_t *rtc)
|
||||
{
|
||||
switch (rtc->command_register) {
|
||||
case GBA_RTC_STATUS:
|
||||
rtc->status = rtc->buffer[0] & GBA_RTC_STATUS_MASK;
|
||||
break;
|
||||
case GBA_RTC_DATE_TIME:
|
||||
gba_rtc_commit_datetime(rtc);
|
||||
break;
|
||||
case GBA_RTC_TIME:
|
||||
gba_rtc_commit_time(rtc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE UINT8 gba_rtc_reverse8(UINT8 value)
|
||||
{
|
||||
value = (value >> 4) | (value << 4);
|
||||
value = ((value & 0x33) << 2) | ((value & 0xcc) >> 2);
|
||||
return ((value & 0x55) << 1) | ((value & 0xaa) >> 1);
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_decode_command(gba_rtc_t *rtc)
|
||||
{
|
||||
UINT8 command = rtc->command;
|
||||
if ((command & 0x0f) != 0x06 && (command & 0xf0) == 0x60) command = gba_rtc_reverse8(command);
|
||||
if ((command & 0x0f) != 0x06) {
|
||||
rtc->phase = GBA_RTC_COMPLETE;
|
||||
return;
|
||||
}
|
||||
|
||||
rtc->command = command;
|
||||
rtc->command_register = (command >> 4) & 7;
|
||||
rtc->command_read = (command >> 7) & 1;
|
||||
rtc->bit_index = 0;
|
||||
rtc->byte_index = 0;
|
||||
memset(rtc->buffer, 0, sizeof(rtc->buffer));
|
||||
|
||||
if (rtc->command_register == GBA_RTC_RESET) {
|
||||
if (!rtc->command_read) rtc->status = 0;
|
||||
rtc->phase = GBA_RTC_COMPLETE;
|
||||
return;
|
||||
}
|
||||
if (rtc->command_register == GBA_RTC_FORCE_IRQ || rtc->command_register == GBA_RTC_UNUSED ||
|
||||
rtc->command_register == GBA_RTC_UNUSED2 || rtc->command_register == GBA_RTC_UNUSED3) {
|
||||
rtc->phase = GBA_RTC_COMPLETE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rtc->command_read) {
|
||||
gba_rtc_latch_read(rtc);
|
||||
rtc->phase = rtc->byte_count ? GBA_RTC_SEND : GBA_RTC_COMPLETE;
|
||||
} else {
|
||||
rtc->byte_count = rtc->command_register == GBA_RTC_STATUS ? 1 :
|
||||
rtc->command_register == GBA_RTC_DATE_TIME ? 7 :
|
||||
rtc->command_register == GBA_RTC_TIME ? 3 : 0;
|
||||
rtc->phase = rtc->byte_count ? GBA_RTC_RECEIVE : GBA_RTC_COMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_sample_input(gba_rtc_t *rtc, UINT8 sio)
|
||||
{
|
||||
if (rtc->phase == GBA_RTC_COMMAND) {
|
||||
rtc->command |= (sio & 1) << rtc->bit_index;
|
||||
if (++rtc->bit_index == 8) gba_rtc_decode_command(rtc);
|
||||
return;
|
||||
}
|
||||
if (rtc->phase != GBA_RTC_RECEIVE) return;
|
||||
|
||||
rtc->buffer[rtc->byte_index] |= (sio & 1) << rtc->bit_index;
|
||||
if (++rtc->bit_index < 8) return;
|
||||
rtc->bit_index = 0;
|
||||
if (++rtc->byte_index < rtc->byte_count) return;
|
||||
gba_rtc_commit_write(rtc);
|
||||
rtc->phase = GBA_RTC_COMPLETE;
|
||||
}
|
||||
|
||||
static FORCE_INLINE void gba_rtc_shift_output(gba_rtc_t *rtc)
|
||||
{
|
||||
if (rtc->phase != GBA_RTC_SEND) {
|
||||
rtc->sio_out = 1;
|
||||
return;
|
||||
}
|
||||
rtc->sio_out = (rtc->buffer[rtc->byte_index] >> rtc->bit_index) & 1;
|
||||
if (++rtc->bit_index < 8) return;
|
||||
rtc->bit_index = 0;
|
||||
if (++rtc->byte_index < rtc->byte_count) return;
|
||||
rtc->phase = GBA_RTC_COMPLETE;
|
||||
}
|
||||
|
||||
static FORCE_INLINE UINT8 gba_rtc_update_pins(gba_rtc_t *rtc, UINT8 pins)
|
||||
{
|
||||
UINT8 old = rtc->last_pins;
|
||||
UINT8 cs = (pins >> 2) & 1;
|
||||
UINT8 old_cs = (old >> 2) & 1;
|
||||
UINT8 sck = pins & 1;
|
||||
UINT8 old_sck = old & 1;
|
||||
|
||||
if (!cs) {
|
||||
gba_rtc_transport_reset(rtc);
|
||||
rtc->last_pins = pins;
|
||||
return rtc->sio_out;
|
||||
}
|
||||
if (!old_cs) {
|
||||
gba_rtc_transport_reset(rtc);
|
||||
rtc->phase = GBA_RTC_COMMAND;
|
||||
rtc->last_pins = pins;
|
||||
return rtc->sio_out;
|
||||
}
|
||||
if (!old_sck && sck) gba_rtc_sample_input(rtc, (old >> 1) & 1);
|
||||
if (old_sck && !sck) gba_rtc_shift_output(rtc);
|
||||
rtc->last_pins = pins;
|
||||
return rtc->sio_out;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -8,5 +8,5 @@ perl cave_tile_func.pl -o ../../../projectfiles/visualstudio-2010/generated/cave
|
||||
perl neo_sprite_func.pl -o ../../../projectfiles/visualstudio-2010/generated/neo_sprite_func.h
|
||||
perl psikyo_tile_func.pl -o ../../../projectfiles/visualstudio-2010/generated/psikyo_tile_func.h
|
||||
perl toa_gp9001_func.pl -o ../../../projectfiles/visualstudio-2010/generated/toa_gp9001_func.h
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2010/generated/driverlist.h -l ../../../projectfiles/visualstudio-2010/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2010/generated/driverlist.h -l ../../../projectfiles/visualstudio-2010/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/gba ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv
|
||||
|
||||
@@ -8,4 +8,4 @@ perl cave_tile_func.pl -o ../../../projectfiles/visualstudio-2015/generated/cave
|
||||
perl neo_sprite_func.pl -o ../../../projectfiles/visualstudio-2015/generated/neo_sprite_func.h
|
||||
perl psikyo_tile_func.pl -o ../../../projectfiles/visualstudio-2015/generated/psikyo_tile_func.h
|
||||
perl toa_gp9001_func.pl -o ../../../projectfiles/visualstudio-2015/generated/toa_gp9001_func.h
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2015/generated/driverlist.h -l ../../../projectfiles/visualstudio-2015/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2015/generated/driverlist.h -l ../../../projectfiles/visualstudio-2015/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/gba ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
@@ -8,4 +8,4 @@ perl cave_tile_func.pl -o ../../../projectfiles/visualstudio-2019/generated/cave
|
||||
perl neo_sprite_func.pl -o ../../../projectfiles/visualstudio-2019/generated/neo_sprite_func.h
|
||||
perl psikyo_tile_func.pl -o ../../../projectfiles/visualstudio-2019/generated/psikyo_tile_func.h
|
||||
perl toa_gp9001_func.pl -o ../../../projectfiles/visualstudio-2019/generated/toa_gp9001_func.h
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2019/generated/driverlist.h -l ../../../projectfiles/visualstudio-2019/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2019/generated/driverlist.h -l ../../../projectfiles/visualstudio-2019/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/gba ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
@@ -8,4 +8,4 @@ perl cave_tile_func.pl -o ../../../projectfiles/visualstudio-2022/generated/cave
|
||||
perl neo_sprite_func.pl -o ../../../projectfiles/visualstudio-2022/generated/neo_sprite_func.h
|
||||
perl psikyo_tile_func.pl -o ../../../projectfiles/visualstudio-2022/generated/psikyo_tile_func.h
|
||||
perl toa_gp9001_func.pl -o ../../../projectfiles/visualstudio-2022/generated/toa_gp9001_func.h
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2022/generated/driverlist.h -l ../../../projectfiles/visualstudio-2022/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2022/generated/driverlist.h -l ../../../projectfiles/visualstudio-2022/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/gba ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
@@ -8,4 +8,4 @@ perl cave_tile_func.pl -o ../../../projectfiles/visualstudio-2026/generated/cave
|
||||
perl neo_sprite_func.pl -o ../../../projectfiles/visualstudio-2026/generated/neo_sprite_func.h
|
||||
perl psikyo_tile_func.pl -o ../../../projectfiles/visualstudio-2026/generated/psikyo_tile_func.h
|
||||
perl toa_gp9001_func.pl -o ../../../projectfiles/visualstudio-2026/generated/toa_gp9001_func.h
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2026/generated/driverlist.h -l ../../../projectfiles/visualstudio-2026/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
perl gamelist.pl -o ../../../projectfiles/visualstudio-2026/generated/driverlist.h -l ../../../projectfiles/visualstudio-2026/generated/gamelist.txt ../../burn/drv/atari ../../burn/drv/capcom ../../burn/drv/cave ../../burn/drv/coleco ../../burn/drv/cps3 ../../burn/drv/dataeast ../../burn/drv/galaxian ../../burn/drv/gba ../../burn/drv/irem ../../burn/drv/konami ../../burn/drv/megadrive ../../burn/drv/midway ../../burn/drv/msx ../../burn/drv/neogeo ../../burn/drv/pce ../../burn/drv/pgm ../../burn/drv/pgm2 ../../burn/drv/pst90s ../../burn/drv/pre90s ../../burn/drv/psikyo ../../burn/drv/sega ../../burn/drv/sg1000 ../../burn/drv/spectrum ../../burn/drv/taito ../../burn/drv/toaplan ../../burn/drv/sms ../../burn/drv/nes ../../burn/drv/snes ../../burn/drv/channelf ../../burn/drv
|
||||
Reference in new issue
Block a user