Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --
- -- ░█▀▄░█▀█░█▀█░█▄█░░░░█░░░█░█░█▀█
- -- ░█▀▄░█░█░█░█░█░█░░░░█░░░█░█░█▀█
- -- ░▀▀░░▀▀▀░▀▀▀░▀░▀░▀░░▀▀▀░▀▀▀░▀░▀
- --
- --
- -- Fair warning: this code is about as bad as the things it does to games.
- -- GBA support experimental and frankly quite boring.
- --Original NES Braidulator by Antony Lavelle 2009 got_wot@hotmail.com http://www.the-exp.net
- --Change these settings to adjust options
- --Which key you would like to function as the "rewind key"
- local rewindKey = 'W' -- Hold this to go back in time!
- --hacks = false;
- hacks = 'wario4'
- wario4_tileset = true;
- wario1_tileset = false;
- wario1_levelload = false;
- wario4_levelid = false;
- -- Keys. Feel free to change them to something convenient, because I have a weird keyboard layout
- randomkey = "A" -- Just your standard fare. One random WRAM byte.
- plusminuskey = "S" -- +/- on one random WRAM byte. Probably the safest you can do which still has some effect.
- powerkey = "D" -- Power corruption! 16 random bytes. The most fun key you can press.
- highkey = "F" -- On GB, random byte from HRAM, may have drastic consequences. On GBA, power corruption on IRAM
- vramkey = "G" -- Messes up vram (graphics). Purely visual - totally safe.
- freezekey = "H" -- Freezes a random byte in memory indefinedly. May have totally different effects from regular corruption.
- unfreezekey = "J" -- Unfreezes every frozen byte. This also happens automatically when rewinding.
- savetileskey = "K" -- Save current tiles.
- restoretileskey = "L" -- Restore saved tiles. Purely visual, can be used to copy tiles from game to game etc.
- wrammap = "Q" -- Display an interactive memory map, one pixel per byte.
- -- Opacity = value. Blue = byte changed this frame. Green = HRAM.
- -- Left: +1 Right: -1 Middle: set to $FF
- -- Warning: SLOW! PARTLY BROKEN FOR GBA!
- rewindon = "E" -- Switches rewinding on and off. May save some 15%, depending on your computer.
- debugkey = "\\" -- Displays some boring CPU info.
- --How much rewind power would you like? (The higher the number the further back in time you can go, but more computer memory is used up)
- --Do not set to 0!
- local saveMax = 2000;
- funtimes = 0;
- txttime = 0;
- --The stuff below is for more advanced users, enter at your own peril!
- print("Boom loaded!")
- if hacks then
- print("Hack mode: ", hacks)
- end
- function rainbowcolor(ri)
- freq = 0.15
- r = math.sin(freq*ri) * 127 + 128
- g = math.sin(freq*ri+2) * 127 + 128
- b = math.sin(freq*ri+4) * 127 + 128
- return {r, g, b}
- end
- function randmemory(from, to) -- gets a random memory offset, avoiding the stack
- if gb then
- while (true) do
- bang = math.random(from, to)
- if bang < sp or bang > stack then
- break
- end
- end
- return bang
- else
- return math.random(from, to)
- end
- end
- frozen = {}
- crashi = 0
- vram = {}
- wram = {}
- prevwram = {}
- s = {0xff, 0xff, 0x00, 0x00, 0xbb, 0xbb, 0x8b, 0x8b, 0x68, 0x68, 0x8b, 0x8b, 0xeb, 0xeb, 0x18, 0x18}
- stack = -1
- -- dumb format for speed/convenience
- invalid_opcodes = {[0xd3]= true, [0xdb]= true, [0xdd]= true, [0xe3]= true, [0xe4]= true, [0xeb]= true, [0xec]= true, [0xed]= true, [0xfd]= true, [0xf4]= true}
- local saveArray = {};--the Array in which the save states are stored
- local saveCount = 1;--used for finding which array position to cycle through
- local save; -- the variable used for storing the save state
- local rewindCount = 0;--this stops you looping back around the array if theres nothing at the end
- local savePreventBuffer = 1;--Used for more control over when save states will be saved, not really used in this version much.
- local saveFrequency = 10; -- look at me mom, I'm editing LIVE!
- local timer = -1;
- local rewind = true
- if hacks == 'wario1' then
- memory.writebyte(0xA8C7, 0x01);
- end
- if hacks == 'wario1' and wario1_tileset == true then
- --preliminary block writing in memory
- print('Writing tileset blocks on the level...');
- blockCUR = 0x00;
- for layoutRAM = 0xC000, 0xC200 do
- memory.writebyte(layoutRAM, 0x7F);
- end
- layoutRAM = 0xC200;
- for blockCUR = 0x00, 0x80 do
- memory.writebyte(layoutRAM,blockCUR);
- layoutRAM = layoutRAM + 0x01;
- end
- for layoutRAM = 0xC280, 0xC500 do
- memory.writebyte(layoutRAM, 0x7F);
- end
- for layoutRAM = 0xC500, 0xC600 do
- memory.writebyte(layoutRAM, 0x00);
- end
- end
- if hacks == 'wario4' and wario4_levelid then
- memory.writebyte(0x03000023,wario4_levelid);
- print('Level ID Set to ', wario4_levelid)
- end
- if hacks == 'wario4' and wario4_tileset == true then
- --preliminary block writing in memory
- print('Writing tileset blocks on the level...');
- memory.writebyte(0x03000C3C, 0x08);
- blockCUR = 0x0000;
- -- for layoutRAM = 0x02000430, 0x201042F do
- -- memory.writeword(layoutRAM, 0x7F);
- -- end
- -- layoutRAM = 0x020000E4;
- -- Set room width
- memory.writebyte(0x03000060,0x29);
- memory.writebyte(0x03000068,0x29);
- --height
- memory.writebyte(0x03000062,0x17);
- memory.writebyte(0x0300006A,0x17);
- layoutRAM = 0x020000E4 - 0x0050 - 0x0050;
- counter = 0;
- counter2 = 0;
- counter3 = 1;
- -- for blockCUR = 0x0000, 0x01FF do
- for blockCUR = 0x0000, 0x02FF do
- if (counter==8) then
- layoutRAM = layoutRAM + 0x0042;
- counter = 0;
- counter2 = counter2 + 1;
- end
- if (counter2==22) then
- layoutRAM = (0x020000E4-0x0050-0x0050) + (0x0010*counter3);
- counter2 = 0;
- counter3 = counter3 + 1;
- end
- memory.writeword(layoutRAM,blockCUR);
- layoutRAM = layoutRAM + 0x0002;
- counter = counter + 1;
- end
- -- for layoutRAM = 0xC280, 0xC500 do
- -- memory.writebyte(layoutRAM, 0x7F);
- -- end
- -- for layoutRAM = 0xC500, 0xC600 do
- -- memory.writebyte(layoutRAM, 0x00);
- -- end
- print('Remember tileset address is 0xFINDMEPLEASE');
- end
- if hacks == 'wario1' and wario1_levelload == true then
- print('Loading Level from wario.dat...');
- open_level = io.open('wario.dat', "rb") or false;
- if open_level == false then
- print('Can\'t open wario.dat');
- else
- load_level = open_level:read("*all");
- print('COMING SOON');
- -- load_status == 1;
- -- if load_level[0x1FFF] or load_level[0x2000] then
- -- load_status = 0;
- -- end
- print(load_level:read(1));
- if load_level[0x1FFF] then
- layoutRAM = 0xC000;
- for i = 0x0000, 0x1FFF do
- memory.writebyte(layoutRAM, load_level:read(i));
- end
- else
- print('ERROR: A level has to be 0x1FFF bytes long.');
- end
- open_level:close();
- end
- end
- while (true) do
- keys = input.get();
- timer = timer + 1;
- savePreventBuffer = savePreventBuffer-1;
- if savePreventBuffer==0 then
- savePreventBuffer = 1;
- end;
- if hacks =='wario1' then
- -- memory.writebyte(0xA8C5, 0x01); -- Debug
- memory.writebyte(0xA99D, 0x10); -- Free camera
- -- memory.writebyte(0xA61C, 0x00); -- override music thing
- action = memory.readbyte(0xA91A);
- pause = memory.readbyte(0xA908);
- if action == 0x09 and pause == 0x00 then -- death action
- memory.writebyte(0xA91A, 0x00); -- Prevent death
- end
- -- memory.writebyte(0x94E2, 0x03); -- NOT Free camera
- end
- keys = input.get();
- if keys[rewindKey] then
- savePreventBuffer = 5;
- if rewindCount==0 then
- --makes sure you can't go back too far could also include other things in here, left empty for now.
- else
- savestate.load(saveArray[saveCount]);
- saveCount = saveCount-1;
- rewindCount = rewindCount-1;
- if saveCount==0 then
- saveCount = saveMax-1;
- end;
- end;
- local HUDMATH = rewindCount / saveMax;--Making the rewind time a percentage.
- gui.text(1,0, string.format("%.2f%%", HUDMATH * 100));--Displaying the time onscreen.
- if math.fmod(timer, 30) <= 15 then
- gui.text(138,8*2, "<<"); -- picky, picky
- end;
- end;
- if rewind and savePreventBuffer==1 and math.fmod(timer, saveFrequency) == 0 then
- -- gui.text(80,15,"");
- saveCount=saveCount+1;
- if saveCount==saveMax then
- saveCount = 1;
- end
- rewindCount = rewindCount+1;
- if rewindCount==saveMax-1 then
- rewindCount = saveMax-2;
- end;
- save = savestate.create();
- savestate.save(save);
- saveArray[saveCount] = save;
- end;
- if math.fmod(timer, 32) == 0 then
- header = memory.readbyte(0x133) -- last byte of logo on GB
- if header == 0x3e then
- gb = true
- gba = false
- else
- gb = false
- gba = true
- end
- end
- if gb then
- pc = memory.getregister('pc')
- op = memory.readbyte(pc)
- is_invalid = invalid_opcodes[op]
- sp = memory.getregister('sp')
- if crashi <= 1 then
- if stack == -1 and sp < 0xe000 and sp >= 0xc000 then
- stack = (math.ceil(sp / 0x10) * 0x10)-1
- print(string.format("sp=%04X, stack detected at %04X", sp, stack))
- elseif sp > 0xFF00 then
- --print("Stack detected in HRAM, restart?")
- stack = -1
- end
- end
- --if sp <=
- end
- if keys[debugkey] then
- if gb then
- debugtext = string.format("pc=%04X sp=%04X", pc, sp)
- gui.text(160-(string.len(debugtext)*4),0, debugtext, 'green');
- debugtext = string.format("opcode %02X", op)
- gui.text(160-(string.len(debugtext)*4),8, debugtext, 'green');
- else
- debugtext = string.format("GBA")
- gui.text(240-(string.len(debugtext)*4),0, debugtext, 'green');
- end
- end
- if gb then
- if pc >= 0x8000 or sp < 0x8000 or is_invalid or pc == 0x39 then
- crashi = crashi + 1
- if crashi >= 2 then
- gui.text(1,8, crashi, 'red');
- if crashi > 10 then info = "Crashed" else info = "Clinical death" end
- crashtext = string.format(info.." pc=%04X sp=%04X", pc, sp)
- gui.text(160-(string.len(crashtext)*4),0, crashtext, 'red');
- crashtext = ""
- if is_invalid then
- crashtext = string.format("Invalid opcode %02X", op)
- elseif pc == 0x39 then
- crashtext = string.format("Stuck in rst 38", op)
- end
- gui.text(160-(string.len(crashtext)*4),8, crashtext, 'red');
- end
- else
- crashi = 0
- end
- -- print(string.format('%04X', memory.getregister('pc')))
- end
- if keys[randomkey] then
- gui.text(1,137, "Random bytes"); -- picky, picky
- if gb then
- bang1 = randmemory(0x9800, 0xFEFF)
- elseif gba then
- bang1 = randmemory(0x2000000, 0x0203FFFF)
- end
- bang2 = math.random(0, 0xFF);
- memory.writebyte(bang1, bang2);
- --print(string.format("%04X => %02X", bang1, bang2));
- end;
- if keys[plusminuskey] then
- if gb then
- bang1 = randmemory(0x9800, 0xFEFF)
- elseif gba then
- bang1 = randmemory(0x2000000, 0x0203FFFF)
- end
- bang2 = AND(memory.readbyte(bang1) + math.random(-1, 1), 0xFF);
- memory.writebyte(bang1, bang2);
- gui.text(1,137, string.format("%04X +/- 1", bang1)); -- picky, picky
- --print(string.format("%04X => %02X", bang1, bang2));
- end;
- -- KABLOOEY
- if keys[powerkey] then
- gui.text(1,137, "Power corruption!", rainbowcolor(timer)); -- picky, picky
- for i = 0, 0xF do
- if gb then
- bang1 = randmemory(0xA000, 0xFEFF)
- elseif gba then
- --if math.random(1) then
- bang1 = randmemory(0x2000000, 0x0203FFFF)
- --else
- -- bang1 = randmemory(0x3000000, 0x0303FFFF)
- --end
- end
- bang2 = math.random(0x00, 0xFF);
- memory.writebyte(bang1, bang2);
- --print(string.format("%04X => %02X", bang1, bang2));
- end;
- end;
- -- KABLOOEY
- if keys[highkey] then
- if gb then
- gui.text(1,137, "HRAM corruption!"); -- picky, picky
- bang1 = randmemory(0xFF8C, 0xFFFE)
- bang2 = math.random(0, 0xFF);
- memory.writebyte(bang1, bang2);
- end
- if gba then
- gui.text(1,137, "Power corruption INT!", rainbowcolor(timer)); -- picky, picky
- for i = 0, 0xF do
- bang1 = randmemory(0x3000000, 0x0300FFFF)
- bang2 = math.random(0x00, 0xFF);
- memory.writebyte(bang1, bang2);
- end;
- end
- end;
- if keys[vramkey] then
- rand = math.random(0, 16)
- if gb then
- if rand >= 3 then
- gui.text(1,137, "Trashing VRAM");
- bang1 = math.random(0x8000, 0x9FFF)
- bang2 = math.random(0, 0xFF);
- memory.writebyte(bang1, bang2);
- --elseif rand >= 3 then -- I hate you vba
- -- gui.text(1,137, "Trashing palettes");
- -- bang1 = math.random(0, 0xFF);
- -- bang2 = math.random(0, 0xFF);
- -- memory.writebyte(0xFF68, bang1);
- -- memory.writebyte(0xFF69, bang2);
- elseif rand >= 1 then
- gui.text(1,137, "Mixing up tiles");
- bang1 = math.random(0x8000, 0x9700)
- tile = memory.readbyterange(bang1, 0x10)
- bang2 = math.random(0x8000, 0x9700)
- for i,byte in pairs(tile) do
- memory.writebyte(bang2+i, byte)
- end
- memory.writebyte(bang1, bang2);
- else
- gui.text(1,137, "Trashing OAM");
- bang1 = math.random(0xFE00, 0xFE90)
- bang2 = math.random(0, 0xFF);
- memory.writebyte(bang1, bang2);
- end
- rand2 = math.random(0, 10000)
- if rand2 == 0 then
- bang = math.random(0x8000, 0x9700)
- bang = AND(bang, 0xfff0)
- for i,byte in pairs(s) do
- memory.writebyte(bang-1+i, byte)
- end
- gui.text(1,137, "4");
- end
- elseif gba then
- for i = 0, 0x8 do -- larger screen, larger corruption
- if rand >= 3 then
- gui.text(1,137, "Trashing VRAM");
- bang1 = math.random(0x6000000, 0x6017fff)
- bang2 = math.random(0, 0xFF);
- memory.writebyte(bang1, bang2);
- else
- gui.text(1,137, "Trashing palettes");
- bang1 = math.random(0x5000000, 0x5000400)
- bang2 = math.random(0, 0xFF);
- memory.writebyte(bang1, bang2);
- end
- end
- end
- --print(string.format("%04X => %02X", bang1, bang2));
- end;
- if keys[freezekey] then
- gui.text(1,137, "Freeze"); -- picky, picky
- for i = 0, 0xF do
- if gb then
- bang1 = randmemory(0xC000, 0xDFFF)
- elseif gba then
- bang1 = randmemory(0x2000000, 0x0203FFFF)
- end
- --bang2 = math.random(0x00, 0xFF);
- frozen[bang1] = memory.readbyte(bang1);
- --print(string.format("%04X => %02X", bang1, bang2));
- end;
- end;
- if keys[unfreezekey] or keys[rewindKey] then
- gui.text(1,137, "Unfreeze")
- frozen = {}
- end
- if keys[savetileskey] then
- if gb then
- gui.text(1,137, "Saved tiles"); -- picky, picky
- vram = memory.readbyterange(0x8000, 0x1700)
- end
- end;
- if keys[restoretileskey] then
- if gb then
- gui.text(1,137, "Restored tiles")
- for i,v in pairs(vram) do
- memory.writebyte(0x8000-1+i, v);
- end
- end
- end
- if keys[rewindon] and not lastkeys[rewindon] then rewind = not rewind end
- if keys[rewindon] then
- if rewind then text = "Rewind ON!" else text = "Rewind OFF!" end
- gui.text(1,137, text)
- end
- if keys[wrammap] and not lastkeys[wrammap] then showwram = not showwram; end
- if showwram then
- --gui.text(1,137, "Live WRAM")
- if gb then
- wram = memory.readbyterange(0xC000, 0x2000)
- for k,v in pairs(memory.readbyterange(0xFF00, 0xFF)) do wram[0x2000+k] = v end
- width = 64
- elseif gba then
- wram = memory.readbyterange(0x2000000, 0x3FFFF)
- width = 64*3
- end
- for i,v in pairs(wram) do
- --memory.writebyte(0x8000-1+i, v);
- if prevwram[i] ~= wram[i] then
- color = {0, 0, 255, v}
- elseif frozen[0xC000+i-1] then
- color = {0, 255, 255, v}
- elseif i > 0x2000 then
- color = {0, 255, 0, v}
- else
- color = {255, 0, 0, v}
- end
- gui.pixel((i-1)%width, math.floor((i-1)/width), color)
- end
- prevwram = wram
- xmouse, ymouse, left, right, middle = keys['xmouse'], keys['ymouse'], keys['leftclick'], keys['rightclick'], keys['middleclick']
- if left or right or middle and xmouse <= width then
- offset = 0xC000 + (xmouse%width) + (ymouse*width)
- if left then
- memory.writebyte(offset, AND(memory.readbyte(offset) + 1, 0xFF))
- elseif right then
- memory.writebyte(offset, AND(memory.readbyte(offset) - 1, 0xFF))
- else
- memory.writebyte(offset, 0xff)
- end
- end
- end
- for i,v in pairs(frozen) do
- memory.writebyte(i, v);
- end
- lastkeys = keys
- emu.frameadvance();
- end;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement