Initial commit

This commit is contained in:
Empathic Qubit 2021-02-25 18:24:37 -05:00
commit c63f6a9325
8 changed files with 1989 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*.lsmv
*.log
catchem/

2
README.md Normal file
View file

@ -0,0 +1,2 @@
# Neat[Tinkering]
MarI/O for DKC2/lsnes. Not usable yet.

69
config.lua Normal file
View file

@ -0,0 +1,69 @@
local _M = {}
--[[
Change BizhawkDir to your BizHawk directory.
--]]
--_M.BizhawkDir = "C:/Users/mmill/Downloads/BizHawk-2.2/"
_M.BizhawkDir = "X:/B2_BizHawkLab/BizHawk-2.2.2/"
_M.StateDir = _M.BizhawkDir .. "Lua/SNES/neat-mario/state/"
_M.PoolDir = _M.BizhawkDir .. "Lua/SNES/neat-mario/pool/"
--[[
At the moment the first in list will get loaded.
Rearrange for other savestates. (will be redone soon)
--]]
_M.State = {
"DP1.state", -- Donut Plains 1
"YI1.state", -- Yoshi's Island 1
"YI2.state", -- Yoshi's Island 2
}
--[[
Start game with specific powerup.
0 = No powerup
1 = Mushroom
2 = Feather
3 = Flower
Comment out to disable.
--]]
_M.StartPowerup = 0
_M.NeatConfig = {
--Filename = "DP1.state",
Filename = _M.PoolDir .. _M.State[1],
Population = 300,
DeltaDisjoint = 2.0,
DeltaWeights = 0.4,
DeltaThreshold = 1.0,
StaleSpecies = 15,
MutateConnectionsChance = 0.25,
PerturbChance = 0.90,
CrossoverChance = 0.75,
LinkMutationChance = 2.0,
NodeMutationChance = 0.50,
BiasMutationChance = 0.40,
StepSize = 0.1,
DisableMutationChance = 0.4,
EnableMutationChance = 0.2,
TimeoutConstant = 20,
MaxNodes = 1000000,
}
_M.ButtonNames = {
"A",
"B",
"X",
"Y",
"Up",
"Down",
"Left",
"Right",
}
_M.BoxRadius = 6
_M.InputSize = (_M.BoxRadius*2+1)*(_M.BoxRadius*2+1)
_M.Running = false
return _M

283
donkutil.lua Normal file
View file

