Added a lot of luaScripts by XKeeper

This commit is contained in:
adelikat 2009-03-29 22:47:19 +00:00
parent d2a3b310b3
commit 24f1e23c47
13 changed files with 3108 additions and 7 deletions

View File

@ -0,0 +1,210 @@
--Bugs Bunny Birthday Blowout
--Written by XKeeper
--Creates Lag and Sprite counters as well as Camera position
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function box(x1,y1,x2,y2,color)
if (x1 >= 0 and x1 <= 255 and x2 >= 0 and x2 <= 255 and y1 >= 0 and y1 <= 244 and y2 >= 0 and y2 <= 244) then
gui.drawbox(x1,y1,x2,y2,color);
end;
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function filledbox(x1,y1,x2,y2,color)
for i = 0, math.abs(y1 - y2) do
line(x1,y1 + i,x2,y1 + i,color);
end;
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function lifebar(x, y, sx, sy, a1, a2, oncolor, offcolor, noborder)
-- this function will have the effect of drawing an HP bar
-- keep in mind xs and ys are 2px larger to account for borders
x1 = x;
x2 = x + sx + 4;
y1 = y;
y2 = y + sy + 4;
w = math.floor(a1 / math.max(1, a1, a2) * sx);
if not a2 then w = 0 end;
if (noborder) then
box(x1 + 1, y1 + 1, x2 - 1, y2 - 1, "#000000");
else
box(x1 + 1, y1 + 1, x2 - 1, y2 - 1, "#ffffff");
box(x1 , y1 , x2 , y2 , "#000000");
end;
if (w < sx) then
filledbox(x1 + w + 2, y1 + 2, x2 - 2, y2 - 2, offcolor);
end;
if (w > 0) then
filledbox(x1 + 2, y1 + 2, x1 + 2 + w, y2 - 2, oncolor);
end;
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function line(x1,y1,x2,y2,color)
if (x1 >= 0 and x1 <= 255 and x2 >= 0 and x2 <= 255 and y1 >= 0 and y1 <= 244 and y2 >= 0 and y2 <= 244) then
local success = pcall(function() gui.drawline(x1,y1,x2,y2,color) end);
if not success then
text(60, 224, "ERROR: ".. x1 ..",".. y1 .." ".. x2 ..",".. y2);
end;
end;
end;
function text(x,y,str)
if (x >= 0 and x <= 255 and y >= 0 and y <= 240) then
gui.text(x,y,str);
end;
end;
function pixel(x,y,color)
if (x >= 0 and x <= 255 and y >= 0 and y <= 240) then
gui.drawpixel(x,y,color);
end;
end;
function drawpos(cx, cy, ex, ey, n)
sx = ex - cx;
sy = ey - cy;
num = "";
if n then
num = string.format("%02X", n);
end;
if sx >= 0 and sx <= 255 and sy >= 0 and sy <= 244 then
line(sx, sy, sx + 16, sy + 0, "#ff0000");
line(sx, sy, sx + 0, sy + 16, "#ff0000");
text(sx, sy, num);
elseif sx < 0 and sy >= 0 and sy <= 244 then
line(0, sy, 16, sy, "#ff0000");
text(4, sy, num);
elseif sx > 255 and sy >= 0 and sy <= 244 then
line(239, sy, 255, sy, "#ff0000");
text(243, sy, num);
elseif sy < 0 and sx >= 0 and sx <= 256 then
line(sx, 8, sx, 24, "#ff0000");
text(sx, 8, num);
elseif sy > 244 and sx >= 0 and sx <= 256 then
line(sx, 212, sx, 244, "#ff0000");
text(sx, 216, num);
end;
end;
lagdetectorold = 0;
timer = 0;
lagframes = 0;
lastlag = 0;
while (true) do
timer = timer + 1;
lagdetector = memory.readbyte(0x00f5);
-- if lagdetector == lagdetectorold then
if AND(lagdetector, 0x20) == 0x20 then
-- if lagdetector == 0x0C then
lagframes = lagframes + 1;
else
if lagframes ~= 0 then
lastlag = lagframes;
end;
lagframes = 0;
lagdetectorold = lagdetector;
end;
memory.writebyte(0x00f5, OR(lagdetector, 0x20));
playerx = memory.readbyte(0x0432) + memory.readbyte(0x0433) * 0x100;
playery = memory.readbyte(0x0435) + memory.readbyte(0x0436) * 0x100;
screenx = memory.readbyte(0x0456) + memory.readbyte(0x0457) * 0x100;
screeny = memory.readbyte(0x0458) + memory.readbyte(0x0459) * 0x100;
text( 8, 8, string.format("%04X, %04X", playerx, playery));
text( 8, 16, string.format("%04X, %04X", screenx, screeny));
drawpos(screenx, screeny, playerx, playery);
tmp = 0;
for i = 0, 0xb do
offset = 0x7680 + i * 0x20;
enemyt = memory.readbyte(offset);
enemyx = memory.readbyte(offset + 2) + memory.readbyte(offset + 3) * 0x100;
enemyy = memory.readbyte(offset + 4) + memory.readbyte(offset + 5) * 0x100;
if enemyt ~= 0xff then
-- text(160, 8 + 8 * tmp, string.format("%02X: %02X <%04X, %04X>", i, enemyt, enemyx, enemyy));
drawpos(screenx, screeny, enemyx, enemyy, i);
tmp = tmp + 1;
end
end;
text(142, 192, string.format("%02d lag frames", lastlag));
text(142, 216, string.format("%02d active sprites", tmp));
-- box(2, 208, 2 + 8 * lastlag, 210, "#ff4444");
-- box(2, 209, 2 + 8 * lastlag, 211, "#ff4444");
-- box(2, 212, 2 + 8 * tmp, 213, "#4444ff");
-- box(2, 214, 2 + 8 * tmp, 215, "#4444ff");
lifebar(144, 200, 100, 4, lastlag, 8, "#ffcc22", "#000000");
lifebar(144, 208, 100, 4, tmp, 12, "#4488ff", "#000000");
FCEU.frameadvance();
end;

View File

@ -0,0 +1,90 @@
--Exciting Bike - Speedometer
--Written by XKeeper
--Shows the speedometer (obviously)
require("x_functions");
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(4);
end;
function gameloop()
end;
gui.register(gameloop);
barcolors = {};
barcolors[0] = "#000000";
barcolors[1] = "#880000";
barcolors[2] = "#ff0000";
barcolors[3] = "#eeee00";
barcolors[4] = "#00ff00";
barcolors[5] = "#00ffff";
barcolors[6] = "#0000ff";
barcolors[7] = "#ff00ff";
barcolors[8] = "#ffffff";
barcolors[9] = "#123456";
lastvalue = {};
justblinked = {};
lastzero = {};
timer = 0;
speed = 0;
while (true) do
timer = timer + 1;
lastvalue['speed'] = speed;
speed = memory.readbyte(0x0094) * 0x100 + memory.readbyte(0x0090);
positionx = memory.readbyte(0x0050) * 0x100 + memory.readbyte(0x0394);
timerspeed = 3 - memory.readbyte(0x004c);
timerslant = math.max(0, memory.readbyte(0x0026) - 1);
if memory.readbyte(0x0303) ~= 0x8E then
text(255, 181, "Didn't advance this frame");
end;
speedadj1 = math.fmod(speed, 0x100);
speedadj2 = math.fmod(math.floor(speed / 0x100), #barcolors + 1);
speedadj3 = math.fmod(speedadj2 + 1, #barcolors + 1);
lifebar( 61, 11, 100, 4, speedadj1, 0x100, barcolors[speedadj3], barcolors[speedadj2], "#000000", "#ffffff");
text( 0, 4 + 6, string.format("Speed: %4X", speed));
text( 1, 4 + 14, string.format("S.Chg: %4d", speed - lastvalue['speed']));
text( 20, 222, " 2009 Xkeeper - http://jul.rustedlogic.net/ ");
line( 21, 231, 232, 231, "#000000");
FCEU.frameadvance();
end;

View File

@ -0,0 +1,221 @@
--Exicitebike
--Written by XKeeper
--Shows various stats including a RAM map & speed
require("x_functions");
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(4);
end;
function gameloop()
end;
gui.register(gameloop);
barcolors = {};
barcolors[0] = "#000000";
barcolors[1] = "#880000";
barcolors[2] = "#ff0000";
barcolors[3] = "#eeee00";
barcolors[4] = "#00ff00";
barcolors[5] = "#00ffff";
barcolors[6] = "#0000ff";
barcolors[7] = "#ff00ff";
barcolors[8] = "#ffffff";
barcolors[9] = "#123456";
lastvalue = {};
justblinked = {};
lastzero = {};
timer = 0;
speed = 0;
while (true) do
timer = timer + 1;
lastvalue['speed'] = speed;
speed = memory.readbyte(0x0094) * 0x100 + memory.readbyte(0x0090);
positionx = memory.readbyte(0x0050) * 0x100 + memory.readbyte(0x0394);
timerspeed = 3 - memory.readbyte(0x004c);
timerslant = math.max(0, memory.readbyte(0x0026) - 1);
if memory.readbyte(0x0303) ~= 0x8E then
text(255, 181, "Didn't advance this frame");
end;
speedadj1 = math.fmod(speed, 0x100);
speedadj2 = math.fmod(math.floor(speed / 0x100), #barcolors + 1);
speedadj3 = math.fmod(speedadj2 + 1, #barcolors + 1);
lifebar( 61, 11, 100, 4, speedadj1, 0x100, barcolors[speedadj3], barcolors[speedadj2], "#000000", "#ffffff");
text(198, 9, string.format("Speed %2d", timerspeed));
text(196, 17, string.format(" Slant %2d", timerslant));
box( 186, 10, 198, 18, "#000000");
box( 186, 18, 198, 26, "#000000");
if timerspeed == 0 then
filledbox(187, 11, 197, 17, "#00ff00");
if memory.readbyte(0x00B0) ~= 0 then
temp = "->";
else
temp = "(B)";
end;
text( 0, 50, string.format("Hold %s to maintain speed", temp));
else
filledbox(187, 11, 197, 17, "#880000");
end;
if timerslant <= 1 then
filledbox(187, 19, 197, 25, "#00ff00");
text( 0, 58, string.format("Use < + > to modify angle"));
else
filledbox(187, 19, 197, 25, "#880000");
end;
text( 0, 4 + 6, string.format("Speed: %4X", speed));
text( 1, 4 + 14, string.format("S.Chg: %4d", speed - lastvalue['speed']));
value = memory.readbyte(0x0064);
lifebar( 1, 1, 240, 6, value, 0xFF, "#ffffff", "#111144", false, "#000000");
tp = math.floor(value / 255 * 240) + 4;
text(tp, 1, string.format("%02X", value));
drawerpos = memory.readbyte(0x00e8);
screenpos = memory.readbyte(0x00eb);
for x = 0, 0x3F do
for y = 0, 5 do
offset = y * 0x40 + x + 0x400;
value = memory.readbyte(offset);
color = string.format("#%02x%02x%02x", value, value, value);
x = math.fmod(x - screenpos, 0x40);
while (x < 0) do
x = x + 0x40;
end;
box(x * 3 + 8, y * 3 + 28, x * 3 + 9, y * 3 + 30, color);
box(x * 3 + 9, y * 3 + 28, x * 3 +10, y * 3 + 30, color);
-- pixel(x * 3 + 9, y * 3 + 28, color);
end;
end;
drawerpos = drawerpos - screenpos;
while (drawerpos < 0) do
drawerpos = drawerpos + 0x40;
end;
box(math.fmod(drawerpos, 0x40) * 3 + 7, 27, math.fmod(drawerpos, 0x40) * 3 + 11, 5 * 3 + 31, "#dd0000");
-- box(math.fmod(screenpos, 0x40) * 3 + 7, 25, math.fmod(screenpos, 0x40) * 3 + 11, 5 * 3 + 31, "#00ff00");
box(math.fmod(0, 0x40) * 3 + 7, 27, math.fmod(0, 0x40) * 3 + 11, 5 * 3 + 31, "#00ff00");
for i = 0, 5 do
offset = 0x00e8 + i;
if not lastzero[offset] then
lastzero[offset] = {};
end;
value = memory.readbyte(offset);
if lastvalue[offset] and lastvalue[offset] ~= value then
if not justblinked[offset] then
color = "#ffffff";
else
color = "#dd0000";
end;
justblinked[offset] = true;
else
color = "#dd0000";
justblinked[offset] = false;
end;
lifebar( 3, 190 + i * 8, 240, 6, value, 240, color, "#111144", false, "#000000");
tp = math.floor(value / 240 * 240) + 4;
text(tp, 190 + i * 8, string.format("%02X", value));
if lastzero[offset]['time'] then
text(165, 190 + i * 8, string.format("%7sa %4df", string.format("%.2f", (lastzero[offset]['total'] / lastzero[offset]['samples'])), lastzero[offset]['time']));
end;
if value == 0 and not lastzero[offset]['uhoh'] then
if lastzero[offset]['fr'] then
lastzero[offset]['time'] = timer - lastzero[offset]['fr'];
if lastzero[offset]['total'] then
lastzero[offset]['total'] = lastzero[offset]['total'] + lastzero[offset]['time'];
lastzero[offset]['samples'] = lastzero[offset]['samples'] + 1;
else
lastzero[offset]['total'] = lastzero[offset]['time'];
lastzero[offset]['samples'] = 1;
end;
end;
lastzero[offset]['fr'] = timer;
lastzero[offset]['uhoh'] = true;
elseif value ~= 0 then
lastzero[offset]['uhoh'] = false;
end;
lastvalue[offset] = value;
end;
--[[
startoffset = 0x5E0;
s = 0x120;
xs = 0x40;
ys = math.floor(s / xs);
for x = 0, xs - 1 do
for y = 0, ys - 1 do
offset = y * xs + x + startoffset;
value = memory.readbyte(offset);
if value == 0x40 then
color = "clear";
else
value = math.fmod(value * 0x10, 0x100);
color = string.format("#%02x%02x%02x", value, value, value);
end;
box(x * 3 + 8, y * 3 + 64, x * 3 + 10, y * 3 + 66, color);
pixel(x * 3 + 9, y * 3 + 65, color);
end;
end;
]]
FCEU.frameadvance();
end;

View File

@ -0,0 +1,186 @@
--Galaxian
--Written by XKeeper
--Accesses the Music Player Easter Egg and displays the songs & information
require "x_functions";
require "x_interface";
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu:5/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(6);
end;
function musicplayer()
resets = memory.readbyte(0x0115);
song = memory.readbyte(0x0002);
songlua = math.max(1, math.floor(resets / 45));
speed = memory.readbyte(0x0004);
speedde = memory.readbyte(0x0104); -- it's really an AND. But the only two values used are 0F and 07, so this modulous works.
pos = memory.readbyte(0x0000);
note = memory.readbyte(0x0001);
offsetb = song * 0x0100 + 0x4010 - 1;
offset = song * 0x0100 + pos - 1 + 0x4010;
note1 = 0x10 - math.floor(note / 0x10);
note2 = math.fmod(note, 0x10);
if note1 == 0x10 then note1 = 0 end;
text( 35, 42, string.format("Song Position: %02X%02X", song, pos));
text( 40, 50, string.format("ROM Offset: %04X", offset));
text( 43, 58, string.format("Song Speed: %02X", speed));
text(105, 66, string.format(" %02X", math.fmod(speedde, speed)));
lifebar(186, 21, 64, 4, note1, 15, "#8888ff", "#000066", false, "#ffffff");
lifebar(186, 29, 64, 4, note2, 15, "#8888ff", "#000066", false, "#ffffff");
text(178, 20, string.format("%X\n%X", note1, note2));
lifebar( 44, 67, 64, 4, math.fmod(speedde, speed), speed, "#8888ff", "#000066", false, "#ffffff");
if control.button(75, 90, 84, 1, "Toggle hex viewer") then
hexmap = not hexmap;
end;
if hexmap then
songdata = {};
songdata2 = {};
for i = 0x00, 0xFF do
if i >= songs[songlua]['st'] and i <= songs[songlua]['en'] or true then
o = string.format("%02X", rom.readbyte(offsetb + i));
else
o = "";
end;
x = math.fmod(i, 0x10);
y = math.floor(i / 0x70);
if not songdata2[x] then
songdata2[x] = {};
end;
if not songdata2[x][y] then
songdata2[x][y] = o;
-- songdata2[x][y] = string.format("%02X", y);
else
songdata2[x][y] = songdata2[x][y] .."\n".. o;
end;
end;
for x = 0, 0x0F do
text(29 + x * 14, 100 + 8 * 0, songdata2[x][0]);
text(29 + x * 14, 100 + 8 * 7, songdata2[x][1]);
text(29 + x * 14, 100 + 8 * 14, songdata2[x][2]);
end;
oboxx = 29 + math.fmod(pos, 0x10) * 14;
oboxy = 100 + 8 * math.floor(pos / 0x10);
c = "#ff0000";
if math.fmod(timer, 4) < 2 then
c = "#FFFFFF";
end;
box(oboxx, oboxy + 0, oboxx + 14, oboxy + 10, c);
end;
if pos >= songs[songlua]['en'] then --and pos == 0xFE then
if not songs[songlua]['xx'] then
memory.writebyte(0x0104, 0xFF);
-- text(50, 50, "LOCK");
else
memory.writebyte(0x0115, songs[songs[songlua]['xx']]['rv']);
memory.writebyte(0x0002, songs[songs[songlua]['xx']]['sv']);
memory.writebyte(0x0004, songs[songs[songlua]['xx']]['sp']);
memory.writebyte(0x0000, songs[songs[songlua]['xx']]['st']);
end;
end;
for id, val in pairs(songs) do
if id == songlua then
c = "#8888ff";
if math.fmod(timer, 4) < 2 then
c = "#FFFFFF";
end;
else
c = nil;
end;
if control.button(195, 33 + 11 * id, 57, 1, string.format("Play song %d", id), c, true) then
-- resetrequired = true;
-- memory.register(0x0104, nil);
memory.writebyte(0x0115, val['rv']);
memory.writebyte(0x0002, val['sv']);
memory.writebyte(0x0004, val['sp']);
memory.writebyte(0x0000, val['st']);
end;
end;
if resetrequired then
text(50, 85, "Please soft-reset game.");
if movie.framecount() == 0 then
resetrequired = false;
end;
end;
end;
songs = {
-- resets song `id` speed start end
{ rv = 0x2E, sv = 0x1B, sp = 0x0F, st = 0x00, en = 0xC6 },
{ rv = 0x5A, sv = 0x18, sp = 0x07, st = 0x00, en = 0xC2 },
{ rv = 0x87, sv = 0x06, sp = 0x0F, st = 0x00, en = 0x7F },
{ rv = 0xB4, sv = 0x16, sp = 0x0F, st = 0x50, en = 0xAF },
{ rv = 0xE1, sv = 0x1A, sp = 0x0F, st = 0x80, en = 0xF8, xx = 0x01 },
};
timer = 0;
hexmap = true;
while true do
timer = timer + 1;
input.update();
if memory.readbyte(0x0101) == 1 then
musicplayer();
else
filledbox(23, 49, 233, 130, "#000000");
text( 25, 50, "Normally you'd have to do something insane");
text( 52, 58, "like push RESET 45 times and");
text( 56, 66, "hold A+B on P2's controller.");
text( 28, 82, "Lucky for you, though, we borrowed this.");
text( 73, 90, "Feel free to use it.");
text( 73, 119, "(Yeah, we've got that)");
timer2 = math.fmod(timer, 60);
if timer2 >= 30 then timer2 = 60 - timer2; end;
timer2 = math.floor((timer2 / 30) * 255);
c = string.format("#%02X%02XFF", timer2, timer2);
if control.button(110, 106, 37, 1, " EASY ", c, "#ffffff") then
memory.writebyte(0x0101, 0x01);
memory.writebyte(0x0115, songs[2]['rv']);
memory.writebyte(0x0002, songs[2]['sv']);
memory.writebyte(0x0004, songs[2]['sp']);
memory.writebyte(0x0000, songs[2]['st']);
FCEU.softreset();
-- text(1, 1, 'woohoo');
end;
end;
FCEU.frameadvance();
end;

View File

@ -0,0 +1,266 @@
--Machrider - Speedometer
--Written by XKeeper
require("x_functions");
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(4);
end;
function savereplay(filename, replaydata)
stringout = "";
f = io.open(filename, "w");
for k, v in pairs(replaydata) do
stringout = string.format("%d:%d:%d\n", k, v['speed'], v['gear']);
f:write(stringout);
end;
f:close();
return true;
end;
olddist = 0;
lastcount = 0;
counter = 0;
altunittype = true;
waittimer = 0;
autoshift = true; -- auto-handle shifting? for the lazy people
speedgraph = {};
timer = 0;
graphlen = 240;
graphheight = 100;
maxspeed = 500;
dorecording = false;
while true do
joydata = joypad.read(1);
if joydata['select'] and not joydatas then
altunittype = not altunittype;
joydatas = true;
elseif joydata['up'] and joydata['B'] and not joydatas and dorecording then
savereplay("machriderspeed.xrp", speedgraph);
joydatas = true;
saved = true;
elseif not joydata['select'] then
joydatas = false;
end;
if saved and dorecording then
text(100, 140, "Saved data!");
end;
speedlow = memory.readbyte(0x0040);
speedhigh = memory.readbyte(0x0041);
speed = speedhigh * 0x100 + speedlow;
rpmlow = memory.readbyte(0x0042);
rpmhigh = memory.readbyte(0x0043);
rpm = rpmhigh * 0x100 + rpmlow;
gear = memory.readbyte(0x0032);
if autoshift and waittimer <= 0 then
if gear < 2 then
memory.writebyte(0x0032, 2);
-- waittimer = 6;
elseif speed <= 250 and gear > 2 then
memory.writebyte(0x0032, math.max(gear - 1, 2));
-- waittimer = 6;
elseif speed >= 255 and gear < 3 then
memory.writebyte(0x0032, math.min(gear + 1, 3));
-- waittimer = 6;
end;
end;
waittimer = waittimer - 1;
if dorecording then
timer = timer + 1;
speedgraph[timer] = {speed = speed, gear = gear};
if timer > graphlen then
temp = timer - graphlen - 1;
-- speedgraph[temp] = nil;
end;
for i = timer - graphlen, timer do
if speedgraph[i] then
xp = ((i + 3) - timer) + graphlen;
yp = graphheight - (speedgraph[i]['speed'] / maxspeed) * graphheight;
if (speedgraph[i]['gear'] == 0) then
c = "blue";
elseif (speedgraph[i]['gear'] == 1) then
c = "green";
elseif (speedgraph[i]['gear'] == 2) then
c = "#cccc00";
elseif (speedgraph[i]['gear'] == 3) then
c = "red";
else
c = "gray";
end;
-- pixel(((i + 3) - timer) + 60, 50 - speedgraph[i], "#ffffff");
line(xp, 10, xp, graphheight + 10, "#000000");
line(xp, yp + 10, xp, graphheight + 10, c);
pixel(xp, yp + 10, "#ffffff");
-- pixel(((i + 3) - timer) + 60, 50 - speedgraph[i], "#ffffff");
end;
end;
end;
--[[
dist = math.fmod(memory.readbyte(0x0062), 0x20);
text( 8, 15, string.format("%02X %4dfr/mv", dist, lastcount));
if dist > olddist then
lastcount = counter;
counter = 0;
end;
olddist = dist;
counter = counter + 1;
lifebar( 8, 8, 0x1F * 5, 3, dist, 0x1F, "#ffffff", "#0000FF", "#000000", "#ffffff");
--]]
barwidth = 100;
segmentwidth = 2;
pct = speed / maxspeed * 100;
if altunittype then
speedadjust = (65535 / 60 / 60 / 60) * speed; -- rough approximation of km/h
text(barwidth * segmentwidth - 2, 221, string.format(" %3.1dkm/h", speedadjust));
else
text(barwidth * segmentwidth - 2, 221, string.format(" %3d", speed));
end;
box(2, 221, barwidth * segmentwidth + 2, 230, "#000000");
box(2, 222, barwidth * segmentwidth + 2, 229, "#000000");
box(2, 223, barwidth * segmentwidth + 2, 228, "#000000");
box(2, 224, barwidth * segmentwidth + 2, 227, "#000000");
box(2, 225, barwidth * segmentwidth + 2, 226, "#000000");
lastseg = false;
if pct > 0 then
for bl = 1, math.min(maxspeed - 1, speed) do
pct = bl / maxspeed;
segment = math.floor(pct * barwidth);
if segment ~= lastseg then
if pct < 0.50 then
val = math.floor(pct * 2 * 0xFF);
segcolor = string.format("#%02XFF00", val);
elseif pct < 0.90 then
val = math.floor(0xFF - (pct - 0.5) * 100/40 * 0xFF);
segcolor = string.format("#FF%02X00", val);
elseif bl < maxspeed then
val = math.floor((pct - 0.90) * 10 * 0xFF);
segcolor = string.format("#FF%02X%02X", val, val);
else
segcolor = "#ffffff";
end;
yb = math.max(math.min(3, (pct * 100 - 50)), 0);
-- box(segment * segmentwidth + 3, 225 - yb, segment * segmentwidth + 3 + (segmentwidth - 2), 229, segcolor);
box(segment * segmentwidth + 3, 225 - yb, segment * segmentwidth + 3, 229, segcolor);
-- box(bl * 3 + 3, 218, bl * 3 + 4, 225, segcolor);
-- line(bl * 3 + 4, 218, bl * 3 + 4, 225, segcolor);
end;
lastseg = segment;
end;
end;
maxrpm = 0x7F;
barwidth = 104;
segmentwidth = 1;
pct = rpmhigh / maxrpm * 100;
line(2, 220, (barwidth + 2) * segmentwidth + 2, 220, "#000000");
if autoshift then
text( 2, 203, string.format("AUTO %1d", gear + 1));
else
text( 2, 203, string.format("Manual %1d", gear + 1));
end;
if altunittype then
text( 2, 211, string.format("%5dRPM", math.min(9999, rpm * .25)));
else
text( 2, 211, string.format("%5dRPM", rpm));
end;
rpmhigh = math.min(maxrpm + 10, rpmhigh);
lastseg = false;
if pct > 0 then
for bl = 1, rpmhigh do
pct = bl / maxrpm;
segment = math.floor(pct * barwidth);
if segment ~= lastseg then
if pct < 0.70 then
val = math.floor(pct * (100/70) * 0xFF);
segcolor = string.format("#%02XFF00", val);
elseif pct < 0.90 then
val = math.floor(0xFF - (pct - 0.7) * 100/20 * 0xFF);
segcolor = string.format("#FF%02X00", val);
elseif bl < maxrpm then
val = math.floor((pct - 0.90) * 10 * 0xFF);
segcolor = string.format("#FF%02X%02X", val, val);
else
segcolor = "#ffffff";
end;
yb = math.floor(math.max(math.min(4, segment - 99), 0) / 2);
-- box(segment * segmentwidth + 3, 225 - yb, segment * segmentwidth + 3 + (segmentwidth - 2), 229, segcolor);
segment = math.min(segment, barwidth);
box(segment * segmentwidth + 3, 221, segment * segmentwidth + 3, 223 - yb, segcolor);
-- box(bl * 3 + 3, 218, bl * 3 + 4, 225, segcolor);
-- line(bl * 3 + 4, 218, bl * 3 + 4, 225, segcolor);
end;
lastseg = seg;
end;
end;
FCEU.frameadvance();
end;

View File

@ -0,0 +1,97 @@
--SMB area scrambler
--Randomly changes the level contents. Doesn't garuantee a winnable level (nor does it guarantee it won't crash the game)
--Written by XKeeper
require("x_functions");
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(4);
end;
function areascrambler()
end;
function gameloop()
joyin = joypad.read(1);
if joyin['select'] then
memory.writebyte(0x00e7, math.random(0, 0xFF));
memory.writebyte(0x00e8, math.random(0, 0xFF));
memory.writebyte(0x00e9, math.random(0, 0xFF));
memory.writebyte(0x00ea, math.random(0, 0xFF));
memory.writebyte(0x0750, math.random(0, 0xFF));
end;
if joyin['up'] then
memory.writebyte(0x009F, -5);
memory.writebyte(0x07F8, 3);
memory.writebyte(0x0722, 0xFF)
end;
screenpage = memory.readbyte(0x071a);
screenxpos = memory.readbyte(0x071c);
arealow = memory.readbyte(0x00e7);
areahigh = memory.readbyte(0x00e8);
enemylow = memory.readbyte(0x00e9);
enemyhigh = memory.readbyte(0x00ea);
unknown = memory.readbyte(0x0750);
text( 6, 30, string.format("Position: %02X %02X", screenpage, screenxpos));
text( 19, 38, string.format("Area: %02X %02X", areahigh, arealow));
text( 13, 46, string.format("Enemy: %02X %02X", enemyhigh, enemylow));
text( 13, 54, string.format("?: %02X", unknown));
end;
function areascramble()
memory.writebyte(0x00e7, math.random(0, 0xFF));
memory.writebyte(0x00e8, math.random(0, 0xFF));
end;
function enemyscramble()
memory.writebyte(0x00e9, math.random(0, 0xFF));
memory.writebyte(0x00ea, math.random(0, 0xFF));
end;
gui.register(gameloop);
memory.register(0x00e8, areascramble);
memory.register(0x00ea, enemyscramble);
while (true) do
memory.writebyte(0x079F, 2);
FCEU.frameadvance();
end;

View File

@ -0,0 +1,353 @@
--Super Mario Bros. - Jetpack
--Written by XKeeper
--A fun script that gives mario a "Jetback"
require("x_functions");
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(4);
end;
function doballs()
count = 0;
for k, v in pairs(balls) do
v['x'] = v['x'] + v['xs'];
v['y'] = v['y'] + v['ys'];
v['ys'] = v['ys'] - 0.1;
v['life'] = v['life'] - 1;
if v['x'] < 0 or v['x'] > 254 or v['y'] < 0 or v['y'] > 243 or v['life'] < 0 then
balls[k] = nil;
else
balls[k] = v;
-- pixel(v['x'], v['y'], "#FFFFFF");
colkey = math.ceil(255 * (5 - math.max(math.min(5, (v['life'] / 15)), 0)) / 5);
if v['c'] >= 0 then
color = string.format("#%02X%02X%02X", v['c'], v['c'], v['c']);
-- color = string.format("#%02X%02X%02X", v['c'] * .8, v['c'] * .5, v['c'] * 0);
else
color = string.format("#%02X0000", v['c'] * -1 , 0, 0);
end;
if v['life'] > 45 then
box(v['x'], v['y'], v['x'] + 1, v['y'] + 1, color);
else
pixel(v['x'], v['y'], color);
end;
count = count + 1;
end;
end;
-- lifebar( 2, 140, 249, 10, spower, 400, "#ffffff", "#000044", "#bbbbff");
return count;
end;
function nojumping()
memory.writebyte(0x000a, AND(memory.readbyte(0x000a), 0x7F));
return true;
end;
function nomoving()
joyput = joypad.read(1);
if (joyput['left'] or joyput['right']) then
memory.writebyte(0x000c, 0);
end;
return true;
end;
function areascrambler()
memory.writebyte(0x00e7, math.random(0, 0xFF));
memory.writebyte(0x00e8, math.random(0, 0xFF));
end;
function enemyscrambler()
memory.writebyte(0x00e9, math.random(0, 0xFF));
memory.writebyte(0x00ea, math.random(0, 0xFF));
end;
--[[
memory.register(0x00e8, areascrambler);
memory.register(0x00ea, enemyscrambler);
--]]
-- gui.register(gameloop);
memory.register(0x000a, nojumping);
memory.register(0x000c, nomoving);
testcount = 0;
balls = {};
z = 0;
timer = 0;
jmax = 500;
jlife = 500; -- jmax;
refillrate = 0.020;
msgdisp = 300;
rechargerate = 0;
while (true) do
timer = timer + 1;
if timer < msgdisp then
yo = (((math.max(0, (timer + 60) - msgdisp))) ^ 2) / 50;
text(20, 50 - yo, "2009 Xkeeper - http://jul.rustedlogic.net/");
text(49, 64 - yo, "A: Jetpack Left/Right: Move");
text(53, 72 - yo, " B button: Turbo boost! ");
end;
invincible = false;
if memory.readbyte(0x079F) >= 1 then
cyclepos = math.abs(15 - math.fmod(timer, 30)) / 15;
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0xFF));
barcolor = "#" .. warningboxcolor .. warningboxcolor .."ff";
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0x80) + 0x7F);
barcolor2 = "#0000" .. warningboxcolor;
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0x40));
barcolor3 = "#0000" .. warningboxcolor;
-- barcolor3 = "#000000";
jlife = math.min(jmax, jlife + (jmax - jlife) / 25 + 0.25);
rechargerate = -0.025;
invincible = true;
elseif jlife <= jmax * 0.25 then
cyclepos = math.abs(15 - math.fmod(timer, 30)) / 15;
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0xFF));
barcolor = "#ff" .. warningboxcolor .. warningboxcolor;
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0x80) + 0x7F);
barcolor2 = "#" .. warningboxcolor .. "0000";
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0x40));
barcolor3 = "#" .. warningboxcolor .. "0000";
-- barcolor3 = "#000000";
else
barcolor = "#ffffff";
barcolor2 = "#ff4444";
barcolor3 = "#000000";
end;
lifebar(5, 8, 240, 2, jlife, jmax, barcolor, barcolor3, "#000000", barcolor2);
textx = math.max(4, math.min(math.floor(jlife/ jmax * 240) - 4, 229));
if jlife == jmax then
textx = 223;
end;
text(textx, 13, string.format("%2.1d%%", math.min(jlife/ jmax * 100)));
--[[
bxp = math.sin(timer / 120) * 64 + 127;
byp = math.cos(timer / 120) * 64 + 127;
for i = 0, 0 do
balls[z] = {x = bxp + math.random(-100, 200) / 100, y = byp + math.random(-4, 4), xs = math.random(-100, 100) / 50, ys = math.random(-100, 100) / 100, life = math.random(60, 120), c = math.random(128, 255)};
z = z + 1;
end;
]]
doballs();
marioxspeed = memory.readbytesigned(0x0057);
marioyspeed = memory.readbytesigned(0x009F);
marioxpos = memory.readbyte(0x4AC);
marioypos = memory.readbyte(0x4AD);
-- lifebar(5, 2, 240, 2, marioxspeed + 0x40, 0x80, "#8888ff", "#000000");
joyput = joypad.read(1);
if joyput['up'] then
memory.writebyte(0x07F8, 3);
end;
if joyput['A'] and jlife >= 3 then
rechargerate = 0;
memory.writebyte(0x009F, math.max(-3, marioyspeed - 1));
-- memory.writebyte(0x009F, -3);
if not invincible then jlife = math.max(0, jlife - 3); end;
for i = 0, 10 do
balls[z] = {x = marioxpos + 5, y = marioypos + 7, xs = math.random(-70, 70) / 100, ys = math.random(100, 300) / 100, life = math.random(30, 60), c = math.random(128, 255)};
z = z + 1;
end;
end;
if (joyput['left'] or joyput['right']) then
speedchange = 1;
speedmax = 0x28;
if joyput['B'] and jlife > 0 then
rechargerate = 0;
if not invincible then jlife = math.max(0, jlife - 1); end;
speedchange = 5;
speedmax = 0x40;
end;
if joyput['left'] then
memory.writebyte(0x0033, 2);
memory.writebyte(0x0045, 2);
if marioxspeed > (speedmax * -1) then
memory.writebyte(0x0057, math.max(-0x40, marioxspeed - speedchange));
end;
for i = 0, 10 do
balls[z] = {x = marioxpos + 7, y = marioypos + 7, xs = math.random(300, 400) / 100, ys = math.random(-10, 20) / 100, life = math.random(5, 5 + speedchange * 10), c = math.random(128, 255)};
z = z + 1;
end;
else
memory.writebyte(0x0033, 1);
memory.writebyte(0x0045, 1);
if marioxspeed < speedmax then
memory.writebyte(0x0057, math.min(0x40, marioxspeed + speedchange));
end;
for i = 0, 10 do
balls[z] = {x = marioxpos + 7, y = marioypos + 7, xs = math.random(-400, -300) / 100, ys = math.random(-10, 20) / 100, life = math.random(5, 5 + speedchange * 10), c = math.random(128, 255)};
z = z + 1;
end;
end;
end;
if not ((joyput['B'] and (joyput['left'] or joyput['right'])) or joyput['A']) then
rechargerate = rechargerate + refillrate;
jlife = math.min(jmax, jlife + rechargerate);
end;
screenpage = memory.readbyte(0x071a);
screenxpos = memory.readbyte(0x071c);
arealow = memory.readbyte(0x00e7);
areahigh = memory.readbyte(0x00e8);
enemylow = memory.readbyte(0x00e9);
enemyhigh = memory.readbyte(0x00ea);
-- text( 10, 24, string.format("Screen position: %02X.%02X", screenpage, screenxpos));
-- text(169, 24, string.format("Area: %02X %02X", areahigh, arealow));
-- text(163, 32, string.format("Enemy: %02X %02X", enemyhigh, enemylow));
--[[
text( 4, 217, string.format("Memory writes: %04d", testcount));
if testcount > 1500 or testcount < 200 then
cyclepos = math.abs(15 - math.fmod(timer, 30)) / 15;
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0xFF));
barcolor = "#ff" .. warningboxcolor .. warningboxcolor;
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0x80) + 0x7F);
barcolor2 = "#" .. warningboxcolor .. "0000";
warningboxcolor = string.format("%02X", math.floor(cyclepos * 0x40));
barcolor3 = "#" .. warningboxcolor .. "0000";
-- barcolor3 = "#000000";
else
barcolor = "#ffffff";
barcolor2 = "#ff4444";
barcolor3 = "#000000";
end;
lifebar(5, 226, 240, 2, testcount, 2500, barcolor, barcolor3, "#000000", barcolor2);
--]]
-- memory.writebyte(0x00e7, math.random(0, 0xFF));
-- memory.writebyte(0x00e8, math.random(0, 0xFF));
-- memory.writebyte(0x00e9, math.random(0, 0xFF));
-- memory.writebyte(0x00ea, math.random(0, 0xFF));
testcount = 0;
--[[
marioxspeed2 = math.abs(marioxspeed);
box(2, 217, 0x40 * 3 + 5, 226, "#000000");
box(2, 218, 0x40 * 3 + 5, 225, "#000000");
box(2, 219, 0x40 * 3 + 5, 224, "#000000");
box(2, 220, 0x40 * 3 + 5, 223, "#000000");
box(2, 221, 0x40 * 3 + 5, 222, "#000000");
if marioxspeed2 > 0 then
for bl = 0, marioxspeed2 do
if bl < 0x20 then
segcolor = string.format("#%02XFF00", math.floor(bl / 0x20 * 0xFF));
else
segcolor = string.format("#FF%02X00", math.max(0, math.floor((0x40 - bl) / 0x20 * 0xFF)));
end;
box(bl * 3 + 3, 218, bl * 3 + 4, 225, segcolor);
-- line(bl * 3 + 4, 218, bl * 3 + 4, 225, segcolor);
end;
end;
--]]
maxspeed = 0x40;
marioxspeed = memory.readbytesigned(0x0057);
marioxspeed2 = math.abs(marioxspeed);
text(maxspeed * 3 + 2, 221, string.format(" %2d", marioxspeed2));
box(5, 221, maxspeed * 3 + 5, 230, "#000000");
box(5, 222, maxspeed * 3 + 5, 229, "#000000");
box(5, 223, maxspeed * 3 + 5, 228, "#000000");
box(5, 224, maxspeed * 3 + 5, 227, "#000000");
box(5, 225, maxspeed * 3 + 5, 226, "#000000");
if marioxspeed2 > 0 then
for bl = 1, marioxspeed2 do
pct = bl / maxspeed;
if pct < 0.50 then
val = math.floor(pct * 2 * 0xFF);
segcolor = string.format("#%02XFF00", val);
elseif pct < 0.90 then
val = math.floor(0xFF - (pct - 0.5) * 100/40 * 0xFF);
segcolor = string.format("#FF%02X00", val);
elseif bl < maxspeed then
val = math.floor((pct - 0.90) * 10 * 0xFF);
segcolor = string.format("#FF%02X%02X", val, val);
else
segcolor = "#ffffff";
end;
yb = math.max(math.min(3, (bl - 0x28)), 0);
box(bl * 3 + 3, 225 - yb, bl * 3 + 4, 229, segcolor);
-- box(bl * 3 + 3, 218, bl * 3 + 4, 225, segcolor);
-- line(bl * 3 + 4, 218, bl * 3 + 4, 225, segcolor);
end;
end;
FCEU.frameadvance();
end;

View File

@ -0,0 +1,573 @@
--Super Mario Bros. - Drag and Drop
--Written by XKeeper
--Allows you to use the mouse to pick up enemies and movie them around!
debugmodes = {
enabled = false; -- CHANGE THIS AT YOUR PERIL
showenemydata = false;
drawmouse = false;
locktimer = false;
invincible = false;
ver = "03/29 15:00:00";
};
control = {}; -- must come first.
-- basically, will contain all the "interface" things,
-- buttons, menus, etc.
-- Easier to organize, I guess.
require "x_functions";
require "x_interface";
if debugmodes['enabled'] and false then
require "x_smb1enemylist"; -- used for summoning and other things... not finished
end;
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu:5/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(6);
end;
-- ****************************************************************************
-- * drawmouse(xpos, ypos, click)
-- * Draws a crude mouse pointer at the location; mostly good for screenshots and debugging.
-- ****************************************************************************
function drawmouse(x, y, click)
if click then
fill = "#cccccc";
else
fill = "#ffffff";
end;
y = y + 1;
for i = 0, 6 do
if i ~= 6 then
line(x + i, y + i, x + i, y + 8 - math.floor(i / 2), fill);
pixel(x + i, y + 8 - math.floor(i / 2), "#000000");
end;
pixel(x + i, y + i - 1, "#000000");
end;
pixel(x + 1, y + 0, "#000000");
line(x , y , x , y + 9, "#000000");
-- line(x + 1, y + 1, x + 6 , y + 6, "#000000");
-- line(x , y + 11, x + 7 , y + 7, "#000000");
end;
-- ****************************************************************************
-- * smbpx2ram( screen-x, screen-y )
-- * Returns the offset that represents the tile under screenx/screeny.
-- ****************************************************************************
function smbpx2ram(px, py)
local py = math.floor(py) - 0x20;
local px = math.floor(px);
if px < 0 or px > 400 or py < 0x00 or py > (240 - 0x20) then
return false;
end;
local oy = math.floor(py / 0x10);
local ox = math.fmod(math.floor((px + smbdata['screenpos']) / 0x10), 0x20);
offset = 0x500 + math.fmod(oy * 0x10 + math.floor(ox / 0x10) * 0xC0 + math.fmod(ox, 0xD0), 0x1A0);
return offset;
end;
-- ****************************************************************************
-- * smbram2px( memory offset )
-- * Gives the current top-left pixel of the tile the offset represents.
-- ****************************************************************************
function smbram2px(offset)
offset = offset - 0x500;
if offset < 0 or offset >= 0x1A0 then
return false;
end;
local px = (math.fmod(offset, 0x10) + math.floor(offset / 0xD0) * 0x10) * 0x10;
px = px - math.fmod(smbdata['screenpos'], 0x200);
if px < 0 then
px = px + 0x200;
end;
local py = math.floor(math.fmod(offset, 0xD0) / 0x10);
returnval = {x = px, y = py};
return returnval;
end;
-- ****************************************************************************
-- * smbmoveenemy( Enemy number, xpos, ypos, x accell, y accell )
-- * moves enemies to given point. auto-sets facing direction, as well
-- ****************************************************************************
function smbmoveenemy(n, x, y, ax, ay)
local x1 = math.fmod(x, 0x100);
local x2 = math.floor(x / 0x100);
local y1 = math.fmod(y, 0x100);
local y2 = math.floor(y / 0x100);
local ax = math.max(-128, math.min(ax, 0x7F));
local ay = math.max(-128, math.min(ay, 0x7F));
memory.writebyte(0x006D + n, x2);
memory.writebyte(0x0086 + n, x1);
memory.writebyte(0x00B5 + n, y2);
memory.writebyte(0x00CE + n, y1);
memory.writebyte(0x0057 + n, ax);
memory.writebyte(0x009F + n, ay);
if ax > 0 then
memory.writebyte(0x0045 + n, 1);
elseif ax < 0 then
memory.writebyte(0x0045 + n, 2);
end;
end;
-- ****************************************************************************
-- * inputaverage()
-- * Mouse movement averages (something unique to this...).
-- ****************************************************************************
function inputaverage()
local tempx = 0;
local tempy = 0;
for temp = 1, 2 do
tempx = tempx + avgmove[temp]['xmouse'];
tempy = tempy + avgmove[temp]['ymouse'];
avgmove[temp] = avgmove[temp + 1];
end;
avgmove[3]['xmouse'] = inpt['xmouse'] - last['xmouse'];
avgmove[3]['ymouse'] = inpt['ymouse'] - last['ymouse'];
avgmove['calc']['xmouse'] = (tempx + avgmove[3]['xmouse']) / 3;
avgmove['calc']['ymouse'] = (tempy + avgmove[3]['ymouse']) / 3;
end;
-- ****************************************************************************
-- * tileview()
-- * This does all the "what tile is here" shit for you (me)
-- ****************************************************************************
function tileview ()
local ramval = smbpx2ram(inpt['xmouse'], inpt['ymouse']);
if ramval then
local ret = smbram2px(ramval);
local c = "#ffffff";
if math.fmod(timer, 4) < 2 then
c = "#cccccc";
end;
if ret then
local tx1 = math.max(0, ret['x'] - 1);
local tx2 = math.min(0xFF, ret['x'] + 0x10);
local ty1 = math.max(ret['y'] * 0x10 + 0x1F, 0);
local ty2 = math.min(244, ret['y'] * 0x10 + 0x30);
box(tx1, ty1, tx2, ty2, c);
end;
local textx = inpt['xmouse'] + 10;
local texty = inpt['ymouse'] - 4;
if textx > 229 then
textx = textx - 42;
end;
texty = math.min(214, texty);
text(textx, texty, string.format("%04X", ramval));
text(textx, texty + 8, string.format(" %02X ", memory.readbyte(ramval)));
end;
end;
-- ****************************************************************************
-- * Generic test function, really. Does nothing of use.
-- * Incidentally, most of the times this shows up, it doesn't
-- ****************************************************************************
function test(arg)
text(50, 100, "IT WORKS");
end;
-- ****************************************************************************
-- * spawnsetup(arg)
-- * Prepares spawning of an enemy.
-- * Perhaps should create a dialog box in the middle of the screen?..
-- ****************************************************************************
function spawnsetup(args)
if mode ~= 2 then
spawndata['lmode'] = mode;
mode = 2;
spawndata['enum'] = 0x00;
spawndata['ename'] = "Green Koopa";
spawndata['etype'] = 0;
spawndata['exs'] = 16;
spawndata['eys'] = 24;
-- etype:
--- 0: normal enemy (one slot)
--- 1: big enemy (two slots, takes latter but fills both)
--- 2: powerup (takes slot 6)
end;
end;
-- ****************************************************************************
-- * spawnsetup(arg)
-- * Prepares spawning of an enemy.
-- * Perhaps should create a dialog box in the middle of the screen?..
-- ****************************************************************************
function spawnenemy(args)
local c = "#ffffff";
if math.fmod(timer, 4) < 2 then
c = "#888888";
end;
local freespace = 0;
if debugmodes['showenemydata'] then
for i = 1, 6 do
text(8, 8 + 8 * i, string.format("%d %02X", i, memory.readbyte(0x000E+i)));
end;
end;
for i = 1, 6 do
if ((spawndata['etype'] <= 1 and i <= 5) or (spawndata['etype'] == 2 and i == 6)) and memory.readbyte(0x000E+i) == 0 then
if debugmodes['showenemydata'] then
text(8, 8 + 8 * i, string.format("%d %02X *", i, memory.readbyte(0x000E+i)));
end;
if (spawndata['etype'] == 1 and memory.readbyte(0x000E + i - 1) == 0) or spawndata['etype'] ~= 1 then
freespace = i;
break;
end;
end;
end;
if freespace > 0 then
box(inpt['xmouse'] - (spawndata['exs'] / 2), inpt['ymouse'] - (spawndata['eys'] / 2), inpt['xmouse'] + (spawndata['exs'] / 2), inpt['ymouse'] + (spawndata['eys'] / 2), c);
text(70, 31, string.format("Summon [%s]", spawndata['ename']));
if debugmodes['showenemydata'] then
text(70, 39, string.format("Enemy slot [%X]", freespace));
end;
local mx = smbdata['screenpos'] + inpt['xmouse'];
local my = 0x100 + inpt['ymouse'];
if inpt['leftclick'] and not last['leftclick'] then
memory.writebyte(0x000E + freespace, 1);
memory.writebyte(0x0015 + freespace, spawndata['enum']);
memory.writebyte(0x0499 + freespace, 3);
smbmoveenemy(freespace, mx - (spawndata['exs'] / 2), my - (spawndata['eys'] / 2), -1, 0);
mode = spawndata['lmode'];
end;
else
text(70, 31, string.format("Can't summon (too many enemies)!"));
end;
end;
-- ****************************************************************************
-- * modechange(arg)
-- * changes current mode (used in menu).
-- * also changes menu text to reflect new mode.
-- ****************************************************************************
function modechange(args)
mode = args[1];
if args[1] == 0 then
mainmenu['menu']['m001_mode']['menu']['m001_tiles']['marked'] = 1;
mainmenu['menu']['m001_mode']['menu']['m002_enemy']['marked'] = 0;
else
mainmenu['menu']['m001_mode']['menu']['m001_tiles']['marked'] = 0;
mainmenu['menu']['m001_mode']['menu']['m002_enemy']['marked'] = 1;
end;
end;
-- ****************************************************************************
-- * debugmode(arg)
-- * changes debugmode flags
-- * useful for on-the-fly checking, I guess
-- ****************************************************************************
function debugmode(args)
if debugmodes[args[2]] == false then
debugmodes[args[2]] = true;
mainmenu['menu']['m999_debug']['menu'][args[1]]['marked'] = 1;
else
debugmodes[args[2]] = false;
mainmenu['menu']['m999_debug']['menu'][args[1]]['marked'] = 0;
end;
end;
mainmenu = {
test = 1;
life = 0;
width = 54;
menu = {
m001_mode = {
label = "Mode",
life = 0;
width = 50;
menu = {
m001_tiles = {
label = " Objects",
action = modechange,
args = {0},
marked = 0;
},
m002_enemy = {
label = " Sprites",
action = modechange,
args = {1},
marked = 1;
},
},
},
m002_summon = {
label = "Summon",
action = spawnsetup,
args = {1},
},
},
};
if debugmodes['enabled'] then
mainmenu['menu']['m999_debug'] = {
label = "Debug",
life = 0;
width = 90;
menu = {
m000_showmouse = {
label = " Draw mouse",
action = debugmode,
marked = debugmodes['drawmouse'] and 1 or 0;
args = {"m000_showmouse", "drawmouse"},
},
m001_enemydata = {
label = " Show enemy data",
action = debugmode,
marked = debugmodes['showenemydata'] and 1 or 0;
args = {"m001_enemydata", "showenemydata"},
},
m002_locktimer = {
label = " Lock timer",
action = debugmode,
marked = debugmodes['locktimer'] and 1 or 0;
args = {"m002_locktimer", "locktimer"},
},
m003_invincible = {
label = " Invincibility",
action = debugmode,
marked = debugmodes['invincible'] and 1 or 0;
args = {"m003_invincible", "invincible"},
},
},
};
end;
smbdata = {screenpos = 0};
mode = 1;
enemyhold = {};
avgmove = {
{ xmouse = 0, ymouse = 0 },
{ xmouse = 0, ymouse = 0 },
{ xmouse = 0, ymouse = 0 },
calc = {}
};
spawndata = {};
while (true) do
input.update(); -- updates mouse position
inputaverage(); -- average movement (for throwing)
smbdata['screenposold'] = smbdata['screenpos'];
smbdata['screenpos'] = memory.readbyte(0x071a) * 0x100 + memory.readbyte(0x071c);
smbdata['screenposchg'] = smbdata['screenpos'] - smbdata['screenposold'];
smbdata['rendercol'] = memory.readbyte(0x06A0);
if smbdata['screenposchg'] < 0 then
smbdata['screenposchg'] = 0;
end;
timer = timer + 1;
if debugmodes['enabled'] then
if control.button( 234, 15, 19, 2, "SET\n999") then
memory.writebyte(0x07F8, 0x09);
memory.writebyte(0x07F9, 0x09);
memory.writebyte(0x07FA, 0x09);
end;
if debugmodes['locktimer'] then
memory.writebyte(0x0787, 0x1F);
end;
if debugmodes['invincible'] then
memory.writebyte(0x079E, 0x02);
end;
end;
if mode == 0 then
tileview();
elseif mode == 2 then
spawnenemy();
else
if debugmodes['showenemydata'] then
text(0, 25 + 0, string.format("E# XPOS YPOS XREL YREL XA YA TY HB"));
end;
for i=1,6 do
if (memory.readbyte(0x000E+i) ~= 0) then --and memory.readbyte(0x04AC+(i*4)) ~= 0xFF) and (memory.readbyte(0x0015 + i) ~= 0x30 and memory.readbyte(0x0015 + i) ~= 0x31) then
if not enemyhold[i] or not inpt['leftclick'] then
enemyhold[i] = nil;
-- text(8, 50 + i * 8, "-");
elseif enemyhold[i] then
-- text(8, 50 + i * 8, string.format("HOLD %04X %04X", smbdata['screenpos'] + inpt['xmouse'] - enemyhold[i]['xmouse'], inpt['ymouse'] + 0x100 - enemyhold[i]['ymouse']));
smbmoveenemy(i, smbdata['screenpos'] + inpt['xmouse'] - enemyhold[i]['x'], inpt['ymouse'] + 0x100 - enemyhold[i]['y'], (avgmove['calc']['xmouse']) * 8, avgmove['calc']['ymouse'] / 2.5);
end;
e2x1 = memory.readbyte(0x04AC+(i*4));
e2y1 = memory.readbyte(0x04AC+(i*4)+1);
e2x2 = memory.readbyte(0x04AC+(i*4)+2);
e2y2 = memory.readbyte(0x04AC+(i*4)+3);
-- text(e2x1 - 5, e2y1 - 13, string.format("%02X", memory.readbyte(0x001E + i)));
enemyxpos = memory.readbytesigned(0x006D + i) * 0x0100 + memory.readbyte(0x0086 + i);
enemyypos = memory.readbytesigned(0x00B5 + i) * 0x100 + memory.readbyte(0x00CE + i);
enemyxacc = memory.readbytesigned(0x0057 + i);
enemyyacc = memory.readbytesigned(0x009f + i);
enemyxposa = enemyxpos - smbdata['screenpos'];
enemyyposa = enemyypos - 0x100;
enemyyposa2 = math.fmod(enemyyposa + 0x10000, 0x100);
enemytype = memory.readbyte(0x0015 + i);
enemyhitbox = memory.readbyte(0x0499 + i);
dead = "";
if enemyyposa <= -72 + 32 and enemyyacc < -3 then
dead = "UP";
end;
if math.abs(enemyxacc) >= 0x60 then
dead = dead .. "SIDE";
end;
if dead ~= "" then
dead = " ".. dead;
end;
if debugmodes['showenemydata'] then
line(enemyxposa, enemyyposa2, enemyxposa + 16, enemyyposa2, "#ffffff");
text(enemyxposa, enemyyposa2, memory.readbyte(0x0045 + i));
text(1, 25 + 8 * i, string.format("E%X %04X %04X %04X %04X %02X %02X %02X %02X %s", i,
AND(enemyxpos, 0xFFFF),
AND(enemyypos, 0xFFFF),
AND(enemyxposa, 0xFFFF),
AND(enemyyposa, 0xFFFF),
AND(enemyxacc, 0xFF),
AND(enemyyacc, 0xFF),
AND(enemytype, 0xFF),
AND(enemyhitbox, 0xFF),
"")); -- dead));
end;
if hitbox(inpt['xmouse'], inpt['ymouse'], inpt['xmouse'], inpt['ymouse'], e2x1, e2y1, e2x2, e2y2, "#ffffff", "#0000ff") then
-- if hitbox(inpt['xmouse'], inpt['ymouse'], inpt['xmouse'], inpt['ymouse'], enemyxposa, enemyyposa, enemyxposa + 0xF, enemyyposa + 0x17) then
-- text(e2x1 - 5, e2y1 - 13, string.format("#%d %02X", i, memory.readbyte(0x0015 + i)));
if inpt['leftclick'] then
if not enemyhold[i] then
enemyhold[i] = { x = inpt['xmouse'] - enemyxposa, y = inpt['ymouse'] - enemyyposa };
end;
-- memory.writebyte(0x001F + i, 0xFF);
-- memory.writebyte(0x04AC + i, 0xFF);
-- memory.writebyte(0x000E + i, 0x00);
end;
end;
else
enemyhold[i] = nil;
end;
end;
end;
--[[
zap = zapper.read();
box(zap['xmouse'] - 5, zap['ymouse'] - 5, zap['xmouse'] + 5, zap['ymouse'] + 5, "#ffffff");
if zap['click'] == 1 then
box(zap['xmouse'] - 7, zap['ymouse'] - 7, zap['xmouse'] + 7, zap['ymouse'] + 7, "#ff0000");
end;
line(zap['xmouse'] - 0, zap['ymouse'] - 9, zap['xmouse'] + 0, zap['ymouse'] + 9, "#ffffff");
line(zap['xmouse'] - 9, zap['ymouse'] - 0, zap['xmouse'] + 9, zap['ymouse'] + 0, "#ffffff");
]]
-- almost always
if control.button(78, 14, 54, 1, "<Main Menu>") then
mainmenu['life'] = 70;
end;
control.showmenu(78, 25, mainmenu);
text( 20, 222, " 2009 Xkeeper - http://jul.rustedlogic.net/ ");
line( 21, 231, 232, 231, "#000000");
if debugmodes['enabled'] then
text( 41, 214, " Debug version - ".. debugmodes['ver'] .." ");
end;
-- always on top
if debugmodes['drawmouse'] then
drawmouse(inpt['xmouse'], inpt['ymouse'], inpt['leftclick']);
end;
FCEU.frameadvance();
end

View File

@ -0,0 +1,245 @@
--Super Mario Bros. - It's Snowing!
--Written by XKeeper
require("x_functions");
if not x_requires then
-- Sanity check. If they require a newer version, let them know.
timer = 1;
while (true) do
timer = timer + 1;
for i = 0, 32 do
gui.drawbox( 6, 28 + i, 250, 92 - i, "#000000");
end;
gui.text( 10, 32, string.format("This Lua script requires the x_functions library."));
gui.text( 53, 42, string.format("It appears you do not have it."));
gui.text( 39, 58, "Please get the x_functions library at");
gui.text( 14, 69, "http://xkeeper.shacknet.nu/");
gui.text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));
gui.drawbox(7, 29, 249, 91, "#ff" .. warningboxcolor .. warningboxcolor);
FCEU.frameadvance();
end;
else
x_requires(4);
end;
function smbpx2ram(px, py)
py = math.floor(py) - 0x20;
px = math.floor(px);
-- text(90, 16, string.format("PX[%4d] PY[%4d]", px, py));
if px < 0 or px > 400 or py < 0x00 or py > (240 - 0x20) then
return false;
end;
oy = math.floor(py / 0x10);
ox = math.fmod(math.floor((px + smbdata['screenpos']) / 0x10), 0x20);
-- text(90, 16, string.format("CX[%4X] CY[%4X]", ox, oy));
offset = 0x500 + math.fmod(oy * 0x10 + math.floor(ox / 0x10) * 0xC0 + math.fmod(ox, 0xD0), 0x1A0);
return offset;
end;
function smbram2px(offset)
offset = offset - 0x500;
if offset < 0 or offset >= 0x1A0 then
return false;
end;
px = (math.fmod(offset, 0x10) + math.floor(offset / 0xD0) * 0x10) * 0x10;
px = px - math.fmod(smbdata['screenpos'], 0x200);
-- text(8, 8, string.format("PX[%4d] OF[%4X]", px, offset));
if px < 0 then
px = px + 0x200;
end;
py = math.floor(math.fmod(offset, 0xD0) / 0x10);
returnval = {x = px, y = py};
return returnval;
end;
function doballs()
count = 0;
for k, v in pairs(balls) do
v['x'] = v['x'] + v['xs'] - smbdata['screenposchg'];
v['y'] = v['y'] + v['ys'];
-- v['ys'] = v['ys'] - 0.1;
v['life'] = v['life'] - 1;
offset = smbpx2ram(v['x'], v['y']);
temp = 0;
if offset then
temp = memory.readbyte(offset);
end;
-- 354 so we can spawn them offscreen
if v['x'] < 0 or v['x'] > 512 or v['y'] < 0 or v['y'] > 243 or v['life'] < 0 or (temp > 0) then
balls[k] = nil;
else
balls[k] = v;
colkey = math.ceil(255 * (5 - math.max(math.min(5, (v['life'] / 15)), 0)) / 5);
if v['c'] >= 0 then
color = string.format("#%02X%02X%02X", v['c'], v['c'], 255);
-- color = string.format("#%02X%02X%02X", v['c'] * .8, v['c'] * .5, v['c'] * 0);
else
color = string.format("#%02X0000", v['c'] * -1 , 0, 0);
end;
if v['life'] > 400 then
box(v['x'] - 1, v['y'] - 1, v['x'] + 1, v['y'] + 1, color);
pixel(v['x'], v['y'], color);
elseif v['life'] > 200 then
box(v['x'], v['y'], v['x'] + 1, v['y'] + 1, color);
else
pixel(v['x'], v['y'], color);
end;
count = count + 1;
end;
end;
return count;
end;
balls = {};
z = 0;
timer = 0;
smbdata = {screenpos = 0};
while (true) do
if
memory.readbyte(0x0301) == 0x3F and
memory.readbyte(0x0302) == 0x10 and
memory.readbyte(0x0303) == 0x04 and
memory.readbyte(0x0304) == 0x22
then
memory.writebyte(0x0304, 0x0F);
end;
smbdata['screenposold'] = smbdata['screenpos'];
smbdata['screenpos'] = memory.readbyte(0x071a) * 0x100 + memory.readbyte(0x071c);
smbdata['screenposchg'] = smbdata['screenpos'] - smbdata['screenposold'];
smbdata['rendercol'] = memory.readbyte(0x06A0);
if smbdata['screenposchg'] < 0 then
smbdata['screenposchg'] = 0;
end;
timer = timer + 1;
ballcount = doballs();
for i = 0, 2 do
balls[z] = {x = math.random(0, 512), y = 0, xs = math.random(-50, 00) / 100, ys = math.random(100, 150) / 100, life = math.random(400, 700), c = math.random(200, 255)};
z = z + 1;
end;
-- lifebar(8, 8, 240, 2, ballcount, 1000, "#ffffff", "clear");
--]]
--[[
for x = 0x00, 0x0F do
for y = 0x00, 0x0C do
box(x * 0x10 + 0, y * 0x10 + 0x20, x * 0x10 + 0x01, y * 0x10 + 0x21, "#FFFFFF");
value = memory.readbyte(smbpx2ram(x * 0x10, y * 0x10 + 0x20));
if value > 0 then
text(x * 0x10 + 0, y * 0x10 + 0x20, string.format("%02X", value));
end;
end;
end;
]]
-- text(8, 8, string.format("0x06A0 [%4X]", smbdata['rendercol']));
--[[
for i = 0, 5 do
ret = smbram2px(0x500 + i * 0x10 + i);
if ret then
-- text(8, 16, string.format("PX[%4d] PY[%4d]", ret['x'], ret['y']));
box(ret['x'] + 0, ret['y'] * 0x10 + 0x20, ret['x'] + 0x0F, ret['y'] * 0x10 + 0x2F, "#FFFFFF");
end;
end;
--]]
--[[
box(19, 19, 0x20 * 2 + 20, 46, "#0000ff");
box(18, 18, 0x20 * 2 + 21, 47, "#0000ff");
for x = 0, 0x1F do
for y = 0, 0x0C do
offset = 0x500 + y * 0x10 + math.floor(x / 0x10) * 0xD0 + math.fmod(x, 0x10);
c = memory.readbyte(offset);
box(x * 2 + 20, y * 2 + 20, x * 2 + 21, y * 2 + 21, string.format("#%02X%02X%02X", c, c, c));
end;
end;
if math.fmod(timer, 2) < 1 then
temp = math.floor(math.fmod(smbdata['screenpos'], 0x200) / 8);
if temp < 0x20 then
box(temp + 20, 19, temp + 0x10 * 2 + 20, 46, "#ffffff");
else
box(temp + 20, 19, 0x20 * 2 + 20, 46, "#ffffff");
box(19, 19, (temp - 0x20) + 20, 46, "#ffffff");
end;
line(smbdata['rendercol'] * 2 + 20, 19, smbdata['rendercol'] * 2 + 20, 46, "#00ff00");
end;
--]]
--[[
x = 0;
y = 0;
px = math.sin(timer / 60) * 100 + 127;
py = math.cos(timer / 60) * 90 + 100 + 0x20;
offset = smbpx2ram(px, py);
if offset then
offset = offset - 0x500;
x = math.floor(offset / 0xD0) * 0x10 + math.fmod(offset, 0x10);
y = math.floor(math.fmod(offset, 0xD0) / 0x10);
x2 = math.fmod(smbdata['screenpos'] + x * 0x10, 0x100);
box( x2, y * 0x10 + 0x20, x2 + 0x0F, y * 0x10 + 0x2F, "#ffffff");
-- line( 0, y * 0x10, 255, y * 0x10, "#ffffff");
box (px - 3, py - 3, px + 3, py + 3, "#ffffff");
line(px - 6, py , px + 6, py , "#ffffff");
line(px , py - 6, px , py + 6, "#ffffff");
text(90, 24, string.format("Offset[%04X]", offset + 0x500));
text(90, 32, string.format("OX[%4X] OY[%4X]", x, y));
text(90, 40, string.format("SX[%4X]", x2));
else
text(90, 24, "Offset failed");
end;
if math.fmod(timer, 2) < 1 then
temp = math.floor(math.fmod(smbdata['screenpos'], 0x200) / 8) + 20;
line(temp, 18, temp, 47, "#ffffff");
box(20 + x * 2, 20 + y * 2, 21 + x * 2, 21 + y * 2, "#ffffff");
end;
--]]
text( 20, 222, " 2009 Xkeeper - http://jul.rustedlogic.net/ ");
line( 21, 231, 232, 231, "#000000");
FCEU.frameadvance();
end;

613
output/luaScripts/vnb.lua Normal file
View File

@ -0,0 +1,613 @@
-- Valkyrie no Bouken stuffs
-- This game sucks, don't play it
-- Lovingly based off of 4matsy's SMB code, and then mutilated and mamed as required
-- Xkeeper 2008, September 12th
require("x_functions");
x_requires(4);
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function mapdot(x,y,color)
if (x >= 1 and x <= 254 and y >= 1 and y <= 239) then
gui.drawline(x - 1, y , x + 1, y , color);
gui.drawline(x , y - 1, x , y + 2, color);
end;
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function doexp()
totalexp = vnbnumber(0x00d5, 5);
growth = memory.readbyte(0x0111);
level = memory.readbyte(0x00b9);
nextlv = memory.readbyte(0x00bb);
prevexp = -1;
if level ~= 0 then
if nextlv < 0x14 then
nextexp = exptable[nextlv + 1];
else
prevexp = math.floor(totalexp / 10000) * 10000;
nextexp = math.floor(totalexp / 10000) * 10000 + 10000;
end;
if growth < 3 and prevexp == -1 then
-- prevexp = exptable[leveltable[growth][level] + 1];
end;
expval = {};
expval["level"] = level;
expval["next"] = nextexp - totalexp;
expval["prev"] = prevexp;
expval["pct"] = math.floor((totalexp - prevexp) / (nextexp - prevexp) * 100);
expval["exp"] = totalexp;
if prevexp == -1 then
expval["pct"] = -1;
end;
else
expval = {};
expval["level"] = 0;
expval["next"] = 0;
expval["prev"] = 0;
expval["pct"] = 0;
expval["exp"] = 0;
end;
return expval;
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function vnbnumber(offset, length)
val = 0;
for i = 0, length do
inp = memory.readbyte(offset + (i));
if (inp ~= 0x26) then val = val + inp * (10 ^ i); end;
end;
return val;
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function worldmap()
herox = memory.readbyte(0x0080) + memory.readbyte(0x0081) * 256; -- hero's X position
heroy = memory.readbyte(0x0082) + memory.readbyte(0x0083) * 256; -- hero's current MP
if mapstyle == 1 then
mapx = 8;
mapy = 9;
mapw = 60;
maph = 37;
elseif mapstyle == 2 or mapstyle == 3 then
mapx = 8;
mapy = 34;
mapw = 240;
maph = 147;
else
return nil;
end;
if gamemode == 0x05 or gamemode == 0x01 or gamemode == 0x06 or gamemode == 0x08 then
maphx = math.ceil(herox / 3840 * mapw);
maphy = math.ceil(heroy / 2352 * maph);
-- filledbox(mapx - 1, mapy - 1, mapx + mapw + 1, mapy + maph, "#000000");
box(mapx - 1, mapy - 1, mapx + mapw + 1, mapy + maph, "#ffffff");
if mapstyle == 3 then
for i = 0, 0xFF do
mappx = math.ceil((3840 / 16) * math.fmod(i, 0x10) / 3840 * mapw);
mappy = math.ceil((2352 / 16) * math.floor(i / 0x10) / 2352 * maph);
mappx2 = math.ceil((3840 / 16) * (math.fmod(i, 0x10) + 1) / 3840 * mapw) - 1;
mappy2 = math.ceil((2352 / 16) * (math.floor(i / 0x10) + 1) / 2352 * maph) - 1;
tmp = memory.readbyte(0x81E5 + i) * 2;
filledbox(mapx + mappx, mapy + mappy, mapx + mappx2, mapy + mappy2, string.format("#%02x%02x%02x", tmp, tmp, tmp));
end;
end;
if math.fmod(timer, 60) >= 30 then
color = "#888888";
else
color = "#bbbbbb";
end;
-- line(mapx, mapy + maphy, mapx + mapw, mapy + maphy, "#cccccc");
-- line(mapx + maphx, mapy, mapx + maphx, mapy + maph, "#cccccc");
mapdist = 51;
for i = 1, mappoints do
mappx = math.ceil(mapdots[i]["x"] / 3840 * mapw);
mappy = math.ceil(mapdots[i]["y"] / 2352 * maph);
mapdot(mapx + mappx, mapy + mappy, mapdots[i]["color"]);
if mapdots[i]["name"] then
mapdotdist = math.abs(mapdots[i]["x"] - herox) + math.abs(mapdots[i]["y"] - heroy);
if mapdotdist < mapdist then
mapdist = mapdotdist;
mapdistn = mapdots[i]["name"];
end;
end;
end;
if mapdist <= 50 then
text(90, 17, mapdistn);
end;
filledbox(mapx + maphx - 0, mapy + maphy - 0, mapx + maphx + 0, mapy + maphy + 0, "#ffffff");
box(mapx + maphx - 1, mapy + maphy - 1, mapx + maphx + 1, mapy + maphy + 1, color);
-- text(mapx + 0, mapy + maph + 2, string.format("%04d, %04d", herox, heroy));
end;
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function gameloop()
if gamemode == 0x01 and math.fmod(timer, 60) >= 30 then
text(105, 180, "< DEMO >");
end;
herohp = memory.readbyte(0x00c0) + memory.readbyte(0x00c1) * 256; -- hero's current HP
heromp = memory.readbyte(0x00c2) + memory.readbyte(0x00c3) * 256; -- hero's current MP
heromaxhp = memory.readbyte(0x00c4) + memory.readbyte(0x00c5) * 256; -- hero's maximum HP
heromaxmp = memory.readbyte(0x00c6) + memory.readbyte(0x00c7) * 256; -- hero's maximum MP
money = vnbnumber(0x00d0, 4);
gametime = memory.readbyte(0x0031) * 0x3c + memory.readbyte(0x0030); -- game-time
gamehour = math.floor(gametime / 320);
gameminute = math.floor((gametime - 320 * gamehour) / 320 * 60);
expval = doexp();
worldmap();
filledbox(96, 194, 255, 244, "#000000");
text(191, 8, string.format("Time: %02d:%02d", gamehour, gameminute));
-- text(188, 23, string.format("GameMode: %02x", gamemode));
text( 90, 194, string.format("HP %3d/%3d MP %3d/%3d", herohp, heromaxhp, heromp, heromaxmp));
if expval["next"] > 0 then
text( 90, 218, string.format("Lv.%2d: %6d XP Next %6d", expval["level"], expval["exp"], expval["next"]));
else
text( 90, 218, string.format("Lv.%2d: %6d EXP", expval["level"], expval["exp"]));
end;
text(217, 202, string.format("ATK %2d", memory.readbyte(0x00e7)));
text(217, 210, string.format("$%5d", money));
lifebar(191, 16, 60, 2, gamehour, 24, "#ffffff", "#777777", true);
lifebar(191, 20, 60, 0, gameminute, 60, "#cccccc", "#555555", true);
lifebar( 90, 202, 123, 4, herohp, heromaxhp, "#ffcc00", "#880000", true);
lifebar( 90, 208, 123, 3, heromp, heromaxmp, "#9999ff", "#0000dd", true);
if expval["pct"] ~= -1 then
lifebar( 90, 226, 162, 2, expval["pct"], 100, "#ffffff", "#555555", true);
end;
box(89, 194, 91, 244, "#000000");
line(90, 194, 90, 244, "#000000");
if not enemy then enemy = {} end;
if gamemode == 0x05 or gamemode == 0x01 or gamemode == 0x06 then
for i = 0, 5 do
offset = 0x500 + 0x10 * i;
if not enemy[i] then
enemy[i] = {};
end;
if (memory.readbyte(offset) > 0) then
if not enemy[i]["maxhp"] then enemy[i]["maxhp"] = 0 end;
enemy[i]["t"] = memory.readbyte(offset);
enemy[i]["x"] = memory.readbyte(offset + 5);
enemy[i]["y"] = memory.readbyte(offset + 6);
enemy[i]["hp"] = memory.readbyte(offset + 15);
enemy[i]["maxhp"] = math.max(enemy[i]["maxhp"], enemy[i]["hp"]);
enemy[i]["item"] = memory.readbyte(offset + 10);
if enemy[i]["t"] > 1 then
text(enemy[i]["x"] - 9, enemy[i]["y"] - 16, enemy[i]["hp"] .."/".. enemy[i]["maxhp"]);
lifebar(enemy[i]["x"] - 5, enemy[i]["y"] - 8, 22, 0, enemy[i]["hp"], enemy[i]["maxhp"], "#ffcc00", "#dd0000", false);
else
if (enemy[i]["item"] == 0x1C) then
if enemy[i]["hp"] == 0 then enemy[i]["hp"] = 10 end;
if enemy[i]["hp"] == 9 then enemy[i]["hp"] = 99 end;
text(enemy[i]["x"] - 6 - math.min(math.floor(enemy[i]["hp"] / 10) * 2, 2), enemy[i]["y"] - 8, "$".. enemy[i]["hp"]);
else
box(enemy[i]["x"], enemy[i]["y"], enemy[i]["x"] + 15, enemy[i]["y"] + 15, "#ffffff");
text(enemy[i]["x"] - string.len(itemlist[enemy[i]["item"]]) * 1.75 + 0, enemy[i]["y"] - 8, itemlist[enemy[i]["item"]]);
end;
end;
else
enemy[i] = {};
end;
end;
end;
for i = 0, 7 do
offset = 0x0160 + 0x02 * i;
item = memory.readbyte(offset + 1);
uses = memory.readbyte(offset + 1);
xo = math.fmod(i, 4);
yo = math.floor(i / 4);
if (item > 0 and (uses > 0 and uses < 255)) then
text(xo * 12 + 8, 194 + yo * 16, uses);
end;
end;
--[[-- auto-regenerate HP
if (herohp < heromaxhp) and ((math.fmod(timer, 3) == 0) or true) then
herohp = herohp + 1;
memory.writebyte(0x00c0, math.fmod(herohp, 256));
memory.writebyte(0x00c1, math.floor(herohp / 256));
end;
--]]--
--[[ basically the Big Cheating Section.
if not expbooster then expbooster = 0 end;
expbooster = expbooster + 1;
if expbooster >= 3 and gamemode == 0x06 then
expbooster = 0;
memory.writebyte(0x0d5, memory.readbyte(0x00d5) + 1);
for i = 0,5 do
inp = memory.readbyte(0x00d5 + i);
if (inp == 0x0a) then
memory.writebyte(0x00d5 + (i + 1), memory.readbyte(0x00d5 + (i + 1)) + 1);
memory.writebyte(0x00d5 + i, 0);
elseif (inp == 0x27) then
memory.writebyte(0x00d5 + i, 1);
end;
end;
end;
]]--
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function charaselect()
asign = memory.readbyte(0x0110);
btype = memory.readbyte(0x0111);
-- line( 92, 30, 92, 130, "#ffffff");
filledbox( 13, 48, 96, 64, "#000000"); -- cover JP text
filledbox( 13, 80, 96, 96, "#000000"); -- cover JP text
filledbox( 13, 112, 96, 128, "#000000"); -- cover JP text
filledbox(160, 48, 231, 64, "#000000"); -- cover JP text
text( 74, 24, " Create your character ");
text( 15, 51, "Astrological sign:");
text(158, 51, string.format("%s", asigns[asign]));
text( 41, 83, "Blood type:");
-- text(164, 83, string.format("%s (%X)", btypes[btype], btype));
text( 26, 115, "Clothing color:");
asign2 = math.fmod(asign, 4);
if asign2 == 0 then
shp = 64;
smp = 32;
elseif asign2 == 1 then
shp = 48;
smp = 48;
elseif asign2 == 2 then
shp = 32;
smp = 64;
elseif asign2 == 3 then
shp = 33;
smp = 63;
end;
strength = 10 + math.floor(shp / 32);
text( 8, 135, "Starting HP: ");
text( 8, 143, "Starting MP: ");
text(167, 135, " ".. shp);
text(167, 143, " ".. smp);
lifebar( 68, 136, 100, 4, shp, 64, "#ffcc00", "#880000");
lifebar( 68, 144, 100, 4, smp, 64, "#9999ff", "#0000dd");
text(194, 136, "Strength: ".. strength);
text(194, 146, "Magic:");
if smp >= 60 then
text(204, 162, "Fireball");
end;
if smp >= 40 then
text(204, 154, "Heal");
end;
graphx = 17;
graphy = 160;
text(graphx - 10, graphy + 63, "Lv.");
for i = 1, 12 do
thispointx = i * 15 + graphx;
line(thispointx, graphy, thispointx, graphy + 63, "#000088");
text(thispointx - 4 - (string.len(string.format("%d", i)) - 1) * 3, graphy + 63, string.format("%d", i));
end;
for i = 0, 7 do
lg = i * 3;
thispointy = graphy + 63 - (lg) * 3;
line(graphx + 15, thispointy, graphx + 180, thispointy, "#000088");
if exptable[lg] then
temp = string.format("%d", exptable[lg]);
text(graphx - 17, thispointy - 4, string.format("%5d", exptable[lg]));
end;
end;
line(graphx + 15, graphy , graphx + 15, graphy + 63, "#9999ff");
line(graphx + 15, graphy + 63, graphx + 180, graphy + 63, "#9999ff");
-- filledbox(graphx + 19, graphy + 1, graphx + 73, graphy + 8, "#666666");
text(graphx + 16, graphy - 1, "EXP Growth");
if btype <= 2 then
lastpointx = graphx;
lastpointy = graphy + 180;
for i = 1, 12 do
thispointx = i * 15 + graphx;
thispointy = graphy + 63 - (leveltable[btype][i] * 3);
line(lastpointx, lastpointy, thispointx, thispointy, "#ffffff");
lastpointx = thispointx;
lastpointy = thispointy;
end;
else
-- filledbox(graphx + 75, graphy + 27, graphx + 119, graphy + 35, "#666666");
text(graphx + 74, graphy + 26, " Random ");
end;
line(194, 145, 254, 145, "#000000");
line( 8, 153, 192, 153, "#000000");
end;
-- ************************************************************************************
-- ************************************************************************************
-- ************************************************************************************
function keyintercept()
tmp = memory.readbyte(0x0026);
if AND(tmp, 0x04) == 0x04 then
mapstyle = math.fmod(mapstyle + 1, 3)
end;
-- memory.writebyte(0x0026, AND(tmp, 0xFB));
end;
memory.register(0x0026, keyintercept);
timer = 0;
mapstyle = 1; -- 0 = hidden, 1 = mini, 2 = bigmap
gamemode = 0;
itemlist = {};
itemlist[0x01] = "Lantrn";
itemlist[0x02] = "Lantrn2";
itemlist[0x03] = "Potion";
itemlist[0x04] = "Potion2";
itemlist[0x05] = "Antidt";
itemlist[0x06] = "Antidt2";
itemlist[0x07] = "Key";
itemlist[0x08] = "GoldKey";
itemlist[0x09] = "Ax";
itemlist[0x0a] = "Ax2";
itemlist[0x0b] = "Sword";
itemlist[0x0c] = "Sword2";
itemlist[0x0d] = "PwSword";
itemlist[0x0e] = "PwSword2";
itemlist[0x0f] = "MsSword";
itemlist[0x10] = "SandraSl";
itemlist[0x11] = "Mantle";
itemlist[0x12] = "Mantle2";
itemlist[0x13] = "Helmet";
itemlist[0x14] = "Helmet2";
itemlist[0x15] = "Tent";
itemlist[0x16] = "Tent2";
itemlist[0x17] = "Tiara";
itemlist[0x18] = "Whale";
itemlist[0x19] = "CureAll";
itemlist[0x1a] = "TimeKey";
itemlist[0x1b] = "Ship";
itemlist[0x1c] = "Cash";
exptable = {
0,
20,
50,
90,
150,
230,
350,
510,
750,
1100,
1600,
2200,
3200,
4400,
6400,
9000,
12000,
15000,
20000,
30000,
40000,
50000,
};
leveltable = {};
leveltable[0] = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x13, 0x14};
leveltable[1] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x07, 0x0A, 0x0D, 0x10, 0x13, 0x14, 0x15};
leveltable[2] = { 0x00, 0x03, 0x06, 0x09, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
asigns = {};
asigns[0x00] = "Aries";
asigns[0x01] = "Taurus";
asigns[0x02] = "Gemini";
asigns[0x03] = "Cancer";
asigns[0x04] = "Leo";
asigns[0x05] = "Virgo";
asigns[0x06] = "Libra";
asigns[0x07] = "Scorpio";
asigns[0x08] = "Sagittarius";
asigns[0x09] = "Capricorn";
asigns[0x0A] = "Aquarius";
asigns[0x0B] = "Pisces";
btypes = {};
btypes[0x00] = "A";
btypes[0x01] = "B";
btypes[0x02] = "O";
btypes[0x03] = "AB";
mapdots = {};
mapdots[1] = {x = 996, y = 1888, color = "#4444ff"}; -- house
mapdots[2] = {x = 773, y = 989, color = "#4444ff"}; -- house
mapdots[3] = {x = 266, y = 2263, color = "#00ff00"}; -- warp point
mapdots[4] = {x = 1800, y = 216, color = "#00ff00"}; -- warp point
mapdots[5] = {x = 776, y = 344, color = "#00ff00"}; -- warp point
mapdots[6] = {x = 2055, y = 2008, color = "#00ff00"}; -- warp point
mapdots[7] = {x = 1863, y = 2045, color = "#dd0000", name = "South Pyramid"}; -- s.pyramid
mapdots[8] = {x = 1607, y = 381, color = "#dd0000", name = "North Pyramid"}; -- n.pyramid
mappoints = table.maxn(mapdots);
while (true) do
timer = timer +1; -- timer for script events
gamemode = memory.readbyte(0x0029); -- game mode
if gamemode == 0x05 or gamemode == 0x01 or gamemode == 0x06 or gamemode == 0x08 then
gameloop();
elseif gamemode == 0x02 then
charaselect();
else
-- gametime = memory.readbyte(0x0031) * 0x3c + memory.readbyte(0x0030); -- game-time
-- gamehour = math.floor(gametime / 320);
-- gameminute = math.floor((gametime - 320 * gamehour) / 320 * 60);
gametimer1 = memory.readbyte(0x0031);
gametimer2 = memory.readbyte(0x0030);
text(190, 8, string.format("Timer: %02X %02X", gametimer1, gametimer2));
text(189, 23, string.format("GameMode: %02x", gamemode));
lifebar(191, 16, 60, 2, gametimer1, 0x80, "#ffffff", "#777777", true);
lifebar(191, 20, 60, 0, gametimer2, 0x3c, "#cccccc", "#555555", true);
end;
FCEU.frameadvance();
end;

View File

@ -1,14 +1,15 @@
--x_functions - various functions needed for scripts witten by Xkeeper
--Written by Xkeeper
x_func_version = 5; x_func_version = 6;
--[[ --[[
Minor version history: Minor version history:
v 5 ----------- v5 -----------
- Added Bisqwit's 'clone table' function. - Added Bisqwit's 'clone table' function.
v6 -----------
- added pairs by keys
- added hitbox functions
@ -50,7 +51,12 @@ end;
-- Draws a rectangle from x1,y1 to x2, y2 -- Draws a rectangle from x1,y1 to x2, y2
function box(x1,y1,x2,y2,color) function box(x1,y1,x2,y2,color)
if (x1 >= 0 and x1 <= 255 and x2 >= 0 and x2 <= 255 and y1 >= 0 and y1 <= 244 and y2 >= 0 and y2 <= 244) then if (x1 >= 0 and x1 <= 255 and x2 >= 0 and x2 <= 255 and y1 >= 0 and y1 <= 244 and y2 >= 0 and y2 <= 244) then
gui.drawbox(x1,y1,x2,y2,color); --[[ local success = pcall(function() gui.drawbox(x1,y1,x2,y2,color); end);
if not success then
text(60, 150, string.format("%3d %3d %3d %3d", x1, y1, x2, y2));
FCEU.pause();
end;
]] gui.drawbox(x1,y1,x2,y2,color);
end; end;
end; end;
@ -147,6 +153,87 @@ table.clone = function(table)
return res return res
end end
spairs = function (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
-- ****************************************************************************
-- * hitbox( coords1, coords2, con, coff )
-- * Checks if any point of coords1 is within coords2.
-- * con/coff determine what colors of box to draw.
-- ****************************************************************************
function hitbox(b1x1, b1y1, b1x2, b1y2, b2x1, b2y1, b2x2, b2y2, con, coff)
if not b1x1 then
text(0, 8, "ERROR!!!!");
return;
end;
local noboxes = false;
if con == nil and coff == nil then
noboxes = true;
else
if coff == nil then
coff = "#00ff00"
end;
if con == nil then
con = "#dd0000";
end;
if coff == nil then
coff = "#00ff00"
end;
end;
boxes = {{
x = {b1x1, b1x2},
y = {b1y1, b1y2},
}, {
x = {b2x1, b2x2},
y = {b2y1, b2y2},
}};
hit = false;
for xc = 1, 2 do
for yc = 1, 2 do
if (boxes[1]['x'][xc] >= boxes[2]['x'][1]) and
(boxes[1]['y'][yc] >= boxes[2]['y'][1]) and
(boxes[1]['x'][xc] <= boxes[2]['x'][2]) and
(boxes[1]['y'][yc] <= boxes[2]['y'][2]) then
hit = true;
-- TODO: make this break out of the for loop? might not be worth it
end;
end;
end;
if hit == true then
if not noboxes then box(b2x1, b2y1, b2x2, b2y2, con); end;
return true;
else
if not noboxes then box(b2x1, b2y1, b2x2, b2y2, coff); end;
return false;
end;
return true;
end;
function x_requires(required) function x_requires(required)
-- Sanity check. If they require a newer version, let them know. -- Sanity check. If they require a newer version, let them know.
timer = 1; timer = 1;
@ -162,7 +249,7 @@ function x_requires(required)
text( 10, 32, string.format("This Lua script requires version %02d or greater.", required)); text( 10, 32, string.format("This Lua script requires version %02d or greater.", required));
text( 43, 42, string.format("Your x_functions.lua is version %02d.", x_func_version)); text( 43, 42, string.format("Your x_functions.lua is version %02d.", x_func_version));
text( 29, 58, "Please check for an updated version at"); text( 29, 58, "Please check for an updated version at");
text( 14, 69, "http://xkeeper.shacknet.nu/"); text( 14, 69, "http://xkeeper.shacknet.nu:5/");
text(114, 78, "emu/nes/lua/x_functions.lua"); text(114, 78, "emu/nes/lua/x_functions.lua");
warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF)); warningboxcolor = string.format("%02X", math.floor(math.abs(30 - math.fmod(timer, 60)) / 30 * 0xFF));

View File

@ -0,0 +1,116 @@
-- ****************************************************************************
-- *
-- * FCEUX Lua GUI tools
-- *
-- ****************************************************************************
control = {};
last = {};
inpt = { xmouse = 0, ymouse = 0 };
-- ****************************************************************************
-- * input.update()
-- * Updates input changes and calculates mouse movement averages.
-- ****************************************************************************
function input.update()
last = table.clone(inpt);
inpt = input.get();
end;
-- ****************************************************************************
-- * control.button( xpos, ypos, width, height, t )
-- * Draws a button that can have some effect. Not quite implemented yet!
-- * width/height are for the outline and more or less have to be set manually.
-- * since height is fixed, though, it's always a multiple.
-- * c disables hitbox checking and sets the outline to that color
-- ****************************************************************************
function control.button(x, y, w, h, t, c, sc)
local h = h * 8;
filledbox( x , y , x + w , y + h , "#000000");
text(x - 1, y - 1, t); -- Yeah, for some reason...
if c and not sc then
box( x - 1, y - 1, x + w + 1, y + h + 1, c);
elseif c then
return (hitbox(inpt['xmouse'], inpt['ymouse'], inpt['xmouse'], inpt['ymouse'], x - 1, y - 1, x + w + 1, y + h + 1, c, c) and (inpt['leftclick'] and not last['leftclick']));
elseif hitbox(inpt['xmouse'], inpt['ymouse'], inpt['xmouse'], inpt['ymouse'], x - 1, y - 1, x + w + 1, y + h + 1, "#6666ff", "#0000ff") and (inpt['leftclick'] and not last['leftclick']) then
box(x - 1, y - 1, x + w + 1, y + h + 1, "#ffffff"); -- for white-flash highlighting
return true;
end;
return false;
end;
-- ****************************************************************************
-- * control.showmenu( xpos, ypos, menutable )
-- * Displays the given menu and takes action on it. Usually.
-- ****************************************************************************
function control.showmenu(x, y, menuinfo)
if menuinfo['life'] > 0 then
local temp = 0;
local i = 0;
local yscale = 11 - math.max(0, menuinfo['life'] - 60);
-- text(x, y - 11, string.format("Life: %3d", menuinfo['life']));
for k, v in spairs(menuinfo['menu']) do
local buttoncolor = nil;
if v['menu'] and v['life'] > 0 then
buttoncolor = "#ffffff";
end;
buttonclicked = control.button(x, y + yscale * i, menuinfo['width'], 1, v['label'], buttoncolor, true);
if v['menu'] then
text(x + menuinfo['width'] - 6, y + yscale * i - 1, ">");
end;
if v['marked'] == 1 then
text(x, y + yscale * i - 1, ">");
end;
-- is a selection, not a submenu
if buttonclicked and v['action'] then
v['action'](v['args']);
menuinfo['life'] = 0;
return -1;
-- a submenu
elseif buttonclicked and v['menu'] then
v['life'] = 70;
end;
if v['menu'] and v['life'] > 0 and temp >= 0 then
temp2 = control.showmenu(x + menuinfo['width'] + 3, y + yscale * i, v);
if temp2 >= 0 then
temp = math.max(temp, temp2);
else
temp = temp2;
end;
end;
i = i + 1;
end;
if temp >= 0 and hitbox(inpt['xmouse'], inpt['ymouse'], inpt['xmouse'], inpt['ymouse'], x, y, x + menuinfo['width'] + 2, y + i * yscale) then
menuinfo['life'] = math.max(menuinfo['life'] - 1, 60);
elseif temp == -1 or (menuinfo['life'] < 60 and inpt['leftclick'] and not last['leftclick']) then
menuinfo['life'] = 0;
return 0;
else
menuinfo['life'] = math.max(math.min(60, temp), menuinfo['life'] - 1);
end;
end;
return menuinfo['life'];
end;

View File

@ -0,0 +1,44 @@
-- temporary file because this will be huge.
handles = {};
handles[ 1] = { x1 = 0, y1 = 0, x2 = 16, y2 = 24 }; -- Green & Red Koopa
handles[ 2] = { x1 = 0, y1 = 8, x2 = 16, y2 = 24 }; -- Goomba
handles[ 3] = { x1 = 0, y1 = 0, x2 = 16, y2 = 16 }; -- generic 16x16
handles[ 4] = { x1 = 0, y1 = 0, x2 = 8, y2 = 8 }; -- generic 8x 8
enemylist = {};
-- type:
-- Default (0): selectable, standard
-- + 0x01: requires special handling
-- + 0x02: can't be selected (dupe, whatever)
-- + 0x10: requires two spaces to summon
-- + 0x20: powerup
--[[
enemylist[] = { id = 0x00, name = "Green Koopa", handle = 1, hitbox = 0x03, type = 0x00 };
enemylist[] = { id = 0x01, name = "Red Koopa", handle = 1, hitbox = 0x03, type = 0x01 }; -- Will jitter back and forth if moved into air
enemylist[] = { id = 0x06, name = "Goomba", handle = 2, hitbox = 0x09, type = 0x00 };
enemylist[] = { id = 0x07, name = "Blooper", handle = 1, hitbox = 0x09, type = 0x01 }; -- Uhh? It just vanishes out of nowhere...
enemylist[] = { id = 0x0A, name = "Gray Cheep-Cheep", handle = 2, hitbox = 0x09, type = 0x00 };
enemylist[] = { id = 0x0B, name = "Red Cheep-Cheep", handle = 2, hitbox = 0x09, type = 0x00 };
enemylist[] = { id = 0x0D, name = "Pirahna Plant", handle = 1, hitbox = 0x09, type = 0x01 }; -- x speed is really y speed, main position needs hacked
enemylist[] = { id = 0x0E, name = "Green Paratroopa", handle = 1, hitbox = 0x03, type = 0x00 };
enemylist[] = { id = 0x14, name = "Flying Cheepcheep", handle = 2, hitbox = 0x09, type = 0x00 };
enemylist[] = { id = 0x2E, name = "Mushroom", handle = 3, hitbox = 0x03, type = 0x20, powerupval = 0x00 };
enemylist[] = { id = 0x2E, name = "Flower", handle = 3, hitbox = 0x03, type = 0x20, powerupval = 0x01 };
enemylist[] = { id = 0x2E, name = "Starman", handle = 3, hitbox = 0x03, type = 0x20, powerupval = 0x02 };
enemylist[] = { id = 0x2E, name = "1-up Mushroom", handle = 3, hitbox = 0x03, type = 0x20, powerupval = 0x03 };
enemylist[] = { id = 0x30, name = "Flagpole flag", handle = 3, hitbox = -1, type = 0x20 };
enemylist[] = { id = 0x31, name = "Castle flag", handle = 3, hitbox = -1, type = 0x00 };
enemylist[] = { id = 0x32, name = "Springboard", handle = 1, hitbox = -1, type = 0x00 };
]]