Zophar's Message Domain

Go Back   Zophar's Message Domain > Emulation Talk > Emulation News

Reply
 
Thread Tools Display Modes
Old 08-16-2018, 09:32 PM   #1
dlevere
Content Manager
 
Join Date: Sep 2017
Location: Philadelphia, PA
Posts: 177
Default The best SNES emulators available

Want to play SNES classics on your PC?

These emulators make it easy
__________________
The Hackmaster
dlevere is offline   Reply With Quote
Old 08-17-2018, 02:36 PM   #2
crazygerry
Junior Member
 
Join Date: Jul 2018
Posts: 3
Default LUA

Nice post.

I'm really interested in new emulators.
By the way... RetroArch is a good one, too.

Unfortunately, most of the emulators doesn't support lua.

I'm used to play Lemmings and SimCity with a mouse,
so I stick with the lua compliant ones... and that is unfortunately just one.

htxxps:..github.com/gocha/snes9x/releases

If you like to play SimCity with a mouse and some other stuff check it out.

You need the following ROM:
Name: SIMCITY
Header Checksum: 39B3
Output: NTSC 60Hz
CRC32: 8AEDD3A1
Licensee: Nintendo
ROM Version: 1.0
Region: USA/Canada


Copy the following code to a file (simcity.lua).

Load the SIMCITY ROM and then the simcity.lua file with the mentioned emulator.

Enjoy Simcity with mouse.

simcity.lua
Code:
print("SimCity grid viewer, for snes9x-rr 1.43 ~ 1.51")
print("written by Dammit, 2/21/2009 ~ 6/2/2011") --dammit9x at hotmail dot com
print("mouse support by crazygerry 2018")
print("tested with: https://github.com/gocha/snes9x/ 1.53 ~ 1.55")
--(old) use with: http://code.google.com/p/snes9x-rr/
--purpose: display land values and other parameters on the playfield for the SimCity game
--discussion: http://tasvideos.org/forum/viewtopic.php?p=192582#192582

local hotkey = { --hotkey settings
	mode_inc    = {"K", "cycle view modes forward (or middleclick)"},
	mode_dec    = {"L", "cycle view modes backward"},
	show_values = {"U", "show/hide grid values"},
	show_grid   = {"I", "show/hide the grid"},
	show_coords = {"O", "show/hide the map coordinates and city center"},
	num_format  = {"P", "switch between decimal & hex numbers"},
}

local globals = { --initial settings
	view_mode   = 1,
	show_values = true,
	show_grid   = true,
	show_coords = false,
	hex_numbers = false,
	use_mouse = true,
}

local label_x, label_y = 128, 216 --where to draw the view mode label
local coord_x, coord_y = 216, 216 --where to draw the map coordinates

local color = {
	["level 8"]     = 0xFF0000, --these are the in-game map colors
	["level 7"]     = 0xFF6300,
	["level 6"]     = 0xFFB500,
	["level 5"]     = 0xFFFF00,
	["level 4"]     = 0x00FF00,
	["level 3"]     = 0x00BD00,
	["level 2"]     = 0x008C00,
	["level 1"]     = 0x005A00,
	["powered"]     = 0xFF8400,
	["unpowered"]   = 0x00B500,
	["city center"] = 0xFF00FF,
	["dec text"]    = 0xFFFFFF, --grid values in decimal mode
	["hex text"]    = 0xFFFF00, --grid values in hexadecimal mode
	["label text"]  = 0x00FF00, --view mode label text
	["coord text"]  = 0x00FFFF, --coordinate text
}

local opacity = {
	fill    = 0x20, --inside of boxes
	outline = 0xA0, --outside of boxes
	text    = 0xFF,
}

--------------------------------------------------------------------------------

--prepare color settings
local fill, outline = {}, {}
local function map_colors(index, name)
	fill[index]    = bit.lshift(color[name], 8) + opacity.fill
	outline[index] = bit.lshift(color[name], 8) + opacity.outline
end

for i = 0xFF, 0, -1 do
	if i > 0xE0 then map_colors(i, "level 8")
	elseif i > 0xC0 then map_colors(i, "level 7")
	elseif i > 0xA0 then map_colors(i, "level 6")
	elseif i > 0x80 then map_colors(i, "level 5")
	elseif i > 0x60 then map_colors(i, "level 4")
	elseif i > 0x40 then map_colors(i, "level 3")
	elseif i > 0x20 then map_colors(i, "level 2")
	elseif i > 0x00 then map_colors(i, "level 1")
	else
		fill[i]    = 0 --blank/transparent
		outline[i] = 0
	end
end
map_colors(true, "powered")
map_colors(false, "unpowered")
map_colors("city center", "city center")
fill["dec text"]   = bit.lshift(color["dec text"], 8) + opacity.text
fill["hex text"]   = bit.lshift(color["hex text"], 8) + opacity.text
fill["label text"] = bit.lshift(color["label text"], 8) + opacity.text
fill["coord text"] = bit.lshift(color["coord text"], 8) + opacity.text

--memory addresses
local address = {
	x_tile   = 0x7E01BD, --camera position by upper-left tile
	y_tile   = 0x7E01BF,
	x_center = 0x7E0BA9, --coordinate of the city center
	y_center = 0x7E0BAA,
	playing  = 0x7E0012, --a game is in progress: draw coords
	hud      = 0x7E2210, --in-game HUD is shown: don't draw grid
	dark     = 0x7E90FF, --darkened BG: don't draw grid
	magnify  = 0x7E019B, --magnifier tool is open: draw grid
	time     = 0x7E0B51, --increments four times per game month; currently unused
	x_cursor = 0x7E01EB,
	y_cursor = 0x7E01ED,
	taxind   = 0x7E2016, -- holds some values to identify tax screen
}

--parameter values are stored here
local view = {
	{address = 0x7F6B00, sqsize = 2, bytes = 1, name = "Land value"},
	{address = 0x7F76B8, sqsize = 2, bytes = 1, name = "Crime"},
	{address = 0x7F8270, sqsize = 2, bytes = 1, name = "Pollution"},
	{address = 0x7F8E28, sqsize = 2, bytes = 1, name = "Population density"},
	{address = 0x7F99E0, sqsize = 2, bytes = 1, name = "Traffic"},
	{address = 0x7FA598, sqsize = 1, bytes = 1/8, name = "Power"},
	{address = 0x7FAB74, sqsize = 4, bytes = 1, name = "Land value modifier"},
	{address = 0x7FAE62, sqsize = 8, bytes = 2, name = "Growth rate"},
	{address = 0x7FAFE8, sqsize = 8, bytes = 1, name = "Police coverage"},
	{address = 0x7FB0AB, sqsize = 8, bytes = 1, name = "Fire coverage"},
}

local screenwidth, screenheight, tilesize = 256, 224, 8 --size in pixels
local mapwidth, mapheight = 120, 100 --size in tiles
local pressing_old = {} --array for keyboard input

for _, mode in ipairs(view) do
	mode.y_step = mapwidth / mode.sqsize
	mode.read = mode.bytes == 2 and memory.readwordsigned or memory.readbyte
end

print()
print("To enable the grid, hide the HUD with button Y or open the magnifier.")
print()
for _, v in pairs(hotkey) do
	print("Press the '" .. v[1] .. "' key to " .. v[2] .. ".")
end

function bit(p) --http://lua-users.org/wiki/BitwiseOperators
	return 2 ^ (p - 1)
end

function hasbit(x, p)
	return x % (p + p) >= p
end

