3
0
mirror of https://github.com/CrazyRedMachine/popnhax.git synced 2024-11-27 15:30:50 +01:00

attract lights

This commit is contained in:
CrazyRedMachine 2024-09-22 21:19:18 +02:00
parent 285be99caa
commit 9e2cd2b1e4
5 changed files with 120 additions and 43 deletions

View File

@ -91,8 +91,10 @@
<!-- Attract mode patches --> <!-- Attract mode patches -->
<!-- Attract mode can be played (press a button other than red during demo to enter interactive mode) --> <!-- Attract mode can be played (press a button other than red during demo to enter interactive mode) -->
<attract_interactive __type="bool">0</attract_interactive> <attract_interactive __type="bool">0</attract_interactive>
<!-- Attract mode will play EX charts at 4.0x hispeed --> <!-- Attract mode will play EX charts instead of normal, and at hispeed default bpm (or x4.0 if unset) -->
<attract_ex __type="bool">0</attract_ex> <attract_ex __type="bool">0</attract_ex>
<!-- Attract mode will light up -->
<attract_lights __type="bool">0</attract_lights>
<!-- Attract mode will play full songs --> <!-- Attract mode will play full songs -->
<attract_full __type="bool">0</attract_full> <attract_full __type="bool">0</attract_full>

View File

