mirror of
https://github.com/notwa/mm
synced 2025-02-05 05:23:22 -08:00
(attempt to) abide to calling conventions
i haven't checked if i need double-word alignment
This commit is contained in:
parent
7c35d99a9f
commit
9a2757d16d
4 changed files with 31 additions and 21 deletions
|
@ -40,6 +40,9 @@ which produces [a large csv file.][csv]
|
||||||
Tests the fastest form of basic movement in Majora's Mask.
|
Tests the fastest form of basic movement in Majora's Mask.
|
||||||
Run it in the Clock Town Great Fairy's Fountain.
|
Run it in the Clock Town Great Fairy's Fountain.
|
||||||
|
|
||||||
|
#### inject.lua
|
||||||
|
Assembles and injects an assembly subroutine into the game.
|
||||||
|
|
||||||
#### oneshot.lua
|
#### oneshot.lua
|
||||||
Instantly gives you all the items in the game, etc.
|
Instantly gives you all the items in the game, etc.
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,16 @@ local ow_before_addr = (ow_before % 0x4000000)*4
|
||||||
|
|
||||||
local header = ("[overwritten]: 0x%08X\n"):format(ow_before_addr)
|
local header = ("[overwritten]: 0x%08X\n"):format(ow_before_addr)
|
||||||
header = header..[[
|
header = header..[[
|
||||||
sw ra, -4(sp)
|
// TODO: optimize for size
|
||||||
|
// TODO: fix case where overwritten function takes 5+ args
|
||||||
|
push ra
|
||||||
|
push a0, a1, a2, a3
|
||||||
bal start
|
bal start
|
||||||
subi sp, sp, 4
|
nop
|
||||||
|
pop a0, a1, a2, a3
|
||||||
jal @overwritten
|
jal @overwritten
|
||||||
nop
|
nop
|
||||||
lw ra, 0(sp)
|
jpop ra
|
||||||
jr
|
|
||||||
addi sp, sp, 4
|
|
||||||
start:
|
start:
|
||||||
]]
|
]]
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
[cosf]: 0x80091F40
|
[cosf]: 0x80091F40
|
||||||
|
|
||||||
main:
|
main:
|
||||||
push ra, a0, s1, s3, s4
|
push 4, s1, s3, s4, ra
|
||||||
// s1: current actor ptr
|
// s1: current actor ptr
|
||||||
// s3: current actor type ptr
|
// s3: current actor type ptr
|
||||||
// s4: current actor type index
|
// s4: current actor type index
|
||||||
|
@ -70,12 +70,11 @@ continue:
|
||||||
bne s4, t0, typeloop
|
bne s4, t0, typeloop
|
||||||
addi s3, s3, @actorlist_dead_space
|
addi s3, s3, @actorlist_dead_space
|
||||||
|
|
||||||
jpop ra, a0, s1, s3, s4
|
jpop 4, s1, s3, s4, ra
|
||||||
|
|
||||||
process_actor: // args: a0. returns nothing.
|
process_actor: // args: a0. returns nothing.
|
||||||
// TODO: ignore bomb explosions, they share the same type
|
// TODO: ignore bomb explosions, they share the same type
|
||||||
push r0, ra, s0, s1
|
push 4, s0, s1, ra
|
||||||
// 0(sp) reserved for sinf/cosf
|
|
||||||
// s0: result of sin
|
// s0: result of sin
|
||||||
// s1: result of cos
|
// s1: result of cos
|
||||||
lh t0, 0(a0)
|
lh t0, 0(a0)
|
||||||
|
@ -128,7 +127,7 @@ process_actor: // args: a0. returns nothing.
|
||||||
sw t5, current_rotation
|
sw t5, current_rotation
|
||||||
|
|
||||||
process_actor_return:
|
process_actor_return:
|
||||||
jpop r0, ra, s0, s1
|
jpop 4, s0, s1, ra
|
||||||
|
|
||||||
rotations:
|
rotations:
|
||||||
.word 0x00000000 // pi*0/6
|
.word 0x00000000 // pi*0/6
|
||||||
|
|
|
@ -1034,31 +1034,37 @@ function Parser:instruction()
|
||||||
local addi = instructions['ADDI']
|
local addi = instructions['ADDI']
|
||||||
local w = instructions[h == 'PUSH' and 'SW' or 'LW']
|
local w = instructions[h == 'PUSH' and 'SW' or 'LW']
|
||||||
local jr = instructions['JR']
|
local jr = instructions['JR']
|
||||||
local registers = {}
|
local stack = {}
|
||||||
while not self:is_EOL() do
|
while not self:is_EOL() do
|
||||||
local r = self:register()
|
if self.tt == 'NUM' then
|
||||||
table.insert(registers, r)
|
if self.tok < 0 then
|
||||||
|
self:error("can't push a negative number of spaces")
|
||||||
|
end
|
||||||
|
for i=1,self.tok do
|
||||||
|
table.insert(stack, '')
|
||||||
|
end
|
||||||
|
self:advance()
|
||||||
|
else
|
||||||
|
table.insert(stack, self:register())
|
||||||
|
end
|
||||||
if not self:is_EOL() then
|
if not self:is_EOL() then
|
||||||
self:optional_comma()
|
self:optional_comma()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #registers == 0 then
|
if #stack == 0 then
|
||||||
self:error(h..' requires at least one argument')
|
self:error(h..' requires at least one argument')
|
||||||
end
|
end
|
||||||
if #registers >= 0x8000/4 then
|
|
||||||
self:error("that's way too many registers bub")
|
|
||||||
end
|
|
||||||
local args = {}
|
local args = {}
|
||||||
if h == 'PUSH' then
|
if h == 'PUSH' then
|
||||||
args.rt = 'SP'
|
args.rt = 'SP'
|
||||||
args.rs = 'SP'
|
args.rs = 'SP'
|
||||||
args.immediate = {'NEGATE', {'NUM', #registers*4}}
|
args.immediate = {'NEGATE', {'NUM', #stack*4}}
|
||||||
self:format_out(addi[3], addi[1], args, addi[4], addi[5])
|
self:format_out(addi[3], addi[1], args, addi[4], addi[5])
|
||||||
end
|
end
|
||||||
args.base = 'SP'
|
args.base = 'SP'
|
||||||
for i, r in ipairs(registers) do
|
for i, r in ipairs(stack) do
|
||||||
args.rt = r
|
args.rt = r
|
||||||
if r ~= 'R0' then
|
if r ~= '' then
|
||||||
args.offset = {'NUM', (i - 1)*4}
|
args.offset = {'NUM', (i - 1)*4}
|
||||||
self:format_out(w[3], w[1], args, w[4], w[5])
|
self:format_out(w[3], w[1], args, w[4], w[5])
|
||||||
end
|
end
|
||||||
|
@ -1070,7 +1076,7 @@ function Parser:instruction()
|
||||||
if h == 'POP' or h == 'JPOP' then
|
if h == 'POP' or h == 'JPOP' then
|
||||||
args.rt = 'SP'
|
args.rt = 'SP'
|
||||||
args.rs = 'SP'
|
args.rs = 'SP'
|
||||||
args.immediate = {'NUM', #registers*4}
|
args.immediate = {'NUM', #stack*4}
|
||||||
self:format_out(addi[3], addi[1], args, addi[4], addi[5])
|
self:format_out(addi[3], addi[1], args, addi[4], addi[5])
|
||||||
end
|
end
|
||||||
elseif h == 'NAND' then
|
elseif h == 'NAND' then
|
||||||
|
|
Loading…
Add table
Reference in a new issue