@ -0,0 +1,283 @@
count = 0
detailsidx = -1
helddown = false
floatmode = false
pokemon = false
pokecount = 0
showhelp = false
locked = false
lockdata = nil
incsprite = 0
fgcolor = 0x00ffffff
bgcolor = 0x99000000
function table_to_string(tbl)
local result = "{"
local keys = {}
for k in pairs(tbl) do
table.insert(keys, k)
end
table.sort(keys)
for _, k in ipairs(keys) do
local v = tbl[k]
if type(v) == "number" and v == 0 then
goto continue
end
-- Check the key type (ignore any numerical keys - assume its an array)
if type(k) == "string" then
result = result.."[\""..k.."\"]".."="
end
-- Check the value type
if type(v) == "table" then
result = result..table_to_string(v)
elseif type(v) == "boolean" then
result = result..tostring(v)
else
result = result.."\""..v.."\""
end
result = result..",\n"
::continue::
end
-- Remove leading commas from the result
if result ~= "" then
result = result:sub(1, result:len()-1)
end
return result.."}"
end
function on_keyhook (key, state)
if not helddown and state["value"] == 1 then
if key == "1" and not locked then
helddown = true
detailsidx = detailsidx - 1
if detailsidx < -1 then
detailsidx = 20
end
elseif key == "2" and not locked then
helddown = true
detailsidx = detailsidx + 1
if detailsidx > 20 then
detailsidx = -1
end
elseif key == "3" then
helddown = true
incsprite = -1
elseif key == "4" then
helddown = true
incsprite = 1
elseif key == "5" then
helddown = true
if not locked then
locked = true
else
locked = false
lockdata = nil
end
elseif key == "6" then
helddown = true
pokemon = not pokemon
elseif key == "7" then
helddown = true
floatmode = not floatmode
elseif key == "0" then
showhelp = true
end
elseif state["value"] == 0 then
helddown = false
showhelp = false
end
end
function on_input (subframe)
if floatmode then
memory.writebyte(0x7e19ce, 0x16)
memory.writebyte(0x7e0e12, 0x99)
memory.writebyte(0x7e0e70, 0x99)
if input.get(0, 6) == 1 then
memory.writeword(0x7e0e02, -0x5ff)
memory.writeword(0x7e0e60, -0x5ff)
memory.writeword(0x7e0e06, 0)
memory.writeword(0x7e0e64, 0)
elseif input.get(0, 7) == 1 then
memory.writeword(0x7e0e02, 0x5ff)
memory.writeword(0x7e0e60, 0x5ff)
memory.writeword(0x7e0e06, 0)
memory.writeword(0x7e0e64, 0)
end
if input.get(0, 4) == 1 then
memory.writeword(0x7e0e06, -0x05ff)
memory.writeword(0x7e0e64, -0x05ff)
elseif input.get(0, 5) == 1 then
memory.writeword(0x7e0e06, 0x5ff)
memory.writeword(0x7e0e64, 0x5ff)
end
end
end
function file_exists(name)
local f=io.open(name,"r")
if f~=nil then io.close(f) return true else return false end
end
function get_sprite(base_addr)
return {
["control"] = memory.readword(base_addr),
["draworder"] = memory.readword(base_addr + 0x02),
["x"] = memory.readword(base_addr + 0x06),
["y"] = memory.readword(base_addr + 0x0a),
["jumpheight"] = memory.readword(base_addr + 0x0e),
["style"] = memory.readword(base_addr + 0x12),
["currentframe"] = memory.readword(base_addr + 0x18),
["nextframe"] = memory.readword(base_addr + 0x1a),
["state"] = memory.readword(base_addr + 0x1e),
["velox"] = memory.readsword(base_addr + 0x20),
["veloy"] = memory.readsword(base_addr + 0x24),
["velomaxx"] = memory.readsword(base_addr + 0x26),
["velomaxy"] = memory.readsword(base_addr + 0x2a),
["motion"] = memory.readword(base_addr + 0x2e),
["attr"] = memory.readword(base_addr + 0x30),
["animnum"] = memory.readword(base_addr + 0x36),
["remainingframe"] = memory.readword(base_addr + 0x38),
["animcontrol"] = memory.readword(base_addr + 0x3a),
["animreadpos"] = memory.readword(base_addr + 0x3c),
["animcontrol2"] = memory.readword(base_addr + 0x3e),
["animformat"] = memory.readword(base_addr + 0x40),
["damage1"] = memory.readword(base_addr + 0x44),
["damage2"] = memory.readword(base_addr + 0x46),
["damage3"] = memory.readword(base_addr + 0x48),
["damage4"] = memory.readword(base_addr + 0x4a),
["damage5"] = memory.readword(base_addr + 0x4c),
["damage6"] = memory.readword(base_addr + 0x4e),
["spriteparam"] = memory.readword(base_addr + 0x58),
}
end
function sprite_details(idx)
local base_addr = idx * 94 + 0x7e0e9e
local sprite = get_sprite(base_addr)
if sprite["control"] == 0 then
gui.text(0, 0, "Sprite "..idx.." (Empty)", fgcolor, bgcolor)
incsprite = 0
locked = false
lockdata = nil
return
end
if incsprite ~= 0 then
memory.writeword(base_addr + 0x36, sprite["animnum"] + incsprite)
lockdata = nil
incsprite = 0
end
if locked and lockdata == nil then
lockdata = memory.readregion(base_addr, 94)
end
if lockdata ~= nil and locked then
memory.writeregion(base_addr, 94, lockdata)
end
gui.text(0, 0, "Sprite "..idx..(locked and " (Locked)" or "")..":\n\n"..table_to_string(sprite), fgcolor, bgcolor)
end
function on_paint (not_synth)
count = count + 1
local guiWidth, guiHeight = gui.resolution()
if showhelp then
gui.text(0, 0, [[
Keyboard Help
===============
Sprite Details:
[1] Next sprite slot
[2] Previous sprite slot
[3] Change to next sprite animation
[4] Change to previous sprite animation
[5] Lock current sprite
[6] Enable / Disable Pokemon mode (take screenshots of enemies)
[7] Enable / Disable float mode (fly with up/down)
]], fgcolor, bgcolor)
return
end
gui.text(guiWidth - 75, 0, "Help [0]", fgcolor, bgcolor)
local stats = ""
if pokemon then
stats = stats.."Pokemon: "..pokecount.."\n"
end
if floatmode then
stats = stats.."Float on\n"
end
gui.text(0, guiHeight - 40, stats, fgcolor, bgcolor)
stats = stats.."\nPokemon: "..pokecount
local cameraX = memory.readword(0x7e17ba) - 256
local cameraY = memory.readword(0x7e17c0) - 256
local partyScreenX = (memory.readword(0x7e0a2a) - 256 - cameraX) * 2
local partyScreenY = (memory.readword(0x7e0a2c) - 256 - cameraY) * 2
if detailsidx ~= -1 then
sprite_details(detailsidx)
else
gui.text(0, 0, "[1] <- Sprite Details Off -> [2]", fgcolor, bgcolor)
end
gui.text(guiWidth - 200, guiHeight - 20, "Camera: "..tostring(cameraX)..","..tostring(cameraY), fgcolor, bgcolor)
gui.text(partyScreenX, partyScreenY, "Party", fgcolor, bgcolor)
local sprites = {}
for idx = 0,20,1 do
local base_addr = idx * 94 + 0x7e0e9e
local sprite = get_sprite(base_addr)
sprites[idx] = sprite
if sprite["control"] == 0 then
goto continue
end
local spriteScreenX = (sprite["x"] - 256 - cameraX) * 2
local spriteScreenY = (sprite["y"] - 256 - cameraY) * 2
local sprcolor = bgcolor
if detailsidx == idx then
sprcolor = 0x00ff0000
end
gui.text(spriteScreenX, spriteScreenY, sprite["animnum"]..","..sprite["attr"], fgcolor, sprcolor)
local filename = os.getenv("HOME").."/neat-donk/catchem/"..sprite["animnum"]..","..sprite["attr"]..".png"
if pokemon and spriteScreenX > (guiWidth / 4) and spriteScreenX < (guiWidth / 4) * 3 and spriteScreenY > (guiHeight / 3) and spriteScreenY < guiHeight and not file_exists(filename) then
gui.screenshot(filename)
pokecount = pokecount + 1
end
::continue::
end
end
input.keyhook("1", true)
input.keyhook("2", true)
input.keyhook("3", true)
input.keyhook("4", true)
input.keyhook("5", true)
input.keyhook("6", true)
input.keyhook("7", true)
input.keyhook("0", true)

164
game.lua Normal file
View file

@ -0,0 +1,164 @@
--Notes here
config = require "config"
spritelist = require "spritelist"
local _M = {}
function _M.getPositions()
partyX = memory.readword(0x7e0a2a) - 256
partyY = memory.readword(0x7e0a2c) - 256
local cameraX = memory.readword(0x7e17ba) - 256
local cameraY = memory.readword(0x7e17c0) - 256
_M.screenX = partyX-layer1x
_M.screenY = partyY-layer1y
end
function _M.getBananas()
local bananas = memory.readword(0x7e08bc)
return bananas
end
function _M.getCoins()
local coins = memory.readword(0x7e08ca)
return coins
end
function _M.getLives()
local lives = memory.readsbyte(0x7e08be) + 1
return lives
end
function _M.writeLives(lives)
memory.writebyte(0x7e08be, lives - 1)
memory.writebyte(0x7e08c0, lives - 1)
end
function _M.getPowerup()
return 0
end
function _M.writePowerup(powerup)
return
-- memory.writebyte(0x0019, powerup)
end
function _M.getHit(alreadyHit)
return not alreadyHit and memory.readbyte(0x7e08be) < memory.readbyte(0x7e08c0)
end
function _M.getHitTimer()
return memory.readbyte(0x7e08c0) - memory.readbyte(0x7e08be)
end
function _M.getTile(dx, dy)
local partyScreenX = (partyX - cameraX) * 2
local partyScreenY = (partyY - cameraY) * 2
x = math.floor((partyX+dx+8)/16)
y = math.floor((partyY+dy)/16)
return memory.readbyte(0x1C800 + math.floor(x/0x10)*0x1B0 + y*0x10 + x%0x10)
end
function _M.getSprites()
local sprites = {}
for slot=0,11 do
local status = memory.readbyte(0x14C8+slot)
if status ~= 0 then
spritex = memory.readbyte(0xE4+slot) + memory.readbyte(0x14E0+slot)*256
spritey = memory.readbyte(0xD8+slot) + memory.readbyte(0x14D4+slot)*256
sprites[#sprites+1] = {["x"]=spritex, ["y"]=spritey, ["good"] = spritelist.Sprites[memory.readbyte(0x009e + slot) + 1]}
end
end
return sprites
end
function _M.getExtendedSprites()
local extended = {}
for slot=0,11 do
local number = memory.readbyte(0x170B+slot)
if number ~= 0 then
spritex = memory.readbyte(0x171F+slot) + memory.readbyte(0x1733+slot)*256
spritey = memory.readbyte(0x1715+slot) + memory.readbyte(0x1729+slot)*256
extended[#extended+1] = {["x"]=spritex, ["y"]=spritey, ["good"] = spritelist.extSprites[memory.readbyte(0x170B + slot) + 1]}
end
end
return extended
end
function _M.getInputs()
_M.getPositions()
sprites = _M.getSprites()
extended = _M.getExtendedSprites()
local inputs = {}
local inputDeltaDistance = {}
local layer1x = memory.read_s16_le(0x1A);
local layer1y = memory.read_s16_le(0x1C);
for dy=-config.BoxRadius*16,config.BoxRadius*16,16 do
for dx=-config.BoxRadius*16,config.BoxRadius*16,16 do
inputs[#inputs+1] = 0
inputDeltaDistance[#inputDeltaDistance+1] = 1
tile = _M.getTile(dx, dy)
if tile == 1 and partyY+dy < 0x1B0 then
inputs[#inputs] = 1
end
for i = 1,#sprites do
distx = math.abs(sprites[i]["x"] - (partyX+dx))
disty = math.abs(sprites[i]["y"] - (partyY+dy))
if distx <= 8 and disty <= 8 then
inputs[#inputs] = sprites[i]["good"]
local dist = math.sqrt((distx * distx) + (disty * disty))
if dist > 8 then
inputDeltaDistance[#inputDeltaDistance] = mathFunctions.squashDistance(dist)
--gui.drawLine(screenX, screenY, sprites[i]["x"] - layer1x, sprites[i]["y"] - layer1y, 0x50000000)
end
end
end
for i = 1,#extended do
distx = math.abs(extended[i]["x"] - (partyX+dx))
disty = math.abs(extended[i]["y"] - (partyY+dy))
if distx < 8 and disty < 8 then
--console.writeline(screenX .. "," .. screenY .. " to " .. extended[i]["x"]-layer1x .. "," .. extended[i]["y"]-layer1y)
inputs[#inputs] = extended[i]["good"]
local dist = math.sqrt((distx * distx) + (disty * disty))
if dist > 8 then
inputDeltaDistance[#inputDeltaDistance] = mathFunctions.squashDistance(dist)
--gui.drawLine(screenX, screenY, extended[i]["x"] - layer1x, extended[i]["y"] - layer1y, 0x50000000)
end
--if dist > 100 then
--dw = mathFunctions.squashDistance(dist)
--console.writeline(dist .. " to " .. dw)
--gui.drawLine(screenX, screenY, extended[i]["x"] - layer1x, extended[i]["y"] - layer1y, 0x50000000)
--end
--inputs[#inputs] = {["value"]=-1, ["dw"]=dw}
end
end
end
end
return inputs, inputDeltaDistance
end
function _M.clearJoypad()
controller = {}
for b = 1,#config.ButtonNames do
controller["P1 " .. config.ButtonNames[b]] = false
end
joypad.set(controller)
end
return _M

29
mathFunctions.lua Normal file
View file

@ -0,0 +1,29 @@
--Notes here
local _M = {}
function _M.sigmoid(x)
return 2/(1+math.exp(-4.9*x))-1
end
function _M.squashDistance(x)
local window = 0.20
local delta = 0.25
local dist = (x-8)
local newDist = 1
while dist > 0 do
newDist = newDist - (window*delta)
dist = dist - 1
end
if newDist < 0.80 then
newDist = 0.80
end
return newDist
end
return _M

1163
neat-donk.lua Normal file

File diff suppressed because it is too large Load diff

276
spritelist.lua Normal file
View file

@ -0,0 +1,276 @@
-- Idea from: https://github.com/kevino5233/MarIO_Enhanced/
-- Spritelist from: https://www.smwcentral.net/?p=viewthread&t=7562
-- Extended spritelist: https://web.archive.org/web/20170709102356/www.smwiki.net/wiki/RAM_Address/$7E:170B
--
local _M = {}
_M.Sprites = {}
-- Make sure this list is sorted before initialization.
_M.NeutralSprites = {
0x0E, -- Keyhole.
0x2C, -- Yoshi egg Red/Blue/Yellow/Blue (X&3).
0x2D, -- Baby green Yoshi.
0x2F, -- Portable spring board.
0x35, -- Green Yoshi.
0x3E, -- POW, blue/silver (X&1).
0x41, -- Dolphin, horizontal.
0x42, -- Dolphin2, horizontal.
0x43, -- Dolphin, vertical.
0x49, -- Growing/shrinking pipe end.
0x4A, -- Goal Point Question Sphere.
0x52, -- Moving ledge hole in ghost house.
0x53, -- ???
0x54, -- Climbing net door, use with object 0x4A-E.
0x55, -- Checkerboard platform, horizontal.
0x56, -- Flying rock platform, horizontal.
0x57, -- Checkerboard platform, vertical.
0x58, -- Flying rock platform, vertical.
0x59, -- Turn block bridge, horizontal and vertical.
0x5A, -- Turn block bridge, horizontal.
0x5B, -- Brown platform floating in water.
0x5C, -- Checkerboard platform that falls.
0x5D, -- Orange platform floating in water.
0x5E, -- Orange platform, goes on forever.
0x5F, -- Brown platform on a chain.
0x60, -- Flat green switch palace switch.
0x61, -- Floating skulls.
0x62, -- Brown platform, line-guided.
0x63, -- Checker/brown platform, line-guided (X&1).
0x64, -- Rope mechanism, line-guided (X&1).
0x6A, -- Coin game cloud.
0x6B, -- Spring board, left wall.
0x6C, -- Spring board, right wall.
0x6D, -- Invisible solid block.
0x79, -- Growing Vine.
0x7C, -- ???
0x80, -- Key.
0x81, -- Changing item from a translucent block.
0x87, -- Lakitu's cloud, no time limit. (!)
0x8A, -- Bird from Yoshi's house, max of 4.
0x8B, -- Puff of smoke from Yoshi's house.
0xA3, -- Grey platform on chain, clockwise/counter (X&1).
0xBA, -- Timed lift, 4 sec/1 sec (X&1).
0xC0, -- Grey platform on lava, sinks.
0xC4, -- Grey platform that falls.
0xC8, -- Light switch block for dark room.
0xC9, -- ???
0xDA, -- Green Koopa shell.
0xDB, -- Red Koopa shell.
0xDC, -- Blue Koopa shell.
0xDD, -- Yellow Koopa shell.
0xDF, -- Green shell, won't use Special World color.
0xE0 -- 3 platforms on chains, clockwise/counter (X&1).
}
-- Make sure this list is sorted before initialization.
_M.GoodSprites = {
0x21, -- Moving coin.
0x45, -- Directional coins, no time limit.
0x74, -- Mushroom.
0x75, -- Flower.
0x76, -- Star.
0x77, -- Feather.
0x78, -- 1-UP.
0x7B, -- Standard Goal Point.
-- "Secret" Goal Point.
0x83, -- Left flying question block, coin/flower/feather/1-UP (X&3).
0x84, -- Flying question block, coin/flower/feather/1-UP (X&3).
0xC1, -- Flying grey turnblocks, first up/down (X&1).
0xC7 -- Invisible mushroom.
}
-- Currently not used.
_M.BadSprites = {
0x00, -- Green Koopa, no shell.
0x01, -- Red Koopa, no shell.
0x02, -- Blue Koopa, no shell.
0x03, -- Yellow Koopa, no shell.
0x04, -- Green Koopa.
0x05, -- Red Koopa.
0x06, -- Blue Koopa.
0x07, -- Yellow Koopa.
0x08, -- Green Koopa, flying left.
0x09, -- Green bouncing Koopa (Y&1).
0x0A, -- Red vertical flying Koopa.
0x0B, -- Red horizontal flying Koopa.
0x0C, -- Yellow Koopa with wings.
0x0F, -- Goomba.
0x10, -- Bouncing Goomba with wings.
0x1A, -- Classic Pirhana Plant (use ExGFX).
0x1C, -- Bullet Bill.
0x4F, -- Jumping Pirhana Plant.
0x50, -- Jumping Pirhana Plant, spit fire.
0x7E, -- Flying Red coin, worth 5 coins.
0x7F, -- Flying Yellow 1-UP.
0xB1, -- Creating/Eating block (X&1).
0xB9, -- Info Box, message 1/2 (X&1).
0xBD, -- Sliding Koopa without a shell.
0x0D, -- Bob-omb.
0x11, -- Buzzy Beetle.
0x13, -- Spiny.
0x14, -- Spiny falling.
0x15, -- Fish, horizontal.
0x16, -- Fish, vertical.
0x18, -- Surface jumping fish.
0x1B, -- Bouncing football in place.
0x1D, -- Hopping flame.
0x1E, -- Lakitu Normal/Fish (X&1).
0x1F, -- Magikoopa.
0x20, -- Magikoopa's magic, stationary.
0x22, -- Green vertical net Koopa, below/above (X&1).
0x23, -- Red fast vertical net Koopa, below/above (X&1).
0x24, -- Green horizontal net Koopa, below/above (X&1).
0x25, -- Red fast horizontal net Koopa, below/above (X&1).
0x26, -- Thwomp.
0x27, -- Thwimp.
0x28, -- Big Boo.
0x29, -- Koopa Kid (place at X=12, Y=0 to 6).
0x2A, -- Upside down Piranha Plant.
0x2B, -- Sumo Brother's fire lightning.
0x2E, -- Spike Top.
0x30, -- Dry Bones, throws bones.
0x31, -- Bony Beetle.
0x32, -- Dry Bones, stay on ledge.
0x33, -- Fireball, vertical. Requires buoyancy!
0x34, -- Boss fireball, stationary.
0x37, -- Boo.
0x38, -- Eerie.
0x39, -- Eerie, wave motion.
0x3A, -- Urchin, fixed vertical/horizontal (X&1).
0x3B, -- Urchin, wall detect v/h (X&1).
0x3C, -- Urchin, wall follow clockwise/counter (X&1).
0x3D, -- Rip Van Fish.
0x3F, -- Para-Goomba.
0x40, -- Para-Bomb.
0x44, -- Torpedo Ted.
0x47, -- Swimming/Jumping fish, doesn't need water. (!)
0x48, -- Diggin' Chuck's rock.
0x46, -- Diggin' Chuck.
0x4B, -- Pipe dwelling Lakitu.
0x4C, -- Exploding Block, fish/goomba/Koopa/Koopa with shell (X&3).
0x4D, -- Ground dwelling Monty Mole, follow/hop (X&1).
0x4E, -- Ledge dwelling Monty Mole, follow/hop (X&1).
0x51, -- Ninji.
0x65, -- Chainsaw, line-guided, right/left (X&1).
0x66, -- Upside down chainsaw, line-guided, null/left (X&1).
0x67, -- Grinder, line-guided, right/left (X&1).
0x68, -- Fuzz Ball, line-guided, right/left (X&1).
0x6E, -- Dino Rhino.
0x6F, -- Dino Torch.
0x70, -- Pokey.
0x71, -- Super Koopa, red cape, swoop.
0x72, -- Super Koopa, yellow cape, swoop.
0x73, -- Super Koopa, feather/yellow cape (X&1).
0x7A, -- Firework, makes Mario temporarily invisible.
0x86, -- Wiggler.
0x8D, -- Ghost house exit sign and door.
0x8E, -- Invisible "Warp Hole" blocks. (!)
0x8F, -- Scale platforms, long/short between (X&1).
0x90, -- Large green gas bubble.
0x91, -- Chargin' Chuck.
0x92, -- Splitin' Chuck.
0x93, -- Bouncin' Chuck.
0x94, -- Whistlin' Chuck, fish/Koopa (X&1).
0x95, -- Clapin' Chuck.
0x97, -- Puntin' Chuck.
0x98, -- Pitchin' Chuck.
0x99, -- Volcano Lotus.
0x9A, -- Sumo Brother.
0x9B, -- Hammer Brother (requires sprite 9C).
0x9C, -- Flying blocks for Hammer Brother.
0x9D, -- Bubble with Goomba/bomb/fish/mushroom (X&3).
0x9E, -- Ball and Chain, clockwise/counter (X&1).
0x9F, -- Banzai Bill.
0xA2, -- MechaKoopa.
0xA4, -- Floating Spike ball, slow/fast (X&1).
0xA5, -- Fuzzball/Sparky, ground-guided, left/right (X&1).
0xA6, -- HotHead, ground-guided, left/right (X&1).
0xA8, -- Blargg.
0xAA, -- Fishbone.
0xAB, -- Rex.
0xAC, -- Wooden Spike, moving down and up.
0xAD, -- Wooden Spike, moving up/down first (X&1).
0xAE, -- Fishin' Boo.
0xAF, -- Boo Block.
0xB0, -- Reflecting stream of Boo Buddies.
0xB2, -- Falling Spike.
0xB3, -- Bowser statue fireball.
0xB4, -- Grinder, non-line-guided.
0xB6, -- Reflecting fireball.
0xB7, -- Carrot Top lift, upper right.
0xB8, -- Carrot Top lift, upper left.
0xBB, -- Grey moving castle block, horizontal.
0xBC, -- Bowser statue, normal/fire/leap (X&3).
0xBE, -- Swooper Bat, hang/fly/fly/fly (X&3).
0xBF, -- Mega Mole.
0xC2, -- Blurp fish.
0xC3, -- A Porcu-Puffer fish.
0xC5, -- Big Boo Boss.
0xC6, -- Dark room with spot light.
0xDE, -- Group of 5 eeries, wave motion.
0xE2, -- Boo Buddies, counter-clockwise.
0xE3 -- Boo Buddies, clockwise.
}
function _M.InitSpriteList()
local k = 1
local j = 1
for i=1, 256 do
local isGood = (k <= #_M.GoodSprites) and (_M.GoodSprites[k] == i - 1)
local isNeutral = (j <= #_M.NeutralSprites) and (_M.NeutralSprites[j] == i - 1)
if isGood then
k = k + 1
_M.Sprites[#_M.Sprites + 1] = 1
elseif isNeutral then
j = j + 1
_M.Sprites[#_M.Sprites + 1] = 0
else
_M.Sprites[#_M.Sprites + 1] = -1
end
end
end
_M.extSprites = {}
-- Make sure this list is sorted before initialization.
_M.ExtNeutralSprites = {
0x01, -- Puff of smoke with various objects.
0x03, -- Flame left by hopping flame.
0x05, -- Player fireball.
0x0A, -- Coin from coin cloud game.
0x0F, -- Trail of smoke (yellow Yoshi stomping the ground).
0x10, -- Spinjump stars.
0x11, -- Yoshi fireballs.
0x12 -- Water bubble.
}
-- Currently not used.
_M.ExtBadSprites = {
0x02, -- Reznor fireball.
0x04, -- Hammer.
0x06, -- Bone from Dry Bones.
0x07, -- Lava splash.
0x08, -- Torpedo Ted shooter's arm.
0x09, -- Unknown flickering object
0x0B, -- Piranha Plant fireball.
0x0C, -- Lava Lotus's fiery objects.
0x0D, -- Baseball.
0x0E -- Wiggler's flower.
}
function _M.InitExtSpriteList()
local j = 1
for i=1, 21 do
local isExtNeutral = (j <= #_M.ExtNeutralSprites) and (_M.ExtNeutralSprites[j] == i - 1)
if isExtNeutral then
j = j + 1
_M.extSprites[#_M.extSprites + 1] = 0
else
_M.extSprites[#_M.extSprites + 1] = -1
end
end
end
return _M