@ -160,68 +160,69 @@ bool patch_full_attract()
void (*real_attract_inter)(void); void (*real_attract_inter)(void);
void hook_attract_inter() void hook_attract_inter()
{ {
__asm("push 0x1EF\n"); __asm("push 0x1EF\n");
__asm("mov eax, dword ptr [_g_is_button_pressed_fn]\n"); __asm("mov eax, dword ptr [_g_is_button_pressed_fn]\n");
__asm("call eax\n"); __asm("call eax\n");
__asm("add esp, 4\n"); __asm("add esp, 4\n");
__asm("test al, al\n"); __asm("test al, al\n");
__asm("je skip_disable_autoplay\n"); __asm("je skip_disable_autoplay\n");
__asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n"); __asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n");
__asm("mov dword ptr [eax], 0\n"); __asm("mov dword ptr [eax], 0\n");
__asm("skip_disable_autoplay:"); __asm("skip_disable_autoplay:");
real_attract_inter(); real_attract_inter();
} }
void (*real_retire_handling)(void); void (*real_retire_handling)(void);
void hook_attract_inter_rearm() void hook_attract_inter_rearm()
{ {
__asm("push eax\n"); __asm("push eax\n");
__asm("mov eax, dword ptr [_g_attract_marker_addr]\n"); __asm("mov eax, dword ptr [_g_attract_marker_addr]\n");
__asm("cmp word ptr [eax], 0x0101\n"); __asm("cmp word ptr [eax], 0x0101\n");
__asm("jne skip_rearm_autoplay\n"); __asm("jne skip_rearm_autoplay\n");
__asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n"); __asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n");
__asm("mov dword ptr [eax], 1\n"); __asm("mov dword ptr [eax], 1\n");
__asm("skip_rearm_autoplay:"); __asm("skip_rearm_autoplay:");
__asm("pop eax\n"); __asm("pop eax\n");
real_retire_handling(); real_retire_handling();
} }
void (*real_songend_handling)(void); void (*real_songend_handling)(void);
void hook_attract_inter_songend_rearm() void hook_attract_inter_songend_rearm()
{ {
__asm("push eax\n"); __asm("push eax\n");
__asm("mov eax, dword ptr [_g_attract_marker_addr]\n"); __asm("mov eax, dword ptr [_g_attract_marker_addr]\n");
__asm("cmp word ptr [eax], 0x0101\n"); __asm("cmp word ptr [eax], 0x0101\n");
__asm("jne skip_se_rearm_autoplay\n"); __asm("jne skip_se_rearm_autoplay\n");
__asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n"); __asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n");
__asm("mov dword ptr [eax], 1\n"); __asm("mov dword ptr [eax], 1\n");
__asm("skip_se_rearm_autoplay:"); __asm("skip_se_rearm_autoplay:");
__asm("pop eax\n"); __asm("pop eax\n");
real_songend_handling(); real_songend_handling();
} }
void (*real_test_handling)(void); void (*real_test_handling)(void);
void hook_attract_inter_rearm_test() void hook_attract_inter_rearm_test()
{ {
__asm("push eax\n"); __asm("push eax\n");
__asm("mov eax, dword ptr [_g_attract_marker_addr]\n"); __asm("mov eax, dword ptr [_g_attract_marker_addr]\n");
__asm("cmp word ptr [eax], 0x0101\n"); __asm("cmp word ptr [eax], 0x0101\n");
__asm("jne skip_rearm_autoplay_test\n"); __asm("jne skip_rearm_autoplay_test\n");
__asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n"); __asm("mov eax, dword ptr [_g_autoplay_marker_addr]\n");
__asm("mov dword ptr [eax], 1\n"); __asm("mov dword ptr [eax], 1\n");
__asm("skip_rearm_autoplay_test:"); __asm("skip_rearm_autoplay_test:");
__asm("pop eax\n"); __asm("pop eax\n");
real_test_handling(); real_test_handling();
} }
void (*real_rearm_marker)(void); void (*real_rearm_marker)(void);
void hook_retrieve_attractmarker() void hook_retrieve_attractmarker()
{ {
__asm("add esi, 0x18\n"); __asm("add esi, 0x18\n");
__asm("mov dword ptr [_g_attract_marker_addr], esi\n"); __asm("mov dword ptr [_g_attract_marker_addr], esi\n");
__asm("sub esi, 0x18\n"); __asm("sub esi, 0x18\n");
real_rearm_marker(); real_rearm_marker();
} }
bool patch_attract_interactive() bool patch_attract_interactive()
{ {
DWORD dllSize = 0; DWORD dllSize = 0;
@ -280,7 +281,7 @@ bool patch_attract_interactive()
} }
/* disable interactive mode after a while without button press */ /* disable interactive mode after a while without button press */
{ {
int64_t pattern_offset = search(data, dllSize, "\x3D\x58\x02\x00\x00\x7C", 6, 0); int64_t pattern_offset = search(data, dllSize, "\x3D\x58\x02\x00\x00\x7C", 6, 0);
if (pattern_offset == -1) { if (pattern_offset == -1) {
LOG("popnhax: attract_interactive: cannot find retire handling\n"); LOG("popnhax: attract_interactive: cannot find retire handling\n");
@ -340,4 +341,69 @@ bool patch_attract_interactive()
LOG("popnhax: attract mode is interactive\n"); LOG("popnhax: attract mode is interactive\n");
return true; return true;
}
uint32_t g_button_bitfield_addr = 0;
void (*real_autoplay_handling)(void);
void hook_attract_autoplay()
{
// ax contains button, need to OR g_button_bitfield_addr with 1<<ax
__asm("push edx\n");
__asm("push ecx\n");
__asm("push ebx\n");
__asm("movzx ecx, ax\n");
__asm("mov ebx, 1\n");
__asm("shl ebx, cl\n");
__asm("mov edx, [_g_button_bitfield_addr]\n");
__asm("or dword ptr [edx], ebx\n");
__asm("pop ebx\n");
__asm("pop ecx\n");
__asm("pop edx\n");
real_autoplay_handling();
}
bool patch_attract_lights()
{
DWORD dllSize = 0;
char *data = getDllData(g_game_dll_fn, &dllSize);
/* retrieve pressed button bitfield address */
{
int64_t pattern_offset = search(data, dllSize, "\x25\xFF\x0F\x00\x00\x5D\xC3\xCC\xCC\xCC\xCC\x55\x8B\xEC\x0F\xB6\x05", 17, 0);
if (pattern_offset == -1) {
LOG("popnhax: attract_lights: cannot find button bitfield address\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset - 0x05;
g_button_bitfield_addr = *((uint32_t*)(patch_addr+0x01));
}
/* hook autoplay button trigger to force corresponding button lamps */
{
int64_t pattern_offset = search(data, dllSize, "\x66\xC1\xE0\x08\x0F\xB7\xC8\x83\xC9\x02\x51", 11, 0);
if (pattern_offset == -1) {
LOG("popnhax: attract_lights: cannot find autopress button handling\n");
return false;
}
uint64_t patch_addr = (int64_t)data + pattern_offset;
MH_CreateHook((LPVOID)patch_addr, (LPVOID)hook_attract_autoplay,
(void **)&real_autoplay_handling);
}
/* force lamp computation in attract mode */
{
if (!find_and_patch_hex(g_game_dll_fn, "\x00\x00\x84\xC0\x75\x41\xE8", 7, 4, "\x90\x90", 2))
{
LOG("popnhax: attract_lights: cannot find lamp compute function\n");
return false;
}
}
LOG("popnhax: attract mode has lights\n");
return true;
} }

View File

@ -5,6 +5,7 @@
#include "popnhax/config.h" #include "popnhax/config.h"
bool patch_attract_interactive(); bool patch_attract_interactive();
bool patch_attract_lights();
bool patch_ex_attract(uint16_t target_bpm); bool patch_ex_attract(uint16_t target_bpm);
bool patch_full_attract(); bool patch_full_attract();

View File

@ -40,6 +40,7 @@ struct popnhax_config {
bool attract_interactive; bool attract_interactive;
bool attract_ex; bool attract_ex;
bool attract_full; bool attract_full;
bool attract_lights;
bool force_slow_timer; bool force_slow_timer;
bool patch_db; bool patch_db;

View File

@ -228,6 +228,8 @@ PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, attract_intera
"/popnhax/attract_interactive") "/popnhax/attract_interactive")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, attract_full, PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, attract_full,
"/popnhax/attract_full") "/popnhax/attract_full")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, attract_lights,
"/popnhax/attract_lights")
PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, force_slow_timer, PSMAP_MEMBER_REQ(PSMAP_PROPERTY_TYPE_BOOL, struct popnhax_config, force_slow_timer,
"/popnhax/force_slow_timer") "/popnhax/force_slow_timer")
/* removed options are now hidden as optional */ /* removed options are now hidden as optional */
@ -8648,6 +8650,11 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
patch_attract_interactive(); patch_attract_interactive();
} }
if (config.attract_lights)
{
patch_attract_lights();
}
if (config.attract_ex) if (config.attract_ex)
{ {
patch_ex_attract( config.hispeed_auto ? config.hispeed_default_bpm : 0 ); patch_ex_attract( config.hispeed_auto ? config.hispeed_default_bpm : 0 );