Created
January 21, 2022 02:18
-
-
Save karmic64/36e57bfcda0fd5f92ff591ead2e2fbeb to your computer and use it in GitHub Desktop.
Bill & Ted NES Mesen lua script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- bill & ted NES Mesen lua script | |
-- coded by karmic, jan 18-20, 2022 | |
figure_names = {"Cleopatra","Confucius","King Arthur","Christopher Columbus","Paul Revere","Jesse James","Al Capone","Elvis","Julius Caesar","Robin Hood","Rembrandt","William Shakespeare","George Washington","Sitting Bull","Thomas Edison","Marilyn Monroe","A stranger"} | |
bait_names = {"Major credit card","Fortune cookie","Holy grail","Compass","Megaphone","Uzi","Book of lawyer stuff","Headstone","Salad dressing","Bag-o-money","Paint roller","Stage prop","Pair of choppers","Lawn chair","Compact disc","Rose","Some stuff"} | |
good_stuff_names = {"Pudding","Firecracker","Textbook","Cassette tape","Coin","Key"} | |
-- helper functions | |
function concat11(lo, hi) | |
return lo | (hi << 8) | |
end | |
function readcpu(addr) | |
return emu.read(addr, emu.memType.cpuDebug, false) | |
end | |
function getprg(bank,addr) | |
if addr < 0xc000 then bank = 0 end | |
return (bank*0x4000)+(addr&0x3fff) | |
end | |
function readprg(bank, addr) | |
return emu.read(getprg(bank,addr), emu.memType.prgRom, false) | |
end | |
function readprglittle(bank,addr) | |
return emu.readWord(getprg(bank,addr), emu.memType.prgRom, false) | |
end | |
function readprgbig(bank, addr) | |
return concat11(readprg(bank,addr+1), readprg(bank,addr)) | |
end | |
-- ingame functions | |
function convert_coord(primary,secondary,cam,persp) | |
-- get point at secondary=0 | |
local offs = primary-cam | |
local x = offs*2 + 128 | |
local y | |
if persp & 0x80 == 0x80 then | |
-- horizontal -- | |
y = offs + 160 | |
else | |
-- vertical -- | |
y = 160 - offs | |
end | |
-- adjust point for secondary | |
if persp & 0x80 == 0x80 then | |
x = x - (secondary*2) | |
else | |
x = x + (secondary*2) | |
end | |
y = y + secondary | |
return x,y | |
end | |
-- main function | |
framecount = 0 | |
function main() | |
emu.clearScreen(); | |
-- only run if nmi vector is to main game | |
if emu.readWord(0x09, emu.memType.cpuDebug, false) ~= 0xa9cd then return end | |
-- get game state information | |
local level = readcpu(0x1c) | |
local world = readcpu(0x26) | |
local bait_index = readcpu(0x03c8) | |
local last_char = readcpu(0x0195) | |
local last_item = readcpu(0x0196) | |
local teleport_block = readcpu(0x0198) | |
local bait_flags = emu.readWord(0x03c5,emu.memType.cpuDebug,false) | |
local correct_figure = readcpu(0x03c7) | |
local correct_figure_index = readcpu(0x03c9) | |
local cam_coord_full = emu.readWord(0xd6,emu.memType.cpuDebug, false) | |
local cam_coord = cam_coord_full & 0xfff | |
local cam_sector = cam_coord_full >> 12 | |
local world_base = readprglittle(2, 0xcf56 + world*2) | |
local sector_screens = readcpu(0xda) | |
local sector_persp = sector_screens & 0x80 | |
sector_screens = sector_screens & 0x7f | |
local sector_cmds = readcpu(0x06e8) | |
local sector_cmd_base = emu.readWord(0x06e9,emu.memType.cpuDebug,false) | |
-- draw sector commands | |
do | |
local cmdptr = sector_cmd_base | |
local cmds = sector_cmds | |
while cmds > 0 do | |
local cmdid = readprg(2,cmdptr) | |
if cmdid > 0x0f then break end | |
local cmd_coord_full = readprgbig(2,cmdptr+1) | |
local cmd_sector = cmd_coord_full >> 12 | |
local cmd_coord = cmd_coord_full & 0xfff | |
-- get more detailed command info | |
local sec_coord = 0 | |
local direction = nil | |
local diameter = nil | |
-- secondary coordinate? | |
if cmdid == 5 or cmdid == 6 or cmdid == 7 or cmdid >= 9 then | |
sec_coord = emu.read(getprg(2,cmdptr+3),emu.memType.prgRom,true) | |
end | |
-- direction? | |
if cmdid == 3 then | |
direction = readprg(2,cmdptr+3) | |
elseif cmdid >= 9 then | |
direction = readprg(2,cmdptr+4) | |
end | |
-- diameter? | |
if cmdid == 6 or cmdid == 7 then | |
diameter = readprg(2,cmdptr+4) | |
end | |
if diameter then | |
-- draw a box with diameter | |
local x1,y1 = convert_coord(cmd_coord-diameter,sec_coord-diameter,cam_coord,sector_persp) | |
local x2,y2 = convert_coord(cmd_coord+diameter,sec_coord-diameter,cam_coord,sector_persp) | |
local x3,y3 = convert_coord(cmd_coord+diameter,sec_coord+diameter,cam_coord,sector_persp) | |
local x4,y4 = convert_coord(cmd_coord-diameter,sec_coord+diameter,cam_coord,sector_persp) | |
emu.drawLine(x1,y1, x2,y2, 0xff00ff) | |
emu.drawLine(x2,y2, x3,y3, 0xff00ff) | |
emu.drawLine(x3,y3, x4,y4, 0xff00ff) | |
emu.drawLine(x4,y4, x1,y1, 0xff00ff) | |
-- draw string describing the item | |
local strx = math.min(x1,x2,x3,x4)+2 | |
local stry = math.min(y1,y2,y3,y4)-12 | |
local item = readprg(2,cmdptr+5) | |
local str | |
local strbg = 0x7f000000 | |
local strcol = 0xffffff | |
if cmdid == 6 then | |
local bait = readcpu(0x019a+item+bait_index) | |
if bait > 0x0f then | |
str = "Already got" | |
else | |
str = bait_names[bait+1] | |
end | |
if bait == correct_figure and framecount % 20 >= 10 then | |
strbg = 0x7fbfbf00 | |
end | |
elseif cmdid == 7 then | |
local unav = item == last_item | |
item = item & 0x7f | |
if item > 0x06 then | |
str = "Invalid" | |
else | |
str = good_stuff_names[item+1] | |
end | |
if unav then | |
strx = strx - 20 | |
str = str.." (unavailable)" | |
end | |
end | |
emu.drawString(strx,stry,str,strcol,strbg) | |
elseif direction then | |
-- draw an arrow | |
local x,y = convert_coord(cmd_coord,sec_coord,cam_coord,sector_persp) | |
local xend,yend | |
local xa1,ya1,xa2,ya2 | |
if sector_persp == 0x80 then direction = (direction+2)&7 end | |
if direction == 0 then | |
-- north | |
xend = x + 20 | |
yend = y - 10 | |
xa1 = xend - 8 | |
ya1 = yend + 2 | |
xa2 = xend - 4 | |
ya2 = yend + 5 | |
elseif direction == 2 then | |
-- east | |
xend = x + 20 | |
yend = y + 10 | |
xa1 = xend - 8 | |
ya1 = yend - 2 | |
xa2 = xend - 4 | |
ya2 = yend - 5 | |
elseif direction == 4 then | |
-- south | |
xend = x - 20 | |
yend = y + 10 | |
xa1 = xend + 8 | |
ya1 = yend - 2 | |
xa2 = xend + 4 | |
ya2 = yend - 5 | |
elseif direction == 6 then | |
-- west | |
xend = x - 20 | |
yend = y - 10 | |
xa1 = xend + 8 | |
ya1 = yend + 2 | |
xa2 = xend + 4 | |
ya2 = yend + 5 | |
end | |
emu.drawLine(x,y,xend,yend,0xff00ff) | |
emu.drawLine(xend,yend,xa1,ya1,0xff00ff) | |
emu.drawLine(xend,yend,xa2,ya2,0xff00ff) | |
-- output string | |
local strx = math.min(x,xend) - 10 | |
local stry = math.min(y,yend) - 12 | |
local str | |
local strbg = 0x7f000000 | |
local strcol = 0xffffff | |
if cmdid == 0x0b then | |
str = "Blocked" | |
elseif cmdid == 0x0c then | |
str = "Exit" | |
elseif cmdid == 0x0d then | |
str = "Jail exit" | |
elseif cmdid == 0x0e then | |
if teleport_block == 0x0a then | |
str = "Teleporter" | |
else | |
strx = strx - 10 | |
str = string.format("Blocked teleporter (%02X)",teleport_block) | |
end | |
elseif cmdid == 0x0f then | |
str = "Unknown door $f" | |
elseif cmdid == 0x09 then | |
local charid = readprg(2,cmdptr+0x0e) | |
if last_char == charid then | |
strx = strx - 20 | |
str = "Unavailable character" | |
else | |
str = "Character" | |
end | |
elseif cmdid == 0x0a then | |
local figix = readprg(2,cmdptr+0x0d) | |
if figix == correct_figure_index and framecount % 20 >= 10 then | |
strbg = 0x7f00ffff | |
end | |
strx = strx - 10 | |
if figix == correct_figure_index then | |
strx = strx - 10 | |
if bait_flags & (1<<correct_figure) == 0 and framecount % 150 >= 75 then | |
strx = strx - 20 | |
str = "...but you need a " .. bait_names[correct_figure+1] .. "." | |
else | |
str = figure_names[correct_figure+1] .. " is here!" | |
end | |
else | |
str = "Historical figure" | |
end | |
end | |
emu.drawString(strx,stry,str,strcol,strbg) | |
elseif cmdid ~= 8 then | |
-- otherwise just draw a line through the thing (ignore crossroads) | |
local x,y = convert_coord(cmd_coord,sec_coord,cam_coord,sector_persp) | |
if sector_persp == 0x80 then | |
emu.drawLine(x-512,y+256,x+512,y-256,0xff00ff) | |
else | |
emu.drawLine(x-512,y-256,x+512,y+256,0xff00ff) | |
end | |
emu.drawString(x,y-12,cmdid,0xffffff,0x000000) | |
end | |
-- next command | |
cmdptr = cmdptr + readcpu(0xafc1 + cmdid) | |
cmds = cmds-1 | |
end | |
end | |
-- camera info | |
emu.drawString(4,212,string.format("Camera: %i:%03X",cam_sector,cam_coord),0xffffff,0x9f0000ff) | |
framecount = framecount + 1 | |
end | |
-- init | |
emu.addEventCallback(main, emu.eventType.startFrame) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment