-
Notifications
You must be signed in to change notification settings - Fork 0
/
CooPatch.lua
160 lines (148 loc) · 5.57 KB
/
CooPatch.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
-- MMBN coop lua script test
-- requires Bizhawk w/ VBA-Next core
-- hooks ingame functions to create and complete events
-- events would be sent between players to simulate a Co-op experience
-- currently only works with NTSC 3 Blue
-- by NMarkro
memory.usememorydomain("System Bus")
pressed = false
queue = {}
valid_registers = emu.getregisters()
end_main_func_addr = 0x08000322
-- function calls are addr+1 to call in THUMB mode
give_chip_func_addr = 0x08011281
give_zenny_func_addr = 0x0801480B
give_bugfrag_func_addr = 0x0801485F
-- IDEA: watch the function that sets chip library flags
-- send give_chip events with "amount = 0" to update the other player's library without adding the chip
-- this is mainly for when players pick up extra folders and folder 2
-- we can't actually call this by itself as it sets off anti-cheat
give_library_func_addr = 0x080112AE
--[[
hooks the end of the main function
code normally looks like this:
0800031C ldr r0,=3006825h load some function addr into r0
0800031E mov r14,r15 move the PC into r14 for returning here
08000320 bx r0 <- hooking here call the function loaded in r0
08000322 b 80002B4h goes back to start of main loop
the idea is to call whatever function we want with r0 then rerun this code normally
--]]
function main_hook()
if next(queue) ~= nil then
local index, event = next(queue)
emu.setregister("R0", event.addr)
emu.setregister("R14", 0x0800031C)
end
end
-- r0 is used to call functions and as function args
-- we need to set the args manually at the beginning of functions
function set_args(registers)
for reg, value in pairs(registers) do
if valid_registers[reg] ~= nil then
emu.setregister(reg, value)
end
end
end
-- hooks the give_chip function
-- has 2 purposes, to create new events for other players or complete current queued events
function give_chip_hook()
-- check if we called this function
if emu.getregister("R14") == 0x0800031C then
local index, event = next(queue)
set_args(event.registers)
table.remove(queue, 1)
else
-- the player was given this chip normally
-- here you would create an event from the given args to be sent over the network
end
end
-- hooks the give_zenny function
-- has 2 purposes, to create new events for other players or complete current queued events
function give_zenny_hook()
-- check if we called this function
if emu.getregister("R14") == 0x0800031C then
local index, event = next(queue)
set_args(event.registers)
table.remove(queue, 1)
else
-- the player was given this zenny normally
-- here you would create an event from the given args to be sent over the network
end
end
-- hooks the give_bugfrag function
-- has 2 purposes, to create new events for other players or complete current queued events
function give_bugfrag_hook()
-- check if we called this function
if emu.getregister("R14") == 0x0800031C then
local index, event = next(queue)
set_args(event.registers)
table.remove(queue, 1)
else
-- the player was given this bugfrag normally
-- here you would create an event from the given args to be sent over the network
end
end
event.onmemoryexecute(main_hook, end_main_func_addr)
-- bizhawk needs even addr for events
event.onmemoryexecute(give_chip_hook, give_chip_func_addr+1)
event.onmemoryexecute(give_zenny_hook, give_zenny_func_addr+1)
event.onmemoryexecute(give_bugfrag_hook, give_bugfrag_func_addr+1)
while true do
local inputs = joypad.get()
-- pressing L+R+A will give you 1x LavaStg T
if inputs.L and inputs.R and inputs.A then
if not pressed then
-- for give_chip the args are
-- R0 = chip_id
-- R1 = chip_code
-- R2 = amount
local new_event = {
addr=give_chip_func_addr,
registers={["R0"]=0x0B3,["R1"]=0x13,["R2"]=0x1}
}
table.insert(queue, new_event)
pressed = true
end
-- pressing L+R+B will give you 1000z
elseif inputs.L and inputs.R and inputs.B then
if not pressed then
-- for give_zenny the args are
-- R0 = amount
local new_event = {
addr=give_zenny_func_addr,
registers={["R0"]=1000}
}
table.insert(queue, new_event)
pressed = true
end
-- pressing L+R+Select will give you 10 bugfrags
elseif inputs.L and inputs.R and inputs.Select then
if not pressed then
-- for give_bugfrag the args are
-- R0 = amount
local new_event = {
addr=give_bugfrag_func_addr,
registers={["R0"]=10}
}
table.insert(queue, new_event)
pressed = true
end
-- pressing L+R+Start will add AntiDmg to your library
elseif inputs.L and inputs.R and inputs.Start then
if not pressed then
-- for give_chip the args are
-- R0 = chip_id
-- R1 = chip_code (shouldn't matter)
-- R2 = amount (set to 0 to only update library)
local new_event = {
addr=give_chip_func_addr,
registers={["R0"]=0x0BF,["R1"]=0x01,["R2"]=0x0}
}
table.insert(queue, new_event)
pressed = true
end
else
pressed = false
end
emu.frameadvance()
end