local function draw_boxes()
	local x_tile, y_tile, mode = globals.x_tile, globals.y_tile, view[globals.view_mode]
	local y = 0
	while y < screenheight do
		local y_next = y + mode.sqsize * tilesize
		if y == 0 then
			y_next = (mode.sqsize - y_tile % mode.sqsize) * tilesize
		end
		if y_next > screenheight then
			y_next = screenheight
		end
		local x = 0
		while x < screenwidth do
			local x_next = x + mode.sqsize * tilesize
			if x == 0 then
				x_next = (mode.sqsize - x_tile % mode.sqsize) * tilesize
			end
			if x_next > screenwidth then
				x_next = screenwidth
			end
			if x_tile + x/tilesize >= 0 and y_tile + y/tilesize >= 0 --check the map boundaries
			and x_tile + x/tilesize < mapwidth and y_tile + y/tilesize < mapheight then
				local value = mode.read(mode.address + math.floor(
				(math.floor((x_tile + x/tilesize) / mode.sqsize)
				+ math.floor((y_tile + y/tilesize) / mode.sqsize) * mode.y_step) * mode.bytes))

				if globals.show_grid then
					if mode.read == memory.readwordsigned then
						if value > 0xFF then value = 0xFF end
						if value < -0xFF then value = -0xFF end
						value = math.floor((value + 0xFF) / 2)
					end
					if mode.bytes < 1 then
						value = hasbit(value, bit(8 - (x_tile + x/tilesize + (y_tile + y/tilesize) * mode.y_step) % 8))
					end
					gui.box(x, y, x_next-1, y_next-1, fill[value], outline[value])
				end

				if globals.show_values and value ~= 0 and mode.sqsize > 1 and
					x_next >= 2 * tilesize and y_next >= 2 * tilesize and
					x + 2 * tilesize <= screenwidth and y + 2 * tilesize <= screenheight then
					local color
					if globals.hex_numbers then
						value, color = string.format("%02X", value), fill["hex text"]
					else
						value, color = string.format("%d", value), fill["dec text"]
					end
					gui.text(x_next - value:len() * 4 - 1, y + 1, value, color)
				end

			end
			x = x_next
		end
		y = y_next
	end

	if globals.show_grid or globals.show_values then --show the label only with the grid or values active
		gui.text(label_x, label_y, mode.name, fill["label text"])
	end
end

local function draw_data()
	local x_tile, y_tile, x_center, y_center = globals.x_tile, globals.y_tile, globals.x_center, globals.y_center
	if globals.grid_ok then
		draw_boxes()
	end

	if globals.show_coords then --show the coordinates & city center
		if globals.use_mouse == false then
			gui.text(coord_x, coord_y, "(" .. x_tile .. ", " .. y_tile .. ")", fill["coord text"])
		end

		local xdraw, ydraw = (x_center - x_tile) * tilesize, (y_center - y_tile) * tilesize
		if x_center < x_tile then
			xdraw = 0
		end
		if x_center >= x_tile + screenwidth/tilesize then
			xdraw = screenwidth - tilesize
		end
		if y_center < y_tile then
			ydraw = 0
		end
		if y_center >= y_tile + screenheight/tilesize then
			ydraw = screenheight - tilesize
		end
		gui.box(xdraw, ydraw, xdraw + 7, ydraw + 7, fill["city center"], outline["city center"])
	end
end

local function mouse_support(inp)
	local taxscreenindicatorvalue = memory.readbyte(address.taxind)
	local taxscreenindicatorvalues = {131,133,135,137,139,141,195,197,199,201}
	local taxscreenvisible, movemap = false, false
	local pad = joypad.get(1)
	local x_mousepos, y_mousepos = math.floor(inp.xmouse/8), math.floor(inp.ymouse/8)
	local x_mouseonmap, y_mouseonmap = x_mousepos + memory.readbytesigned(address.x_tile), y_mousepos + memory.readbytesigned(address.y_tile)
	for i = 1, 10 do
		if taxscreenindicatorvalues[i] == taxscreenindicatorvalue then taxscreenvisible = true break end
	end
	if taxscreenvisible == false then	
		if(x_mouseonmap >= 0 and x_mouseonmap < mapwidth and y_mouseonmap >= 0 and y_mouseonmap < mapheight) then
			gui.text(coord_x, coord_y, "(" .. x_mouseonmap+1 .. ", " .. y_mouseonmap+1 .. ")", fill["coord text"])		
		end
		if(x_mouseonmap >= -6 and x_mouseonmap < mapwidth+6 and y_mouseonmap >= -6 and y_mouseonmap < mapheight+6) then
			memory.writebyte(address.x_cursor,x_mousepos*8)
			memory.writebyte(address.y_cursor,y_mousepos*8)			
		end
		if(inp.xmouse > 232) then memory.writebyte(address.x_cursor,232) end
		if(inp.xmouse < 16) then memory.writebyte(address.x_cursor,16) end
		if(inp.ymouse > 192) then memory.writebyte(address.y_cursor,192) end
		if(inp.ymouse < 24) then memory.writebyte(address.y_cursor,24) end
	end
	if (inp.xmouse >= screenwidth-1) then movemap, pad.right = true, true joypad.set(1,pad) end
	if (inp.xmouse <= 0) then movemap, pad.left = true, true joypad.set(1,pad) end
	if (inp.ymouse >= screenheight-1) then movemap, pad.down = true, true joypad.set(1,pad) end
	if (inp.ymouse <= 0) then movemap, pad.up = true, true joypad.set(1,pad) end
	if (movemap and inp.leftclick == false) then pad.Y = true end
	if (inp.leftclick) then pad.B = true joypad.set(1,pad) end
	if (inp.rightclick) then pad.X = true joypad.set(1,pad) end
end

emu.registerafter(function()
	globals.game_playing = memory.readbyte(address.playing) > 0
	if not globals.game_playing then
		pressing_old = {}
		return
	end

	globals.grid_ok = memory.readbyte(address.dark) == 0 and 
		(memory.readword(address.hud) == 0x5555 or memory.readbyte(address.magnify) > 0)
	globals.x_tile, globals.y_tile = memory.readbytesigned(address.x_tile), memory.readbytesigned(address.y_tile)
	globals.x_center, globals.y_center = memory.readbyte(address.x_center), memory.readbyte(address.y_center)
	
	local pressing = input.get()
	
	if (globals.show_grid or globals.show_values) and globals.grid_ok then
		if (pressing[hotkey.mode_inc[1]] or pressing.middleclick) and not (pressing_old[hotkey.mode_inc[1]] or pressing_old.middleclick) then
			globals.view_mode = globals.view_mode >= #view and 1 or globals.view_mode + 1
		elseif pressing[hotkey.mode_dec[1]] and not pressing_old[hotkey.mode_dec[1]] then
			globals.view_mode = globals.view_mode == 1 and #view or globals.view_mode - 1
		end
	end
	if pressing[hotkey.show_values[1]] and not pressing_old[hotkey.show_values[1]] and globals.grid_ok then
		globals.show_values = not globals.show_values
	end
	if pressing[hotkey.show_grid[1]] and not pressing_old[hotkey.show_grid[1]] and globals.grid_ok then
		globals.show_grid = not globals.show_grid
	end
	if pressing[hotkey.show_coords[1]] and not pressing_old[hotkey.show_coords[1]] then
		globals.show_coords = not globals.show_coords
	end
	if pressing[hotkey.num_format[1]] and not pressing_old[hotkey.num_format[1]] and globals.show_values then
		globals.hex_numbers = not globals.hex_numbers
	end

	pressing_old = pressing
end)

gui.register(function()
	if globals.game_playing then
		draw_data()
		if globals.use_mouse then
			mouse_support(input.get())
		end
	end
end)
Have fun !

Last edited by crazygerry; 08-24-2018 at 11:35 AM.
crazygerry is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT. The time now is 12:01 AM.

Contact Us - Zophar's Domain - Archive - Top

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.