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 = {}
- 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 then return end
- for i,group in pairs(spritegroup[frame]) do
- for j,group2 in pairs(spritegroup[frame+1]) 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
- then
- spritegroup[frame][i].normalmovement = j
- end
- end
- for j,group2 in pairs(spritegroup[frame+2]) do
- if math.abs(group.min_x - group2.min_x) <= 2*distx and
- math.abs(group.min_y - group2.min_y) <= 2*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
- then
- spritegroup[frame][i].twostepmovement = j
- end
- end
- group.blinking = not group.normalmovement and group.twostepmovement
- 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
- if group.blinking or not group.normalmovement then
- gui.box(math.max(0,group.min_x), math.max(0,group.min_y), group.max_x + 16, group.max_y + 16, color)
- --gui.text(group.min_x, group.min_y, "BLINKING SPRITE")
- 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()
- if spritegroup[cf - 1] == nil or spritegroup[cf] == nil or spritegroup[cf + 1] == nil then return end
- cf = emu.framecount()
- m = cf - 4 * math.floor(cf/4)
- -- change sprite blinking status on two consecutive frames
- if m == 0 then
- -- don't change anything
- elseif m == 1 then
- -- copy all sprites that blink on the previous frame and the next frame
- for i,group in pairs(spritegroup[cf - 1]) do
- if group.blinking then
- -- do a linear movement interpolation
- gn = group.twostepmovement
- group2 = spritegroup[cf + 1][gn]
- group.offset_x = (group2.min_x - group.min_x) / 2
- group.offset_y = (group2.min_y - group.min_y) / 2
- end
- end
- elseif m == 2 then
- -- kill all sprites that blink on the current frame
- for i,group in pairs(spritegroup[cf]) do
- if group.blinking then
- group.enabled = false
- end
- end
- -- copy all movement mismatched sprites from previous and next frame semi-transparent
- for i,group in pairs(spritegroup[cf - 1]) do
- if not group.normalmovement then
- -- here we should insert some "copy code"
- end
- end
- for i,group in pairs(spritegroup[cf + 1]) do
- if not group.normalmovement then
- -- here we should insert some "copy code"
- end
- end
- elseif m == 3 then
- -- do nothing
- end
- end)
- while(true) do
- cf = emu.framecount()
- findblinkingspritegroups(cf, 8, 8)
- m = cf - 4 * math.floor(cf/4)
- colors = {[0]="red", [1]="green", [2]="red",[3]="green",[4]="red",[5]="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