Compare commits

...
18 Commits
Author SHA1 Message Date
Bobby Dilley 88e1628382 Merge branch 'bobby/outrun-chihiro' 2026-02-24 21:59:38 +00:00
Bobby Dilley 6918990746 Update changelog 2026-02-24 21:59:35 +00:00
Bobby Dilley 87dccf51a4 Undo changes to resolution 2026-02-24 21:51:47 +00:00
Bobby Dilley 81d9185227 Fix outrun 4:3 in a different way@ 2026-02-24 21:51:47 +00:00
Bobby Dilley 510d13398e Try to render like chihiro in 640x480 2026-02-24 21:51:47 +00:00
dkeruza-neo 973cfb7058 refactor: delegate strdup'd command string buffer freeing to compileShader and remove a redundant free. 2026-02-17 22:51:30 -05:00
dkeruza c47a4a6889 Merge pull request #115 from RoseGunsDays/master
Add support for MJ4 Rev. A, MJ4 Rev. F and MJ4 Evolution Rev. B
2026-02-17 22:44:16 -05:00
dkeruza 4d44d95397 Merge pull request #114 from Rolel/master
Fix a typo in config file
2026-02-16 22:15:41 -05:00
SBH da0316d5a6 Added support for MJ4 Evolution Rev. B 2026-02-16 14:29:45 -07:00
SBH 9179d0e282 Change MJ4 touch panel functions to use GROUP_MJ4 2026-02-16 14:15:14 -07:00
SBH d5e370240c Merge branch 'master' into master 2026-02-16 13:24:19 -07:00
SBH 01c2c5b765 Added MJ4 Rev. F patches to resolution.c 2026-01-05 05:18:21 -07:00
SBH a0e504c4c9 Cleanup for real this time oops 2026-01-05 04:56:06 -07:00
SBH 3ad93675e0 guide.md cleanup 2026-01-05 04:37:12 -07:00
SBH d09c6c72e1 Cleanup + update guide.md 2026-01-05 04:21:46 -07:00
SBH 32759cd01d Added support for MJ4 Rev. A and MJ4 Rev. F 2026-01-05 04:09:54 -07:00
Rolel 42 f0e9a22b24 Merge pull request #3 from Rolel/Rolel-config-typo-patch
Fix a typo in config description
2025-12-28 16:35:35 +01:00
Rolel 42 cf33403979 Fix a typo in config description 2025-12-28 16:35:06 +01:00
13 changed files with 250 additions and 34 deletions
+13 -1
View File
@@ -2,6 +2,18 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [2.1.4]
### Added
- Force Outrun to render properly in 4:3 when resolution is set to 640x480
to match the chihiro version of the game for use on CRT cabinets.
## [2.1.3]
### Added
- MJ4 Rev. A, MJ4 Rev. F and MJ4 Evolution Rev. B support.
### Fixed
- Fixed a bug in the shader patching code that prevented the loader to compile shaders for non nVidia GPUs.
## [2.1.2] ## [2.1.2]
### Added ### Added
- Virtual Card file support for ID4 and ID5 (read the documentation). - Virtual Card file support for ID4 and ID5 (read the documentation).
@@ -169,4 +181,4 @@ All notable changes to this project will be documented in this file.
- Dynamic resolution patching allowing most games to scale properly in HD - Dynamic resolution patching allowing most games to scale properly in HD
- Original cabinet support with pass through of JVS and FFB - Original cabinet support with pass through of JVS and FFB
- Network play - Network play
- Both simple X11 and advanced evdev input system allowing for ready-to-play keyboard and mouse support or mapping of any controller - Both simple X11 and advanced evdev input system allowing for ready-to-play keyboard and mouse support or mapping of any controller
+4 -1
View File
@@ -36,8 +36,11 @@ The follow list of games are supported. It is worth noting that there are multip
| Let's Go Jungle | SBLU | DVP-0011 | ✓ | ✓ | ✓ | | | Let's Go Jungle | SBLU | DVP-0011 | ✓ | ✓ | ✓ | |
| Let's Go Jungle! Rev A | SBLU | DVP-0011A | ✓ | ✓ | ✓ | | | Let's Go Jungle! Rev A | SBLU | DVP-0011A | ✓ | ✓ | ✓ | |
| Let's Go Jungle Special | SBNR | DVP-0036 | ✓ | ✓ | ✓ | | | Let's Go Jungle Special | SBNR | DVP-0036 | ✓ | ✓ | ✓ | |
| SEGA Network Taisen Mahjong MJ4 | SBPN | DVP-0049G | ✓ | ✓ | ✓ | ✓ | | SEGA Network Taisen Mahjong MJ4 Rev A | SBPN | DVP-0049A | ✓ | ✓ | ✓ | ✓ |
| SEGA Network Taisen Mahjong MJ4 Rev F | SBPN | DVP-0049F | ✓ | ✓ | ✓ | ✓ |
| SEGA Network Taisen Mahjong MJ4 Rev G | SBPN | DVP-0049G | ✓ | ✓ | ✓ | ✓ |
| SEGA Network Taisen Mahjong MJ4 Evolution | SBTA | DVP-0081 | ✓ | ✓ | ✓ | ✓ | | SEGA Network Taisen Mahjong MJ4 Evolution | SBTA | DVP-0081 | ✓ | ✓ | ✓ | ✓ |
| SEGA Network Taisen Mahjong MJ4 Evolution Rev B | SBTA | DVP-0081B | ✓ | ✓ | ✓ | ✓ |
| Outrun 2 SP SDX | SBMB | DVP-0015 | ✓ | ✓ | ✓ | ✓ | | Outrun 2 SP SDX | SBMB | DVP-0015 | ✓ | ✓ | ✓ | ✓ |
| Outrun 2 SP SDX Rev A | SBMB | DVP-0015A | ✓ | ✓ | ✓ | ✓ | | Outrun 2 SP SDX Rev A | SBMB | DVP-0015A | ✓ | ✓ | ✓ | ✓ |
| Primeval Hunt | SBPP | DVP-0048 | ✓ | ✓ | ✓ | ✓ | | Primeval Hunt | SBPP | DVP-0048 | ✓ | ✓ | ✓ | ✓ |
+46 -9
View File
@@ -22,6 +22,8 @@ extern SDL_Window *sdlWindow;
int blitWidth = 0; int blitWidth = 0;
int blitHeight = 0; int blitHeight = 0;
int gameIsOutrunChihiroMode = 0;
int fboInitialized = false; int fboInitialized = false;
GLuint fboId = 0; GLuint fboId = 0;
GLuint fboTextureId = 0; GLuint fboTextureId = 0;
@@ -36,6 +38,30 @@ void initBlitting()
blitSetWidthandHeightSize(); blitSetWidthandHeightSize();
blitInitializeFbo(); blitInitializeFbo();
dest.gameScale = 1.0f; dest.gameScale = 1.0f;
if(gGrp == GROUP_OUTRUN && getConfig()->width == 640)
gameIsOutrunChihiroMode = 1;
}
/**
* If the game is outrun in 640x480 mode we force the game to write to out temp framebuffer directly
* to avoid the framebuffer of the window being too small and the edges getting clipped off. So we
* hook glBindFramebuffer and if the game tries to bind the default framebuffer, we bind our FBO instead and
* set the viewport to 800x480 so the game renders to our FBO. Then in blitStretch we copy from our FBO to the
* screen with the correct aspect ratio.
*/
void glBindFramebufferEXT(GLenum target, GLuint framebuffer) {
void (*_glBindFramebufferEXT)(GLenum target, GLuint framebuffer) = dlsym(RTLD_NEXT, "glBindFramebufferEXT");
if(target == GL_FRAMEBUFFER_EXT && framebuffer == 0 && fboInitialized && gameIsOutrunChihiroMode)
{
glBindFramebuffer(GL_FRAMEBUFFER, fboId);
glViewport(0, 0, 800, 480);
glClear(GL_COLOR_BUFFER_BIT);
return;
}
_glBindFramebufferEXT(target, framebuffer);
} }
void blitSetWidthandHeightSize() void blitSetWidthandHeightSize()
@@ -58,7 +84,7 @@ void blitSetWidthandHeightSize()
blitWidth = 640; blitWidth = 640;
blitHeight = 480; blitHeight = 480;
} }
else if (gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE || gId == MJ4_REVG || gId == MJ4_EVO) else if (gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE || gGrp == GROUP_MJ4)
{ {
blitWidth = 1024; blitWidth = 1024;
blitHeight = 768; blitHeight = 768;
@@ -121,14 +147,18 @@ void blitStretch()
if (fboInitialized && fboId > 0 && fboTextureId > 0 && sdlWindow) if (fboInitialized && fboId > 0 && fboTextureId > 0 && sdlWindow)
{ {
SDL_GetWindowSizeInPixels(sdlWindow, &drawableW, &drawableH); SDL_GetWindowSizeInPixels(sdlWindow, &drawableW, &drawableH);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
glBlitFramebuffer(0, 0, blitWidth, blitHeight, 0, 0, blitWidth, blitHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
float gameAspect = (float)blitWidth / (float)blitHeight;
float windowAspect = (float)drawableW / (float)drawableH; float windowAspect = (float)drawableW / (float)drawableH;
float gameAspect = 4.0 / 3.0;
if(!gameIsOutrunChihiroMode)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId);
glBlitFramebuffer(0, 0, blitWidth, blitHeight, 0, 0, blitWidth, blitHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
gameAspect = (float)blitWidth / (float)blitHeight;
}
dest.W = drawableW; dest.W = drawableW;
dest.H = drawableH; dest.H = drawableH;
@@ -142,7 +172,7 @@ void blitStretch()
dest.H = (GLsizei)(drawableW / gameAspect); dest.H = (GLsizei)(drawableW / gameAspect);
dest.Y = (drawableH - dest.H) / 2; dest.Y = (drawableH - dest.H) / 2;
} }
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
@@ -151,7 +181,14 @@ void blitStretch()
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glReadBuffer(GL_COLOR_ATTACHMENT0); glReadBuffer(GL_COLOR_ATTACHMENT0);
glBlitFramebuffer(0, 0, blitWidth, blitHeight, dest.X, dest.Y, dest.X + dest.W, dest.Y + dest.H, GL_COLOR_BUFFER_BIT, GL_LINEAR); if(gameIsOutrunChihiroMode)
{
glBlitFramebuffer(80, 0, blitWidth - 80, blitHeight, dest.X, dest.Y, dest.X + dest.W, dest.Y + dest.H, GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
else
{
glBlitFramebuffer(0, 0, blitWidth, blitHeight, dest.X, dest.Y, dest.X + dest.W, dest.Y + dest.H, GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }
+4
View File
@@ -37,8 +37,11 @@
#define LETS_GO_JUNGLE 0xb1c8c901 // DVP-0011 #define LETS_GO_JUNGLE 0xb1c8c901 // DVP-0011
#define LETS_GO_JUNGLE_REVA 0xc697c4fb // DVP-0011A #define LETS_GO_JUNGLE_REVA 0xc697c4fb // DVP-0011A
#define LETS_GO_JUNGLE_SPECIAL 0x240beedc // DVP-0036A #define LETS_GO_JUNGLE_SPECIAL 0x240beedc // DVP-0036A
#define MJ4_REVA 0x6eb2a533 // DVP-0049A
#define MJ4_REVF 0x220ac11 // DVP-0049F
#define MJ4_REVG 0x57813a7 // DVP-0049G #define MJ4_REVG 0x57813a7 // DVP-0049G
#define MJ4_EVO 0xb785a0e9 // DVP-0081 #define MJ4_EVO 0xb785a0e9 // DVP-0081
#define MJ4_EVO_REVB 0x7f11d214 // DVP-0081B
#define OUTRUN_2_SP_SDX 0x92c196d5 // DVP-0015 #define OUTRUN_2_SP_SDX 0x92c196d5 // DVP-0015
#define OUTRUN_2_SP_SDX_REVA 0x4debd5f0 // DVP-0015A #define OUTRUN_2_SP_SDX_REVA 0x4debd5f0 // DVP-0015A
#define OUTRUN_2_SP_SDX_REVA_TEST 0x6b2d5c46 // DVP-0015A #define OUTRUN_2_SP_SDX_REVA_TEST 0x6b2d5c46 // DVP-0015A
@@ -133,6 +136,7 @@ typedef enum
GROUP_ID4_JAP, GROUP_ID4_JAP,
GROUP_ID5, GROUP_ID5,
GROUP_LGJ, GROUP_LGJ,
GROUP_MJ4,
GROUP_OUTRUN, GROUP_OUTRUN,
GROUP_OUTRUN_TEST, GROUP_OUTRUN_TEST,
GROUP_RAMBO, GROUP_RAMBO,
+1 -1
View File
@@ -124,7 +124,7 @@ void createDefaultIni(const char *filePath)
fprintf(file, "# Hacky way to make MJ4 and AxA work at prohibited times\nMJ4_ENABLED_ALL_THE_TIME = %s\n\n", fprintf(file, "# Hacky way to make MJ4 and AxA work at prohibited times\nMJ4_ENABLED_ALL_THE_TIME = %s\n\n",
defaults.mj4EnabledAtT ? "true" : "false"); defaults.mj4EnabledAtT ? "true" : "false");
fprintf(file, "# House of the dead 4 speed fix, set the frequency of your CPU in Ghz\nCPU_FREQ_GHZ = %.1f\n\n", defaults.cpuFreqGhz); fprintf(file, "# House of the dead 4 speed fix, set the frequency of your CPU in Ghz\nCPU_FREQ_GHZ = %.1f\n\n", defaults.cpuFreqGhz);
fprintf(file, "# Set to true if you want to chnge the way the guns are show in Rambo\n"); fprintf(file, "# Set to true if you want to change the way the guns are show in Rambo\n");
fprintf(file, "RAMBO_GUNS_SWITCH = false\n\n"); fprintf(file, "RAMBO_GUNS_SWITCH = false\n\n");
fprintf(file, "# Set to true to set the language in Chinese for ID5 DVP-0084 and DVP-0084A\n"); fprintf(file, "# Set to true to set the language in Chinese for ID5 DVP-0084 and DVP-0084A\n");
fprintf(file, "ID5_CHINESE_LANGUAGE = %s\n\n", defaults.id5ChineseLanguage ? "true" : "false"); fprintf(file, "ID5_CHINESE_LANGUAGE = %s\n\n", defaults.id5ChineseLanguage ? "true" : "false");
+5 -2
View File
@@ -32,8 +32,11 @@ static const GameData gameData[] = {
{LETS_GO_JUNGLE, "Let's Go Jungle! Lost on the Island of Spice!", "lgj", "DVP-0011", "SBLU", "2006", "1360x768", WORKING, SEGA_TYPE_3, SHOOTING, 1360, 768, GROUP_LGJ, 0, 0, 0, 0, 0, 0, YELLOW}, {LETS_GO_JUNGLE, "Let's Go Jungle! Lost on the Island of Spice!", "lgj", "DVP-0011", "SBLU", "2006", "1360x768", WORKING, SEGA_TYPE_3, SHOOTING, 1360, 768, GROUP_LGJ, 0, 0, 0, 0, 0, 0, YELLOW},
{LETS_GO_JUNGLE_REVA, "Let's Go Jungle! Lost on the Island of Spice! Rev A", "lgj-rev-a", "DVP-0011A", "SBLU", "2006", "1360x768", WORKING, SEGA_TYPE_3, SHOOTING, 1360, 768, GROUP_LGJ, 0, 0, 0, 0, 0, 0, YELLOW}, {LETS_GO_JUNGLE_REVA, "Let's Go Jungle! Lost on the Island of Spice! Rev A", "lgj-rev-a", "DVP-0011A", "SBLU", "2006", "1360x768", WORKING, SEGA_TYPE_3, SHOOTING, 1360, 768, GROUP_LGJ, 0, 0, 0, 0, 0, 0, YELLOW},
{LETS_GO_JUNGLE_SPECIAL, "Let's Go Jungle! Special!", "lgj-sp", "DVP-0036", "SBNR", "2007", "1024x768", WORKING, SEGA_TYPE_3, SHOOTING, 1024, 768, GROUP_LGJ, 1, 0, 0, 0, 0, 0, YELLOW}, {LETS_GO_JUNGLE_SPECIAL, "Let's Go Jungle! Special!", "lgj-sp", "DVP-0036", "SBNR", "2007", "1024x768", WORKING, SEGA_TYPE_3, SHOOTING, 1024, 768, GROUP_LGJ, 1, 0, 0, 0, 0, 0, YELLOW},
{MJ4_EVO, "SEGA Network Taisen Mahjong MJ4 Evolution", "mj4-evo", "DVP-0081", "SBTA", "2008", "1024x768", WORKING, SEGA_TYPE_3, MAHJONG, 1024, 768, -1, 0, 0, 0, 0, 0, 1, YELLOW}, {MJ4_EVO, "SEGA Network Taisen Mahjong MJ4 Evolution", "mj4-evo", "DVP-0081", "SBTA", "2010", "1024x768", WORKING, SEGA_TYPE_3, MAHJONG, 1024, 768, GROUP_MJ4, 0, 0, 0, 0, 0, 1, YELLOW},
{MJ4_REVG, "SEGA Network Taisen Mahjong MJ4", "mj4-rev-g", "DVP-0049G", "SBPN", "2007", "1024x768", WORKING, SEGA_TYPE_3, MAHJONG, 1024, 768, -1, 0, 0, 0, 0, 0, 1, YELLOW}, {MJ4_EVO_REVB, "SEGA Network Taisen Mahjong MJ4 Evolution Rev B", "mj4-evo-rev-b", "DVP-0081B", "SBTA", "2010", "1024x768", WORKING, SEGA_TYPE_3, MAHJONG, 1024, 768, GROUP_MJ4, 0, 0, 0, 0, 0, 1, YELLOW},
{MJ4_REVA, "SEGA Network Taisen Mahjong MJ4 Rev A", "mj4-rev-a", "DVP-0049A", "SBPN", "2007", "1024x768", WORKING, SEGA_TYPE_3, MAHJONG, 1024, 768, GROUP_MJ4, 0, 0, 0, 0, 0, 1, YELLOW},
{MJ4_REVF, "SEGA Network Taisen Mahjong MJ4 Rev F", "mj4-rev-f", "DVP-0049F", "SBPN", "2007", "1024x768", WORKING, SEGA_TYPE_3, MAHJONG, 1024, 768, GROUP_MJ4, 0, 0, 0, 0, 0, 1, YELLOW},
{MJ4_REVG, "SEGA Network Taisen Mahjong MJ4 Rev G", "mj4-rev-g", "DVP-0049G", "SBPN", "2007", "1024x768", WORKING, SEGA_TYPE_3, MAHJONG, 1024, 768, GROUP_MJ4, 0, 0, 0, 0, 0, 1, YELLOW},
{OUTRUN_2_SP_SDX, "Outrun 2 SP SDX", "outrun2", "DVP-0015", "SBMB", "2006", "800x480", WORKING, SEGA_TYPE_3, DRIVING, 800, 480, GROUP_OUTRUN, 0, 1, 1, 0, 0, 0, YELLOW}, {OUTRUN_2_SP_SDX, "Outrun 2 SP SDX", "outrun2", "DVP-0015", "SBMB", "2006", "800x480", WORKING, SEGA_TYPE_3, DRIVING, 800, 480, GROUP_OUTRUN, 0, 1, 1, 0, 0, 0, YELLOW},
{OUTRUN_2_SP_SDX_TEST, "Outrun 2 SP SDX", "outrun2", "DVP-0015", "SBMB", "2006", "800x480", WORKING, SEGA_TYPE_3, DRIVING, 800, 480, GROUP_OUTRUN_TEST, 0, 1, 1, 0, 0, 0, YELLOW}, {OUTRUN_2_SP_SDX_TEST, "Outrun 2 SP SDX", "outrun2", "DVP-0015", "SBMB", "2006", "800x480", WORKING, SEGA_TYPE_3, DRIVING, 800, 480, GROUP_OUTRUN_TEST, 0, 1, 1, 0, 0, 0, YELLOW},
{OUTRUN_2_SP_SDX_REVA, "Outrun 2 SP SDX Rev A", "outrun2-rev-a", "DVP-0015A", "SBMB", "2006", "800x480", WORKING, SEGA_TYPE_3, DRIVING, 800, 480, GROUP_OUTRUN, 0, 1, 1, 0, 0, 0, YELLOW}, {OUTRUN_2_SP_SDX_REVA, "Outrun 2 SP SDX Rev A", "outrun2-rev-a", "DVP-0015A", "SBMB", "2006", "800x480", WORKING, SEGA_TYPE_3, DRIVING, 800, 480, GROUP_OUTRUN, 0, 1, 1, 0, 0, 0, YELLOW},
+1 -1
View File
@@ -106,7 +106,7 @@ void FGAPIENTRY glutSwapBuffers(void)
sprintf(windowTitle, "%s - FPS: %.2f", sdlGameTitle, calculateFps()); sprintf(windowTitle, "%s - FPS: %.2f", sdlGameTitle, calculateFps());
SDL_SetWindowTitle(sdlWindow, windowTitle); SDL_SetWindowTitle(sdlWindow, windowTitle);
if (gId == MJ4_REVG || gId == MJ4_EVO) if (gGrp == GROUP_MJ4)
mj4TouchHolding(); mj4TouchHolding();
} }
+4 -4
View File
@@ -1112,7 +1112,7 @@ ssize_t read(int fd, void *buf, size_t count)
phRead(fd, buf, count); phRead(fd, buf, count);
return 1; return 1;
} }
if ((gId == MJ4_EVO || gId == MJ4_REVG || gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE) && getConfig()->emulateTouchscreen == 1 && if ((gGrp == GROUP_MJ4 || gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE) && getConfig()->emulateTouchscreen == 1 &&
mj4ResponseReady) mj4ResponseReady)
{ {
return mj4ReadTouchPacket(buf, count); return mj4ReadTouchPacket(buf, count);
@@ -1293,7 +1293,7 @@ ssize_t write(int fd, const void *buf, size_t count)
return driveboardWrite(fd, buf, count); return driveboardWrite(fd, buf, count);
} }
if (fd == hooks[SERIAL1] && (gId == MJ4_EVO || gId == MJ4_REVG || gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE)) if (fd == hooks[SERIAL1] && (gGrp == GROUP_MJ4 || gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE))
{ {
return mj4WriteTouchPacket(buf, count); return mj4WriteTouchPacket(buf, count);
} }
@@ -1336,7 +1336,7 @@ int ioctl(int fd, unsigned long int request, ...)
if (fd == hooks[SERIAL0] || fd == hooks[SERIAL1]) if (fd == hooks[SERIAL0] || fd == hooks[SERIAL1])
{ {
if (request == 0x541b && (gId == R_TUNED || gId == MJ4_REVG || gId == MJ4_EVO) && fd == hooks[SERIAL1]) if (request == 0x541b && (gId == R_TUNED || gGrp == GROUP_MJ4) && fd == hooks[SERIAL1])
{ {
uint8_t d = 1; uint8_t d = 1;
memcpy(argp, &d, sizeof(uint8_t)); memcpy(argp, &d, sizeof(uint8_t));
@@ -1730,7 +1730,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
{ {
struct tm *(*_gmtime_r)(const time_t *, struct tm *) = (struct tm * (*)(const time_t *, struct tm *)) dlsym(RTLD_NEXT, "gmtime_r"); struct tm *(*_gmtime_r)(const time_t *, struct tm *) = (struct tm * (*)(const time_t *, struct tm *)) dlsym(RTLD_NEXT, "gmtime_r");
if ((gId == MJ4_REVG || gId == MJ4_EVO) && getConfig()->mj4EnabledAtT == 1) if ((gGrp == GROUP_MJ4) && getConfig()->mj4EnabledAtT == 1)
{ {
time_t target_time = 1735286445; time_t target_time = 1735286445;
struct tm *res = _gmtime_r(&target_time, result); struct tm *res = _gmtime_r(&target_time, result);
+4 -1
View File
@@ -94,7 +94,9 @@ uint32_t cleanElfCRC32[] = {
0xB0A96E34, // DVP-0043 | vf5 0xB0A96E34, // DVP-0043 | vf5
0xF99E5635, // DVP-0044 | drive.elf 0xF99E5635, // DVP-0044 | drive.elf
0x4143F6B4, // DVP-0048A | main.exe 0x4143F6B4, // DVP-0048A | main.exe
0x65489691, // DVP-0049 | mj4 0x93210094, // DVP-0049A | mj4
0x561DC942, // DVP-0049F | mj4
0x65489691, // DVP-0049G | mj4
0x653BC83B, // DVP-0057 | a.elf 0x653BC83B, // DVP-0057 | a.elf
0x04D88552, // DVP-0057B | a.elf 0x04D88552, // DVP-0057B | a.elf
0x089D6051, // DVP-0060 | dsr 0x089D6051, // DVP-0060 | dsr
@@ -108,6 +110,7 @@ uint32_t cleanElfCRC32[] = {
0xDCC1f8E7, // DVP-0078 | ramboM.elf 0xDCC1f8E7, // DVP-0078 | ramboM.elf
0x05647A8E, // DVP-0079 | hummer_Master.elf 0x05647A8E, // DVP-0079 | hummer_Master.elf
0x0AD7CF0F, // DVP-0081 | mj4 0x0AD7CF0F, // DVP-0081 | mj4
0xEE2D5861, // DVP-0081B | mj4
0x4442EA15, // DVP-0083 | hummer_Master.elf 0x4442EA15, // DVP-0083 | hummer_Master.elf
0x8DF6BBF9, // DVP-0084 | id5.elf 0x8DF6BBF9, // DVP-0084 | id5.elf
0x2AF8004E, // DVP-0084A | id5.elf 0x2AF8004E, // DVP-0084A | id5.elf
+128
View File
@@ -1950,6 +1950,134 @@ int initPatch()
} }
} }
break; break;
case MJ4_EVO_REVB:
{
detourFunction(0x08841fbd, amDongleInit);
detourFunction(0x08840849, amDongleIsAvailable);
detourFunction(0x08840866, amDongleIsDevelop);
detourFunction(0x0884136a, amDongleUpdate);
// Fixes and patches to bypss network check
amDipswContextAddr = (void *)0x0af9513c; // Address of amDipswContext
detourFunction(0x088405dc, amDipswInit);
detourFunction(0x08840660, amDipswExit);
detourFunction(0x088406d5, amDipswGetData);
detourFunction(0x0884074b, amDipswSetLed);
patchMemoryFromString(0x080ea0f5, "909090909090");
detourFunction(0x080e327c, stubRetZero); // skip checks
detourFunction(0x080ee51e, stubRetZero);
patchMemoryFromString(0x080ea0e3, "75");
patchMemoryFromString(0x08c065b8, "00");
patchMemoryFromString(0x080eac5c, "01");
patchMemoryFromString(0x08c64e00, "ffffffff");
patchMemoryFromString(0x080e9346, "90909090909090909090");
patchMemoryFromString(0x080eaca6, "90909090909090909090");
patchMemoryFromString(0x0885d08d, "2e2f72616d2f746f2e74787400"); // Patch /home/disk2 folder
patchMemoryFromString(0x0885d0a4, "2e2f72616d2f66726f6d2e74787400"); // Patch /home/disk2 folder
patchMemoryFromString(0x0885d0bd, "2e2f72616d2f2e746d7000"); // Patch /home/disk2 folder
patchMemoryFromString(0x0885d10d, "2e2f72616d00"); // Patch /home/disk2 folder
patchMemoryFromString(0x0885d11d, "2e2f666f6f3100"); // Patch /home/disk2 folder
patchMemoryFromString(0x0885d12e, "2e2f666f6f3200"); // Patch /home/disk2 folder
patchMemoryFromString(0x08860885, "2e2f72616d2f746d7000"); // Patch /home/disk2 folder
patchMemoryFromString(0x08863fef, "2e2f00"); // Patch /home/disk2 folder
if (GPUVendor != NVIDIA_GPU)
{
detourFunction(0x08051314, gl_ProgramStringARB);
}
}
break;
case MJ4_REVA:
{
setVariable(0x0a250914, 2);
setVariable(0x0a250910, 2);
setVariable(0x0a25090c, 2);
setVariable(0x0a250908, 2);
setVariable(0x0a250900, 2);
setVariable(0x0a2508fc, 2);
// Security
detourFunction(0x085c9d64, amDongleInit);
detourFunction(0x085c881d, amDongleIsAvailable);
detourFunction(0x085c883a, amDongleIsDevelop);
detourFunction(0x085c9213, amDongleUpdate);
// Fixes and patches to bypss network check
amDipswContextAddr = (void *)0x0a27a81c; // Address of amDipswContext
detourFunction(0x085c85b0, amDipswInit);
detourFunction(0x085c8634, amDipswExit);
detourFunction(0x085c86a9, amDipswGetData);
detourFunction(0x085c8720, amDipswSetLed);
detourFunction(0x080e209c, stubRetZero); // skip checks
detourFunction(0x080ed218, stubRetZero);
patchMemoryFromString(0x080e8e81, "75");
patchMemoryFromString(0x0887ce98, "00");
patchMemoryFromString(0x080e8e93, "909090909090"); // test skip countdown
patchMemoryFromString(0x085e43ad, "2e2f72616d2f746f2e74787400"); // Patch /home/disk2 folder
patchMemoryFromString(0x085e43c4, "2e2f72616d2f66726f6d2e74787400"); // Patch /home/disk2 folder
patchMemoryFromString(0x085e43dd, "2e2f72616d2f2e746d7000"); // Patch /home/disk2 folder
patchMemoryFromString(0x085e442d, "2e2f72616d00"); // Patch /home/disk2 folder
patchMemoryFromString(0x085e443d, "2e2f666f6f3100"); // Patch /home/disk2 folder
patchMemoryFromString(0x085e444e, "2e2f666f6f3200"); // Patch /home/disk2 folder
patchMemoryFromString(0x085e7b03, "2e2f72616d2f746d7000"); // Patch /home/disk2 folder
patchMemoryFromString(0x085eb1c7, "2e2f00"); // Patch /home/disk2 folder
// Mesa Patches
if (GPUVendor != NVIDIA_GPU)
{
detourFunction(0x08050b44, gl_ProgramStringARB);
}
}
break;
case MJ4_REVF:
{
setVariable(0x0a2d3654, 2);
setVariable(0x0a2d3650, 2);
setVariable(0x0a2d364c, 2);
setVariable(0x0a2d3648, 2);
setVariable(0x0a2d3640, 2);
setVariable(0x0a2d363c, 2);
// Security
detourFunction(0x0860533a, amDongleInit);
detourFunction(0x08603df5, amDongleIsAvailable);
detourFunction(0x08603e12, amDongleIsDevelop);
detourFunction(0x086047eb, amDongleUpdate);
// Fixes and patches to bypss network check
amDipswContextAddr = (void *)0x0a2fd57c; // Address of amDipswContext
detourFunction(0x08603b88, amDipswInit);
detourFunction(0x08603c0c, amDipswExit);
detourFunction(0x08603c81, amDipswGetData);
detourFunction(0x08603cf7, amDipswSetLed);
detourFunction(0x080e24fc, stubRetZero); // skip checks
detourFunction(0x080ed74c, stubRetZero);
patchMemoryFromString(0x080e9339, "75");
patchMemoryFromString(0x088d2f38, "00");
patchMemoryFromString(0x080e934b, "909090909090"); // test skip countdown
patchMemoryFromString(0x0862036d, "2e2f72616d2f746f2e74787400"); // Patch /home/disk2 folder
patchMemoryFromString(0x08620384, "2e2f72616d2f66726f6d2e74787400"); // Patch /home/disk2 folder
patchMemoryFromString(0x0862039d, "2e2f72616d2f2e746d7000"); // Patch /home/disk2 folder
patchMemoryFromString(0x086203ed, "2e2f72616d00"); // Patch /home/disk2 folder
patchMemoryFromString(0x086203fd, "2e2f666f6f3100"); // Patch /home/disk2 folder
patchMemoryFromString(0x0862040e, "2e2f666f6f3200"); // Patch /home/disk2 folder
patchMemoryFromString(0x08623ae3, "2e2f72616d2f746d7000"); // Patch /home/disk2 folder
patchMemoryFromString(0x086275b3, "2e2f00"); // Patch /home/disk2 folder
// Mesa Patches
if (GPUVendor != NVIDIA_GPU)
{
detourFunction(0x08050d50, gl_ProgramStringARB);
}
}
break;
case MJ4_REVG: case MJ4_REVG:
{ {
setVariable(0x0acf85d4, 2); setVariable(0x0acf85d4, 2);
+21
View File
@@ -2532,6 +2532,20 @@ int initResolutionPatches()
setVariable(addressC + 0x8, (size_t)newWidthSPtrLGJ); setVariable(addressC + 0x8, (size_t)newWidthSPtrLGJ);
} }
break; break;
case MJ4_REVA:
{
patchMemoryFromString(0x080520b1, "01"); // Enable Anti Alias
patchMemoryFromString(0x080520aa, "03"); // Force 1024x768
patchMemoryFromString(0x080531fa, "b803000000"); // Skips resolution set by the Dip Switches.
}
break;
case MJ4_REVF:
{
patchMemoryFromString(0x080522e1, "01"); // Enable Anti Alias
patchMemoryFromString(0x080522da, "03"); // Force 1024x768
patchMemoryFromString(0x0805346a, "b803000000"); // Skips resolution set by the Dip Switches.
}
break;
case MJ4_REVG: case MJ4_REVG:
{ {
patchMemoryFromString(0x080524a1, "01"); // Enable Anti Alias patchMemoryFromString(0x080524a1, "01"); // Enable Anti Alias
@@ -2546,6 +2560,13 @@ int initResolutionPatches()
patchMemoryFromString(0x08053b24, "b803000000"); // Skips resolution set by the Dip Switches. patchMemoryFromString(0x08053b24, "b803000000"); // Skips resolution set by the Dip Switches.
} }
break; break;
case MJ4_EVO_REVB:
{
patchMemoryFromString(0x08052961, "01"); // Enable Anti Alias
patchMemoryFromString(0x0805295a, "03"); // Force 1024x768
patchMemoryFromString(0x08053b24, "b803000000"); // Skips resolution set by the Dip Switches.
}
break;
case OUTRUN_2_SP_SDX: case OUTRUN_2_SP_SDX:
{ {
if (gWidth <= 800 && gHeight <= 480) if (gWidth <= 800 && gHeight <= 480)
+13 -6
View File
@@ -121,7 +121,7 @@ void startSDL(int *argcp, char **argv)
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
if (gGrp == GROUP_ABC || gGrp == GROUP_VF5 || gId == R_TUNED || gId == GHOST_SQUAD_EVOLUTION || gId == SEGA_RACE_TV || if (gGrp == GROUP_ABC || gGrp == GROUP_VF5 || gId == R_TUNED || gId == GHOST_SQUAD_EVOLUTION || gId == SEGA_RACE_TV ||
gId == MJ4_REVG || gId == MJ4_EVO) gGrp == GROUP_MJ4 )
{ {
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1);
} }
@@ -130,11 +130,18 @@ void startSDL(int *argcp, char **argv)
strcat(sdlGameTitle, getGameName()); strcat(sdlGameTitle, getGameName());
int windowWidth = gWidth;
if(gGrp == GROUP_OUTRUN && getConfig()->width == 640)
{
gWidth = 800;
}
// Hacky way to make AxA games render the characters properly // Hacky way to make AxA games render the characters properly
if (gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE) if (gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE)
sdlWindow = SDL_CreateWindow(sdlGameTitle, 1024, 768, windowFlags); sdlWindow = SDL_CreateWindow(sdlGameTitle, 1024, 768, windowFlags);
else else
sdlWindow = SDL_CreateWindow(sdlGameTitle, gWidth, gHeight, windowFlags); sdlWindow = SDL_CreateWindow(sdlGameTitle, windowWidth, gHeight, windowFlags);
if (!sdlWindow) if (!sdlWindow)
{ {
@@ -143,7 +150,7 @@ void startSDL(int *argcp, char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (gId == GHOST_SQUAD_EVOLUTION || gId == MJ4_EVO || gId == MJ4_REVG) if (gId == GHOST_SQUAD_EVOLUTION || gGrp == GROUP_MJ4)
SDL_SetWindowSize(sdlWindow, gWidth, gHeight + 1); SDL_SetWindowSize(sdlWindow, gWidth, gHeight + 1);
x11Display = (Display *)SDL_GetPointerProperty(SDL_GetWindowProperties(sdlWindow), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); x11Display = (Display *)SDL_GetPointerProperty(SDL_GetWindowProperties(sdlWindow), SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL);
@@ -172,11 +179,11 @@ void startSDL(int *argcp, char **argv)
// If games are any of the LGJ or Primeval Hunt, we prevent the window to resize. // If games are any of the LGJ or Primeval Hunt, we prevent the window to resize.
if ((gGrp == GROUP_LGJ || gId == PRIMEVAL_HUNT) && !getConfig()->fullscreen) if ((gGrp == GROUP_LGJ || gId == PRIMEVAL_HUNT) && !getConfig()->fullscreen)
SDL_SetWindowMaximumSize(sdlWindow, gWidth, gHeight); SDL_SetWindowMaximumSize(sdlWindow, windowWidth, gHeight);
else if (gGrp != GROUP_LGJ) else if (gGrp != GROUP_LGJ)
SDL_SetWindowMaximumSize(sdlWindow, displayMode->w, displayMode->h); SDL_SetWindowMaximumSize(sdlWindow, displayMode->w, displayMode->h);
SDL_SetWindowMinimumSize(sdlWindow, gWidth, gHeight); SDL_SetWindowMinimumSize(sdlWindow, windowWidth, gHeight);
// Hacky way to make AxA games render the characters properly // Hacky way to make AxA games render the characters properly
if (gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE) if (gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE)
@@ -222,7 +229,7 @@ void startSDL(int *argcp, char **argv)
gId == GHOST_SQUAD_EVOLUTION || gId == PRIMEVAL_HUNT)) gId == GHOST_SQUAD_EVOLUTION || gId == PRIMEVAL_HUNT))
initCrossHairs(); initCrossHairs();
if ((gId == MJ4_REVG || gId == MJ4_EVO || gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE) && strcmp(getConfig()->touchCursor, "") != 0 && if ((gGrp == GROUP_MJ4 || gId == QUIZ_AXA || gId == QUIZ_AXA_LIVE) && strcmp(getConfig()->touchCursor, "") != 0 &&
getConfig()->emulateTouchscreen) getConfig()->emulateTouchscreen)
setCursor(touchCursor); setCursor(touchCursor);
else if (getConfig()->hideCursor) else if (getConfig()->hideCursor)
+6 -8
View File
@@ -569,7 +569,7 @@ void gl_ProgramStringARB(int target, int program_fmt, int program_len, char *pro
newProgram = replaceInBlock(program, rtunedFsMesa, rtunedFsMesaCount, "", ""); newProgram = replaceInBlock(program, rtunedFsMesa, rtunedFsMesaCount, "", "");
} }
} }
else if (gId == MJ4_REVG || gId == MJ4_EVO) else if (gGrp == GROUP_MJ4)
{ {
if (target == GL_VERTEX_PROGRAM_ARB) if (target == GL_VERTEX_PROGRAM_ARB)
{ {
@@ -976,10 +976,10 @@ void glBindTexture(GLenum target, GLuint texture)
} }
} }
int parseCgcArgs(const char *input, const char ***compilerArgs, const char **outputFileName) int parseCgcArgs(const char *input, const char ***compilerArgs, const char **outputFileName, char **bufferToFree)
{ {
char *inputCopy = strdup(input); char *inputCopy = strdup(input);
char *toFree = inputCopy; *bufferToFree = inputCopy;
char *token = strtok(inputCopy, " "); char *token = strtok(inputCopy, " ");
char **args = malloc(256 * sizeof(char *)); char **args = malloc(256 * sizeof(char *));
int count = 0; int count = 0;
@@ -1014,7 +1014,6 @@ int parseCgcArgs(const char *input, const char ***compilerArgs, const char **out
} }
(*compilerArgs)[argIndex] = NULL; (*compilerArgs)[argIndex] = NULL;
free(args); free(args);
free(toFree);
if (strcmp(profile, "vp40") == 0) if (strcmp(profile, "vp40") == 0)
{ {
return 6150; return 6150;
@@ -1215,9 +1214,9 @@ int compileWithCGC(char *command)
{ {
const char **compilerArgs = NULL; const char **compilerArgs = NULL;
const char *outputFileName = NULL; const char *outputFileName = NULL;
char *argsBuffer = NULL;
int profile = parseCgcArgs(command, &compilerArgs, &outputFileName); int profile = parseCgcArgs(command, &compilerArgs, &outputFileName, &argsBuffer);
size_t *ctx = _cgCreateContext(); size_t *ctx = _cgCreateContext();
char *program = NULL; char *program = NULL;
@@ -1248,10 +1247,9 @@ int compileWithCGC(char *command)
fprintf(outputFile, "%s", compiledSource); fprintf(outputFile, "%s", compiledSource);
fclose(outputFile); fclose(outputFile);
free(argsBuffer);
_cgDestroyProgram(program); _cgDestroyProgram(program);
_cgDestroyContext(ctx); _cgDestroyContext(ctx);
free((void *)*compilerArgs);
return 0; return 0;
} }