--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;

