Advertisement
Guest User

simcity grid viewer

a guest
Jun 3rd, 2011
582
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.38 KB | None | 0 0
  1. print("SimCity grid viewer, for snes9x-rr 1.43 ~ 1.51")
  2. print("written by Dammit, 2/21/2009 ~ 6/2/2011") --dammit9x at hotmail dot com
  3. --use with: http://code.google.com/p/snes9x-rr/
  4. --purpose: display land values and other parameters on the playfield for the SimCity game
  5. --discussion: http://tasvideos.org/forum/viewtopic.php?p=192582#192582
  6.  
  7. local hotkey = { --hotkey settings
  8.     mode_inc    = {"rightbracket", "cycle view modes forward"},
  9.     mode_dec    = {"leftbracket", "cycle view modes backward"},
  10.     show_values = {"V", "show/hide grid values"},
  11.     show_grid   = {"G", "show/hide the grid"},
  12.     show_coords = {"C", "show/hide the map coordinates and city center"},
  13.     num_format  = {"N", "switch between decimal & hex numbers"},
  14. }
  15.  
  16. local globals = { --initial settings
  17.     view_mode   = 1,
  18.     show_values = true,
  19.     show_grid   = true,
  20.     show_coords = true,
  21.     hex_numbers = false,
  22. }
  23.  
  24. local label_x, label_y = 128, 216 --where to draw the view mode label
  25. local coord_x, coord_y = 216, 216 --where to draw the map coordinates
  26.  
  27. local color = {
  28.     ["level 8"]     = 0xFF0000, --these are the in-game map colors
  29.     ["level 7"]     = 0xFF6300,
  30.     ["level 6"]     = 0xFFB500,
  31.     ["level 5"]     = 0xFFFF00,
  32.     ["level 4"]     = 0x00FF00,
  33.     ["level 3"]     = 0x00BD00,
  34.     ["level 2"]     = 0x008C00,
  35.     ["level 1"]     = 0x005A00,
  36.     ["powered"]     = 0xFF8400,
  37.     ["unpowered"]   = 0x00B500,
  38.     ["city center"] = 0xFF00FF,
  39.     ["dec text"]    = 0xFFFFFF, --grid values in decimal mode
  40.     ["hex text"]    = 0xFFFF00, --grid values in hexadecimal mode
  41.     ["label text"]  = 0x00FF00, --view mode label text
  42.     ["coord text"]  = 0x00FFFF, --coordinate text
  43. }
  44.  
  45. local opacity = {
  46.     fill    = 0x20, --inside of boxes
  47.     outline = 0xA0, --outside of boxes
  48.     text    = 0xFF,
  49. }
  50.  
  51. --------------------------------------------------------------------------------
  52.  
  53. --prepare color settings
  54. local fill, outline = {}, {}
  55. local function map_colors(index, name)
  56.     fill[index]    = bit.lshift(color[name], 8) + opacity.fill
  57.     outline[index] = bit.lshift(color[name], 8) + opacity.outline
  58. end
  59.  
  60. for i = 0xFF, 0, -1 do
  61.     if i > 0xE0 then map_colors(i, "level 8")
  62.     elseif i > 0xC0 then map_colors(i, "level 7")
  63.     elseif i > 0xA0 then map_colors(i, "level 6")
  64.     elseif i > 0x80 then map_colors(i, "level 5")
  65.     elseif i > 0x60 then map_colors(i, "level 4")
  66.     elseif i > 0x40 then map_colors(i, "level 3")
  67.     elseif i > 0x20 then map_colors(i, "level 2")
  68.     elseif i > 0x00 then map_colors(i, "level 1")
  69.     else
  70.         fill[i]    = 0 --blank/transparent
  71.         outline[i] = 0
  72.     end
  73. end
  74. map_colors(true, "powered")
  75. map_colors(false, "unpowered")
  76. map_colors("city center", "city center")
  77. fill["dec text"]   = bit.lshift(color["dec text"], 8) + opacity.text
  78. fill["hex text"]   = bit.lshift(color["hex text"], 8) + opacity.text
  79. fill["label text"] = bit.lshift(color["label text"], 8) + opacity.text
  80. fill["coord text"] = bit.lshift(color["coord text"], 8) + opacity.text
  81.  
  82. --memory addresses
  83. local address = {
  84.     x_tile   = 0x7E01BD, --camera position by upper-left tile
  85.     y_tile   = 0x7E01BF,
  86.     x_center = 0x7E0BA9, --coordinate of the city center
  87.     y_center = 0x7E0BAA,
  88.     playing  = 0x7E0012, --a game is in progress: draw coords
  89.     hud      = 0x7E2210, --in-game HUD is shown: don't draw grid
  90.     dark     = 0x7E90FF, --darkened BG: don't draw grid
  91.     magnify  = 0x7E019B, --magnifier tool is open: draw grid
  92.     time     = 0x7E0B51, --increments four times per game month; currently unused
  93. }
  94.  
  95. --parameter values are stored here
  96. local view = {
  97.     {address = 0x7F6B00, sqsize = 2, bytes = 1, name = "Land value"},
  98.     {address = 0x7F76B8, sqsize = 2, bytes = 1, name = "Crime"},
  99.     {address = 0x7F8270, sqsize = 2, bytes = 1, name = "Pollution"},
  100.     {address = 0x7F8E28, sqsize = 2, bytes = 1, name = "Population density"},
  101.     {address = 0x7F99E0, sqsize = 2, bytes = 1, name = "Traffic"},
  102.     {address = 0x7FA598, sqsize = 1, bytes = 1/8, name = "Power"},
  103.     {address = 0x7FAB74, sqsize = 4, bytes = 1, name = "Land value modifier"},
  104.     {address = 0x7FAE62, sqsize = 8, bytes = 2, name = "Growth rate"},
  105.     {address = 0x7FAFE8, sqsize = 8, bytes = 1, name = "Police coverage"},
  106.     {address = 0x7FB0AB, sqsize = 8, bytes = 1, name = "Fire coverage"},
  107. }
  108.  
  109. local screenwidth, screenheight, tilesize = 256, 224, 8 --size in pixels
  110. local mapwidth, mapheight = 120, 100 --size in tiles
  111. local pressing_old = {} --array for keyboard input
  112.  
  113. for _, mode in ipairs(view) do
  114.     mode.y_step = mapwidth / mode.sqsize
  115.     mode.read = mode.bytes == 2 and memory.readwordsigned or memory.readbyte
  116. end
  117.  
  118. print()
  119. print("To enable the grid, hide the HUD with button Y or open the magnifier.")
  120. print()
  121. for _, v in pairs(hotkey) do
  122.     print("Press the '" .. v[1] .. "' key to " .. v[2] .. ".")
  123. end
  124.  
  125. function bit(p) --http://lua-users.org/wiki/BitwiseOperators
  126.     return 2 ^ (p - 1)
  127. end
  128.  
  129. function hasbit(x, p)
  130.     return x % (p + p) >= p
  131. end
  132.  
  133. local function draw_boxes()
  134.     local x_tile, y_tile, mode = globals.x_tile, globals.y_tile, view[globals.view_mode]
  135.     local y = 0
  136.     while y < screenheight do
  137.         local y_next = y + mode.sqsize * tilesize
  138.         if y == 0 then
  139.             y_next = (mode.sqsize - y_tile % mode.sqsize) * tilesize
  140.         end
  141.         if y_next > screenheight then
  142.             y_next = screenheight
  143.         end
  144.         local x = 0
  145.         while x < screenwidth do
  146.             local x_next = x + mode.sqsize * tilesize
  147.             if x == 0 then
  148.                 x_next = (mode.sqsize - x_tile % mode.sqsize) * tilesize
  149.             end
  150.             if x_next > screenwidth then
  151.                 x_next = screenwidth
  152.             end
  153.             if x_tile + x/tilesize >= 0 and y_tile + y/tilesize >= 0 --check the map boundaries
  154.             and x_tile + x/tilesize < mapwidth and y_tile + y/tilesize < mapheight then
  155.                 local value = mode.read(mode.address + math.floor(
  156.                 (math.floor((x_tile + x/tilesize) / mode.sqsize)
  157.                 + math.floor((y_tile + y/tilesize) / mode.sqsize) * mode.y_step) * mode.bytes))
  158.  
  159.                 if globals.show_grid then
  160.                     if mode.read == memory.readwordsigned then
  161.                         if value > 0xFF then value = 0xFF end
  162.                         if value < -0xFF then value = -0xFF end
  163.                         value = math.floor((value + 0xFF) / 2)
  164.                     end
  165.                     if mode.bytes < 1 then
  166.                         value = hasbit(value, bit(8 - (x_tile + x/tilesize + (y_tile + y/tilesize) * mode.y_step) % 8))
  167.                     end
  168.                     gui.box(x, y, x_next-1, y_next-1, fill[value], outline[value])
  169.                 end
  170.  
  171.                 if globals.show_values and value ~= 0 and mode.sqsize > 1 and
  172.                     x_next >= 2 * tilesize and y_next >= 2 * tilesize and
  173.                     x + 2 * tilesize <= screenwidth and y + 2 * tilesize <= screenheight then
  174.                     local color
  175.                     if globals.hex_numbers then
  176.                         value, color = string.format("%02X", value), fill["hex text"]
  177.                     else
  178.                         value, color = string.format("%d", value), fill["dec text"]
  179.                     end
  180.                     gui.text(x_next - value:len() * 4 - 1, y + 1, value, color)
  181.                 end
  182.  
  183.             end
  184.             x = x_next
  185.         end
  186.         y = y_next
  187.     end
  188.  
  189.     if globals.show_grid or globals.show_values then --show the label only with the grid or values active
  190.         gui.text(label_x, label_y, mode.name, fill["label text"])
  191.     end
  192. end
  193.  
  194. local function draw_data()
  195.     local x_tile, y_tile, x_center, y_center = globals.x_tile, globals.y_tile, globals.x_center, globals.y_center
  196.     if globals.grid_ok then
  197.         draw_boxes()
  198.     end
  199.  
  200.     if globals.show_coords then --show the coordinates & city center
  201.         gui.text(coord_x, coord_y, "(" .. x_tile .. ", " .. y_tile .. ")", fill["coord text"])
  202.  
  203.         local xdraw, ydraw = (x_center - x_tile) * tilesize, (y_center - y_tile) * tilesize
  204.         if x_center < x_tile then
  205.             xdraw = 0
  206.         end
  207.         if x_center >= x_tile + screenwidth/tilesize then
  208.             xdraw = screenwidth - tilesize
  209.         end
  210.         if y_center < y_tile then
  211.             ydraw = 0
  212.         end
  213.         if y_center >= y_tile + screenheight/tilesize then
  214.             ydraw = screenheight - tilesize
  215.         end
  216.         gui.box(xdraw, ydraw, xdraw + 7, ydraw + 7, fill["city center"], outline["city center"])
  217.     end
  218. end
  219.  
  220. emu.registerafter(function()
  221.     globals.game_playing = memory.readbyte(address.playing) > 0
  222.     if not globals.game_playing then
  223.         pressing_old = {}
  224.         return
  225.     end
  226.  
  227.     globals.grid_ok = memory.readbyte(address.dark) == 0 and
  228.         (memory.readword(address.hud) == 0x5555 or memory.readbyte(address.magnify) > 0)
  229.     globals.x_tile, globals.y_tile = memory.readbytesigned(address.x_tile), memory.readbytesigned(address.y_tile)
  230.     globals.x_center, globals.y_center = memory.readbyte(address.x_center), memory.readbyte(address.y_center)
  231.  
  232.     local pressing = input.get()
  233.  
  234.     if (globals.show_grid or globals.show_values) and globals.grid_ok then
  235.         if pressing[hotkey.mode_inc[1]] and not pressing_old[hotkey.mode_inc[1]] then
  236.             globals.view_mode = globals.view_mode >= #view and 1 or globals.view_mode + 1
  237.         elseif pressing[hotkey.mode_dec[1]] and not pressing_old[hotkey.mode_dec[1]] then
  238.             globals.view_mode = globals.view_mode == 1 and #view or globals.view_mode - 1
  239.         end
  240.     end
  241.     if pressing[hotkey.show_values[1]] and not pressing_old[hotkey.show_values[1]] and globals.grid_ok then
  242.         globals.show_values = not globals.show_values
  243.     end
  244.     if pressing[hotkey.show_grid[1]] and not pressing_old[hotkey.show_grid[1]] and globals.grid_ok then
  245.         globals.show_grid = not globals.show_grid
  246.     end
  247.     if pressing[hotkey.show_coords[1]] and not pressing_old[hotkey.show_coords[1]] then
  248.         globals.show_coords = not globals.show_coords
  249.     end
  250.     if pressing[hotkey.num_format[1]] and not pressing_old[hotkey.num_format[1]] and globals.show_values then
  251.         globals.hex_numbers = not globals.hex_numbers
  252.     end
  253.  
  254.     pressing_old = pressing
  255. end)
  256.  
  257. gui.register(function()
  258.     gui.clearuncommitted()
  259.  
  260.     if globals.game_playing then
  261.         draw_data()
  262.     end
  263. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement