rendered paste body-- Sonic - Mouse Control-- Adds the ability to move game objects using the mouse.-- Written by: deltaphcif not gens.emulating() then error("ROM must be loaded first.")endchecksum = memory.readword(0x18E)if checksum == 0x264A or checksum == 0xAFC7 then -- Sonic 1 print("Detected Sonic 1.") ostentry = "s1s2" addr_xcamera = 0xFFF700 addr_ycamera = 0xFFF616 addr_startedflag = 0xFFFE02 addr_dirtyflag = 0xFFF72C addr_levellayout = 0xFFA400 addr_ost = 0xFFD000 addr_ostend = 0xFFEFFF ost_length = 0x40 ost_x = 0x08 ost_y = 0x0C ost_xspeed = 0x10 ost_yspeed = 0x12 level_rowlength = 0x40 level_tilesize = 256elseif checksum == 0xD951 then -- Sonic 2 print("Detected Sonic 2.") ostentry = "s1s2" addr_xcamera = 0xFFEE00 addr_ycamera = 0xFFEE04 addr_startedflag = 0xFFF711 addr_dirtyflag = 0xFFF72C addr_levellayout = 0xFF8000 addr_ost = 0xFFB000 addr_ostend = 0xFFD5FF ost_length = 0x40 ost_x = 0x08 ost_y = 0x0C ost_xspeed = 0x10 ost_yspeed = 0x12 level_rowlength = 0x80 level_tilesize = 128elseif checksum == 0xA8F2 or checksum == 0xDFB3 then -- Sonic 3/K print("Detected Sonic 3/K.") ostentry = "s3sk" addr_xcamera = 0xFFEE78 addr_ycamera = 0xFFEE7C addr_startedflag = 0xFFF711 addr_dirtyflag = 0xFFF72C addr_levellayout = 0xFF8000 addr_ost = 0xFFB000 addr_ostend = 0xFFCFCB ost_length = 0x4A ost_x = 0x10 ost_y = 0x14 ost_xspeed = 0x18 ost_yspeed = 0x1A level_rowlength = 0 -- varies per level level_tilesize = 128else error("Unable to detect game. Make sure it's a clean Sonic 1/2/3/K ROM.")enddragobject = nilxmouse = 0ymouse = 0xmousedelta = 0ymousedelta = 0leftclickdown = falserightclickdown = falseinput_state = {}draw_queue = {}pinned = {}memory.register(addr_startedflag, function() if memory.readbyte(addr_startedflag) == 0 then pinned = {} endend)gui.register( function() local item = draw_queue[1] while item do item[1](item[2], item[3], item[4], item[5], item[6], item[7]) table.remove(draw_queue, 1) item = draw_queue[1] end input_state = input.get() if do_button("Objects", 0, 216, 30, 7) then workfunc = work_objects end if ostentry == s1s2_ostentry then if do_button("Tiles", 35, 216, 22, 7) then workfunc = work_tiles end endend)gens.registerbefore( function() local xcamera = memory.readword(addr_xcamera) local ycamera = memory.readword(addr_ycamera) xmousedelta = input_state.xmouse - xmouse ymousedelta = input_state.ymouse - ymouse xmouse = input_state.xmouse ymouse = input_state.ymouse workfunc(xcamera, ycamera)end)function work_tiles(xcamera, ycamera) local xtile1, ytile1, tilepos, tilenum, x1, y1, x2, y2 xtile1 = math.floor((xcamera + xmouse) / level_tilesize) ytile1 = math.floor((ycamera + ymouse) / level_tilesize) tilepos = addr_levellayout + (((ytile1 * level_rowlength) * 2) + xtile1) tilenum = memory.readbyte(tilepos) x1 = (xtile1 * level_tilesize) - xcamera y1 = (ytile1 * level_tilesize) - ycamera x2 = x1 + level_tilesize y2 = y1 + level_tilesize table.insert(draw_queue, {gui.box, x1, y1, x2, y2, {0,0,0,0}, {255, 255, 255, 255}}) table.insert(draw_queue, {gui.text, x1 + 2, y1 + 2, string.format("%02X", tilenum)}) if do_button("-", x2 - 17, y1 + 2, 7, 9) then memory.writebyte(tilepos, tilenum - 1) memory.writebyte(addr_dirtyflag, 1) end if do_button("+", x2 - 9, y1 + 2, 7, 9) then memory.writebyte(tilepos, tilenum + 1) memory.writebyte(addr_dirtyflag, 1) endendfunction work_objects(xcamera, ycamera) local i, entry, x1, y1, x2, y2, outline_color for i=addr_ost,addr_ostend,ost_length do entry = ostentry(i) if entry then local width, height if entry.widthhalf > 0 then width = entry.widthhalf elseif entry.width > 0 then width = entry.width else width = 8 end if ostentry == s1s2_ostentry then if entry.heighthalf > 0 then height = entry.heighthalf else height = 8 end elseif ostentry == s3sk_ostentry then if entry.heighthalf > 0 then height = entry.heighthalf elseif entry.height > 0 then height = entry.height else height = 8 end end if pinned[tostring(entry.baseaddr)] == nil then x1 = (entry.x - width) - xcamera y1 = (entry.y - height) - ycamera x2 = (entry.x + width) - xcamera y2 = (entry.y + height) - ycamera else local x = pinned[tostring(entry.baseaddr)][1] local y = pinned[tostring(entry.baseaddr)][2] x1 = x - width y1 = y - height x2 = x + width y2 = y + height memory.writeword(i + ost_x, xcamera + x) memory.writeword(i + ost_y, ycamera + y) memory.writeword(i + ost_xspeed, 0) memory.writeword(i + ost_yspeed, 0) end if (xmouse >= x1 and ymouse >= y1) and (xmouse <= x2 and ymouse <= y2) then outline_color = {255, 0, 0, 255} if input_state.leftclick then if pinned[tostring(entry.baseaddr)] ~= nil then pinned[tostring(entry.baseaddr)][1] = xmouse pinned[tostring(entry.baseaddr)][2] = ymouse end if not leftclickdown then dragobject = entry.baseaddr leftclickdown = true end else leftclickdown = false dragobject = nil end if input_state.rightclick then if not rightclickdown then if pinned[tostring(entry.baseaddr)] == nil then pinned[tostring(entry.baseaddr)] = {xmouse, ymouse} else pinned[tostring(entry.baseaddr)] = nil end rightclickdown = true end else rightclickdown = false end else if pinned[tostring(entry.baseaddr)] ~= nil then outline_color = {0, 255, 0, 255} else outline_color = {255, 255, 255, 255} end end if dragobject ~= nil then if pinned[tostring(dragobject)] ~= nil then pinned[tostring(dragobject)][1] = xmouse pinned[tostring(dragobject)][2] = ymouse end memory.writeword(dragobject + ost_x, xcamera + xmouse) memory.writeword(dragobject + ost_y, ycamera + ymouse) memory.writeword(dragobject + ost_xspeed, xmousedelta * 100) memory.writeword(dragobject + ost_yspeed, ymousedelta * 100) end table.insert(draw_queue, {gui.box, x1, y1, x2, y2, {0,0,0,0}, outline_color}) end endendfunction s1s2_ostentry(address) local entry = {} entry.baseaddr = address entry.id = memory.readbyte(address) if entry.id == 0 or entry.id == nil then return nil end entry.renderflags = memory.readbyte(address + 0x01) entry.artindex = memory.readword(address + 0x02) entry.mappings = memory.readdword(address + 0x04) entry.x = memory.readword(address + 0x08) entry.xsub = memory.readword(address + 0x0A) entry.y = memory.readword(address + 0x0C) entry.ysub = memory.readword(address + 0x0E) entry.xspeed = memory.readword(address + 0x10) entry.yspeed = memory.readword(address + 0x12) entry.inertia = memory.readword(address + 0x14) entry.heighthalf = memory.readbyte(address + 0x16) entry.widthhalf = memory.readbyte(address + 0x17) entry.priority = memory.readbyte(address + 0x18) entry.width = memory.readbyte(address + 0x19) entry.dispframe = memory.readbyte(address + 0x1A) entry.animframe = memory.readbyte(address + 0x1B) entry.animnum = memory.readbyte(address + 0x1C) entry.animrestart = memory.readbyte(address + 0x1D) entry.animtime = memory.readbyte(address + 0x1E) entry.collision = memory.readbyte(address + 0x20) entry.colcustom = memory.readbyte(address + 0x21) entry.status = memory.readbyte(address + 0x22) entry.respawn = memory.readbyte(address + 0x23) entry.counter = memory.readbyte(address + 0x24) entry.counter2 = memory.readbyte(address + 0x25) entry.angle = memory.readbyte(address + 0x26) entry.angle2 = memory.readbyte(address + 0x27) entry.subtype = memory.readbyte(address + 0x28) entry.parent = memory.readword(address + 0x3E) return entryendfunction s3sk_ostentry(address) local entry = {} entry.baseaddr = address entry.pointer = memory.readdword(address) if entry.pointer == 0 or entry.pointer == nil then return nil end entry.renderflags = memory.readbyte(address + 0x04) entry.routine = memory.readbyte(address + 0x05) entry.height = memory.readbyte(address + 0x06) entry.width = memory.readbyte(address + 0x07) entry.priority = memory.readword(address + 0x08) entry.artindex = memory.readword(address + 0x0A) entry.mappings = memory.readdword(address + 0x0C) entry.x = memory.readword(address + 0x10) entry.xsub = memory.readword(address + 0x12) entry.y = memory.readword(address + 0x14) entry.ysub = memory.readword(address + 0x16) entry.xspeed = memory.readword(address + 0x18) entry.yspeed = memory.readword(address + 0x1A) entry.inertia = memory.readword(address + 0x1C) entry.heighthalf = memory.readbyte(address + 0x1E) entry.widthhalf = memory.readbyte(address + 0x1F) entry.animnum = memory.readbyte(address + 0x20) entry.animrestart = memory.readbyte(address + 0x21) entry.dispframe = memory.readbyte(address + 0x22) entry.animframe = memory.readbyte(address + 0x23) entry.animtime = memory.readbyte(address + 0x24) entry.animcounter = memory.readbyte(address + 0x25) entry.angle = memory.readbyte(address + 0x26) entry.angle2 = memory.readbyte(address + 0x27) entry.collision = memory.readbyte(address + 0x28) entry.colcustom = memory.readbyte(address + 0x29) entry.status = memory.readbyte(address + 0x2A) entry.shieldreact = memory.readbyte(address + 0x2B) entry.subtype = memory.readbyte(address + 0x2C) entry.respawn = memory.readword(address + 0x48) return entryendfunction do_button(text, x, y, width, height) local return_value, fill_color, outline_color if (input_state.xmouse >= x and input_state.ymouse >= y) and (input_state.xmouse <= x + width and input_state.ymouse <= y + height) then outline_color = {255, 255, 255, 255} if input_state.leftclick then if not leftclickdown then return_value = true leftclickdown = true end fill_color = {127, 0, 0, 255} else leftclickdown = false fill_color = {0, 0, 192, 255} end else fill_color = {0, 0, 127, 255} outline_color = {0, 0, 255, 255} end gui.box(x, y, x + width, y + height, fill_color, outline_color) gui.text(x + 2, y + 2, text, {255, 255, 255, 255}, {0, 0, 0, 0}) return return_valueendif ostentry == "s1s2" then ostentry = s1s2_ostentryelseif ostentry == "s3sk" then ostentry = s3sk_ostentryendworkfunc = work_objects