-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmm2_minimap.lua
182 lines (165 loc) · 5.08 KB
/
mm2_minimap.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
-- BLOCK TYPES
WALL = 0x40
LADDER = 0x80 -- also water and right conveyor belts
FATAL = 0xC0 -- also ice and left conveyor belts
-- OTHER INFO
TILE_SIZE = 16
NUM_ROWS = 15
NUM_COLS = 16
MACRO_COLS = 8
MACRO_ROWS = 8
TSA_COLS_PER_MACRO = 2
TSA_ROWS_PER_MACRO = 2
NUM_SPRITES = 32
SCREEN_WIDTH = 256
MINI_TILE_SIZE = 3
PLAYING = 178
BOSS_RUSH = 100
LAGGING = 171
HEALTH_REFILL = 119
PAUSED = 128
DEAD = 156
MENU = 197
READY = 82
-- RAM ADDRESSES
SCROLL_X = 0x001F
SCROLL_Y = 0x0022
CURRENT_STAGE = 0x002A -- STAGE SELECT = 1,2,3... clockwise starting at bubble man
GAME_STATE = 0x01FE
MEGAMAN_ID = 0x0400
MEGAMAN_ID2 = 0x0420
CURRENT_SCREEN = 0x0440
MEGAMAN_X = 0x0460
MEGAMAN_Y = 0x04A0
-- ROM ADDRESSES
TSA_PROPERTIES_START = 0x10
TSA_PROPERTIES_SIZE = 0x500
MAP_START = 0x510
MAP_SIZE = 0x4000
function getBlockAt(stage, screen, x, y)
local stage_start = stage * MAP_SIZE + MAP_START
local screen_start = stage_start + MACRO_COLS * MACRO_ROWS * screen
local address = screen_start + x * MACRO_ROWS + y
return rom.readbyte(address)
end
function getTSAArrayFromBlock(stage, block)
local stage_start = stage * MAP_SIZE + TSA_PROPERTIES_START
local address = stage_start + block * TSA_COLS_PER_MACRO * TSA_ROWS_PER_MACRO
return {rom.readbyte(address), rom.readbyte(address + 1), rom.readbyte(address + 2), rom.readbyte(address + 3)}
end
function getTSAFromBlock(stage, block, x, y)
local TSAArray = getTSAArrayFromBlock(stage, block)
return TSAArray[x * TSA_ROWS_PER_MACRO + y + 1]
end
function getTSAAt(stage, screen, x, y)
local block_x = math.floor(x / TSA_COLS_PER_MACRO)
local block_y = math.floor(y / TSA_ROWS_PER_MACRO)
local block = getBlockAt(stage, screen, block_x, block_y)
local TSA = getTSAFromBlock(stage, block, x % TSA_COLS_PER_MACRO, y % TSA_ROWS_PER_MACRO)
return TSA
end
function isWall(TSA)
return AND(TSA, 0xC0) == WALL
end
function isFatal(TSA)
return AND(TSA, 0xC0) == FATAL
end
function isLadder(TSA)
return AND(TSA, 0xC0) == LADDER
end
function isFree(TSA)
return AND(TSA, 0xC0) == 0
end
function getScreenMap(stage, screen)
local map = {}
local i, j, x, y, TSA
for i = 1,NUM_ROWS do
map[i] = {}
for j = 1,NUM_COLS do
TSA = getTSAAt(stage, screen, j-1, i-1)
map[i][j] = TSA
end
end
return map
end
function getMap(stage, screen)
local map1 = getScreenMap(stage, screen - 1)
local map2 = getScreenMap(stage, screen)
local map3 = getScreenMap(stage, screen + 1)
local mmx = memory.readbyte(MEGAMAN_X)
local mmy = memory.readbyte(MEGAMAN_Y)
local scrollx = memory.readbyte(SCROLL_X)
local mmtilex = math.floor(mmx / TILE_SIZE)
local mmtiley = math.floor(mmy / TILE_SIZE)
local size1 = NUM_COLS/2 - mmtilex
--emu.message(string.format("%02X",getBlockAt(stage, screen, mmtilex*1, (mmtiley-1)*1)))
gui.text(0,8,string.format("pos:%02X, %02X\nblock: %02X",mmtilex, mmtiley, getBlockAt(stage, screen, mmtilex/2, (mmtiley)/2 + 1)))
if scrollx == 0 then
return map2
end
local map = {}
for i = 1,NUM_ROWS do
map[i] = {}
if size1 > 0 then
for j = 1,size1 do
map[i][j] = map1[i][(NUM_COLS - size1) + j]
end
for j = 1,NUM_COLS-size1 do
map[i][size1+j] = map2[i][j]
end
else
for j = 1,NUM_COLS+size1 do
map[i][j] = map2[i][j-size1]
end
for j = 1,-size1 do
map[i][NUM_COLS + size1 + j] = map3[i][j]
end
end
end
return map
end
function validState()
local state = memory.readbyte(GAME_STATE)
return state==PLAYING or state==BOSS_RUSH or state==LAGGING or state==HEALTH_REFILL
end
function minimap()
if not validState() then return end --originally was if not validState then blah end. It worked fine without parentheses???
local current_stage = memory.readbyte(CURRENT_STAGE)
if current_stage >= 8 then
current_stage = current_stage - 8
end
local current_screen = memory.readbyte(CURRENT_SCREEN)
local map = getMap(current_stage, current_screen)
local map_left = SCREEN_WIDTH - NUM_COLS * MINI_TILE_SIZE - 2 * MINI_TILE_SIZE
local map_top = MINI_TILE_SIZE * 2
local color
local i, j
for i = 1,NUM_ROWS do
for j = 1,NUM_COLS do
color = "#000000CC"
if isWall(map[i][j]) then
color = "#0000FFCC"
end
if isFatal(map[i][j]) then
color = "#FF0000CC"
end
if isLadder(map[i][j]) then
color = "#00FF00CC"
end
--To turn this from minimap into full-size map, this line is literally all we need to change.
gui.drawbox(map_left + j * MINI_TILE_SIZE, map_top + i * MINI_TILE_SIZE, map_left + j * MINI_TILE_SIZE + MINI_TILE_SIZE, map_top + i * MINI_TILE_SIZE + MINI_TILE_SIZE, color, color)
end
end
local sx, sy
local scroll_x = memory.readbyte(SCROLL_X)
for i = 0,NUM_SPRITES-1 do
if memory.readbyte(MEGAMAN_ID2+i)>=0x80 then
color = string.format("#%x%x%x",memory.readbyte(MEGAMAN_ID + i), memory.readbyte(MEGAMAN_ID2 + i), i*8)
sx = memory.readbyte(MEGAMAN_X + i)
sx = math.ceil(AND(sx+255-scroll_x,255) / TILE_SIZE)
sy = math.ceil((memory.readbyte(MEGAMAN_Y + i)) / TILE_SIZE)
gui.drawbox(map_left + sx * MINI_TILE_SIZE, map_top + sy * MINI_TILE_SIZE, map_left + sx * MINI_TILE_SIZE + MINI_TILE_SIZE, map_top + sy * MINI_TILE_SIZE + MINI_TILE_SIZE, color, "clear")
end
end
end
emu.registerafter(minimap)