mirror of
https://github.com/CrazyRedMachine/popnhax.git
synced 2024-11-27 15:30:50 +01:00
attract lights
This commit is contained in:
parent
285be99caa
commit
9e2cd2b1e4
4
dist/popnhax/popnhax.xml
vendored
4
dist/popnhax/popnhax.xml
vendored
@ -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>
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
@ -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();
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 );
|
||||||
|
Loading…
Reference in New Issue
Block a user