Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- snes blinking sprites marker
- -- to understand what's going on here you must read
- -- http://patpend.net/technical/snes/snes.txt
- --[[ HOW TO USE:
- - playback a movie file
- - start the script when you got to the start of an interesting section
- - press numpad+ to see sprite data
- --]]
- local count = 0
- oam = {}
- sprite_size_table = { -- note: width==height
- {8,16},{8,32},{8,64},
- {16,32},{16,64},{32,64}
- }
- bit_select = {[0]=1,[1]=2,[2]=4,[3]=8,[4]=16,[5]=32,[6]=64,[7]=128}
- function bit(val,bit)
- return AND(val,bit_select[bit])/bit_select[bit]
- end
- spritedata = {}
- spritegroup = {}
- potentialgroups = {
- --[[
- all colliding sprites go here, if they are drawn directly after one another
- [frame][1].start
- [frame][1].finish
- [frame][2].start
- [frame][2].finish
- --]]
- }
- collisionstatistics = {
- --[[
- [b2][b3].count
- [b2][b3][xoffset1][yoffset1][b2][b3].count,
- [b2][b3][xoffset1][yoffset1][b2][b3][xoffset2][yoffset2][b2][b3].count
- --]]
- }
- function parse_oam(frame)
- -- here are still some programming errors left...
- spritedata[frame] = {}
- --[[
- | 0 Byte 0 xxxxxxxx x: X-location. |
- | Byte 1 yyyyyyyy y: Y-location. |
- | Byte 2 abcdeeeC a: Vertical flip. |
- | b: Horizontal flip. |
- | c: Playfield priority. |
- | d: Playfield priority. |
- | e: Pallete #. |
- | Byte 3 CCCCCCCC C: Character data. |
- | |
- |starting at oam byte 512: |
- |2 bits are defined for each OBJ (eg. byte #0 holds the info for OBJ 0, 1, 2,|
- |and 3; byte #1 holds the info for OBJ 4, 5, 6, and 7). Therefore, 128/4 is |
- |32 bytes of data for the following table: |
- | ab |
- | ||____Size toggle bit. |
- | |_____MSB of X-position bit. |
- | |
- |So, the 4 bytes/sprites + the block are put into the OAM table by consec- |
- |utive writes to the OAM data register. You first should set the OAM address |
- |to $0000, then shove your data into it. |
- --]]
- for i=0,31 do for j=0,3 do
- spritedata[frame][4*i+j] = {}
- spritedata[frame][4*i+j].x = oam[frame][4*(4*i+j)] + 256 * bit(oam[frame][512+i],2*j)
- temp = oam[frame][4*(4*i+j)+1]
- if temp < 224 then
- spritedata[frame][4*i+j].y = temp
- else
- spritedata[frame][4*i+j].y = temp - 256
- end
- spritedata[frame][4*i+j].width = sprite_size[bit(oam[frame][512+i],2*j+1) + 1]
- if real_x == 256 + 128 then --don't draw this one, it doesn't exist
- spritedata[frame][4*i+j].enabled = false
- else
- spritedata[frame][4*i+j].enabled = true
- end
- spritedata[frame][4*i+j].verticalflip = (bit(oam[frame][4*(4*i+j)+2], 0) == 1)
- spritedata[frame][4*i+j].horizontalflip = (bit(oam[frame][4*(4*i+j)+2], 1) == 1)
- spritedata[frame][4*i+j].playfieldpriority = 2*bit(oam[frame][4*(4*i+j)+2], 2) + bit(oam[frame][4*(4*i+j)+2], 3)
- spritedata[frame][4*i+j].pallete = 4*bit(oam[frame][4*(4*i+j)+2], 4) + 2*bit(oam[frame][4*(4*i+j)+2], 5) + bit(oam[frame][4*(4*i+j)+2], 6)
- spritedata[frame][4*i+j].characterdata = 256 * bit(oam[frame][4*(4*i+j)+2], 7) + oam[frame][4*(4*i+j)+3]
- end end
- end
- function read_oam()
- b = memory.readword(0x2101)
- name_base = AND(b, 1+2+4) * 4096
- name_bits = AND(b, 8+16)
- sprite_size_bits = AND(b, 32+64+128) / 32
- --sprite_size = {8,16} --should be sprite_size_table[sprite_size_bits + 1]
- sprite_size = {16,32}
- oam[cf] = {}
- memory.writeword(0x2102,0)
- for i = 0,512+32-1 do
- --memory.writeword(0x2102,i)
- w = memory.readbyte(0x2138)
- oam[cf][i] = w
- --oam[2*i+1] = w % 256
- end
- end
- --vram_sprite_offset
- start = savestate.create()
- savestate.save(start)
- function detectspritegroups(frame)
- spritegroup[frame] = {}
- groupcount = 0
- i = 0
- while i < 127 do
- groupcount = groupcount + 1
- spritegroup[frame][groupcount] = {
- min_x = spritedata[frame][i].x,
- max_x = spritedata[frame][i].x,
- min_y = spritedata[frame][i].y,
- max_y = spritedata[frame][i].y,
- numberofsprites = 1,
- first = i
- }
- j = i + 1
- while not spritedata[frame][j].enabled and j < 127 do
- j = j + 1
- end
- while (
- -- spritedata[frame][i].characterdata == spritedata[frame][j].characterdata and
- math.mod(spritedata[frame][i].x - spritedata[frame][j].x, spritedata[frame][i].width) == 0 and
- math.mod(spritedata[frame][i].y - spritedata[frame][j].y, spritedata[frame][i].width) == 0 ) and
- ( spritedata[frame][i].x == spritedata[frame][j].x or spritedata[frame][i].y == spritedata[frame][j].y)
- do
- spritegroup[frame][groupcount].min_x = math.min(spritegroup[frame][groupcount].min_x, spritedata[frame][j].x)
- spritegroup[frame][groupcount].max_x = math.max(spritegroup[frame][groupcount].max_x, spritedata[frame][j].x)
- spritegroup[frame][groupcount].min_y = math.min(spritegroup[frame][groupcount].min_y, spritedata[frame][j].y)
- spritegroup[frame][groupcount].max_y = math.max(spritegroup[frame][groupcount].max_y, spritedata[frame][j].y)
- spritegroup[frame][groupcount].numberofsprites = spritegroup[frame][groupcount].numberofsprites + 1
- j = j + 1
- if j == 128 then break end
- end
- i = j
- end
- end
- function findblinkingspritegroups(frame, distx, disty)
- if spritegroup[frame] == nil or spritegroup[frame+1] == nil or
- spritegroup[frame+2] == nil or spritegroup[frame-1] == nil or
- spritegroup[frame-2] == nil then
- return
- end
- for i,group in pairs(spritegroup[frame]) do
- local help = function(offset, name)
- for j,group2 in pairs(spritegroup[frame+offset]) do
- if math.abs(group.min_x - group2.min_x) <= distx and
- math.abs(group.min_y - group2.min_y) <= disty and
- group.max_x - group.min_x == group2.max_x - group2.min_x and
- group.max_y - group.min_y == group2.max_y - group2.min_y and (
- group.characterdata == group2.characterdata or (
- group.numberofsprites == group2.numberofsprites and
- group.numberofsprites > 1))
- then
- spritegroup[frame][i][name] = j
- end
- end
- end
- help(1,"normalmovement")
- help(2,"twostepmovement")
- help(-1,"normalbackwardmovement")
- help(-2,"twostepbackwardmovement")
- group.blinking = (not group.normalmovement and group.twostepmovement)
- or (not group.normalbackwardmovement and group.twostepbackwardmovement)
- or (not group.normalmovement and not group.normalbackwardmovement)
- end
- end
- while(true) do
- snes9x.frameadvance()
- cf = emu.framecount()
- spritedata[cf] = {}
- read_oam()
- parse_oam(cf)
- detectspritegroups(cf)
- keys = input.get()
- if keys["numpad+"] then break end
- end
- function drawspritegroups(frame, color)
- for i,group in pairs(spritegroup[frame]) do
- gui.box(math.max(0,group.min_x), math.max(0,group.min_y), group.max_x + 16, group.max_y + 16, "transparent", color)
- end
- for i,group in pairs(spritegroup[frame]) do
- gui.text(group.min_x, group.min_y, string.format("%i / %i / %i / %i", group.first, group.numberofsprites, group.min_x, group.min_y))
- if group.blinking then
- gui.text(group.min_x, group.min_y+8, "BLINKING")
- end
- if group.offset_x then
- gui.text(group.max_x, group.max_y, tostring(group.offset_x) .. "|" .. tostring(group.offset_y))
- end
- end
- end
- savestate.load(start)
- emu.registerbefore(function()
- cf = emu.framecount()
- if spritegroup[cf - 1] == nil or spritegroup[cf] == nil or spritegroup[cf + 1] == nil then return end
- deletecount=0
- for i,group in pairs(spritegroup[cf]) do
- if group.blinking then
- deletegroup(cf,group)
- deletecount = deletecount+1
- end
- end
- gui.text(0,0,tostring(deletecount))
- --if deletecount > 0 then emu.pause() end
- writeoam(cf)
- end)
- function writeoam(frame)
- memory.writebyte(0x2102,0)
- for i=0,512+32-1 do
- memory.writebyte(0x2104,oam[frame][i])
- end
- end
- function deletegroup(frame,group)
- for i=group.first,group.first+group.numberofsprites-1 do
- --send sprite to x = 384
- oam[frame][4*i] = 255
- oam[frame][4*i+1] = 224
- --[[
- local manipulate = 512 + math.floor(i/4)
- local bitnum = 2 * math.mod(i,4)
- local b = bit(oam[frame][manipulate], bitnum)
- if b == 1 then oam[frame][manipulate] = oam[frame][manipulate] - bit_select[bitnum] end
- --]]
- end
- end
- while(true) do
- cf = emu.framecount()
- findblinkingspritegroups(cf, 10, 10)
- m = math.mod(cf, 4)
- colors = {[0]="red", [1]="green", [2]="red",[3]="green"}
- --if spritedata[cf] ~= nil then drawspritegroups(cf, colors[m]) end
- --if spritedata[cf-1] ~= nil then drawspritegroups(cf-1, colors[m+1]) end
- snes9x.frameadvance()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement