Skip to content

Instantly share code, notes, and snippets.

@spiiin
Created June 3, 2015 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spiiin/a5ec2c7c9e5b6ba59039 to your computer and use it in GitHub Desktop.
Save spiiin/a5ec2c7c9e5b6ba59039 to your computer and use it in GitHub Desktop.
--загружаем библиотеку gd
require "gd"
--начальный адрес для коррапта (сразу от заголовка образа ROM)
START_ADDR = 0x10
--конечный адрес для коррапта (зависит от маппера, на котором сделан картридж, можно просто выставить размер файла)
END_ADDR = 0x20010
CUR_ADDR = START_ADDR
--конечный номер кадра, после которого нужно сделать скриншот (когда игровой экран уже отображается для игрока, номер замерен для созданного сохранения)
FRAME_FOR_SCREEN = 7035
--тестовое значение, которым будет записано вместо байта игры
WRITE_VALUE = 0x33
--шаг, с которым будет производиться коррапт, для экономии времени поиска
--(изменять каждый байт на экране не нужно, на экране может отображаться большое количество макроблоков, достаточно обнаружить хотя бы один из них).
STEP = 8
--таблица для сохранения хешей всех уникальных скриншотов
shas = {}
--запомнить значение, которое будет испорчено корраптом, чтобы потом его восстановить
lastValue = rom.readbyte(START_ADDR)
--загрузить предварительно заготовленное сохранение из ПЕРВОГО слота (нумерация слотов в эмуляторе начинается с 0, а в LUA - с 1).
s = savestate.create(2)
savestate.load(s)
while (true) do
--если экран загрузился и уже отображается
if (emu.framecount() > FRAME_FOR_SCREEN) then
--сохранить скриншот в памяти
local gdStr = gui.gdscreenshot();
--подсчитать его хеш
local hash = emu.calchash(gdStr, string.len(gdStr));
--если такого скриншота ещё не было
if (not shas[hash]) then
print("Found new screen "..tostring(hash));
local fname = string.format("%05X", CUR_ADDR)..".png";
local gdImg = gd.createFromGdStr(gdStr);
--сохранить скриншот на диск с указанием в имени адреса изменённого байта
gdImg:png(fname)
shas[hash] = true;
end;
--восстановить значение предыдущего байта
rom.writebyte(CUR_ADDR, lastValue);
CUR_ADDR = CUR_ADDR + STEP;
--коррапт следующего байта
lastValue = rom.readbyte(CUR_ADDR);
rom.writebyte(CUR_ADDR, WRITE_VALUE);
--снова загрузка сохранения, чтобы дать возможность игре загрузить из нового образа данные в память
s = savestate.create(2)
--отображение прогресса
savestate.load(s)
gui.text(20,20, string.format("%05X", CUR_ADDR));
--когда все адреса будут обработаны, остановить эмулятор
if (CUR_ADDR > END_ADDR) then
emu.pause();
end
end;
--проматываем эмуляцию до следующего кадра
emu.frameadvance();
end;
# -*- coding: utf-8 -*-
import Image
def cutBlock(pp):
im = Image.open(pp)
X = 96 #загрузить скриншот в любой графический редактор, чтобы посмотреть координаты начала блока
Y = 96
imCut = im.crop((X,Y,X+32,Y+32)) #вырезать из скриншота блок по заданным координатам
imCut.save("_" + pp)
for x in xrange(256):
cutBlock(r"%03d.png"%x)
BLOCK_COUNT = 102
MAX_BLOCK_COUNT = 256
imBig = Image.new("RGB", (32*MAX_BLOCK_COUNT,32))
for x in xrange(BLOCK_COUNT):
im = Image.open("_%03d.png"%x)
imBig.paste(im, (32*x,0,32*x+32,32))
imBig64 = imBig.resize((MAX_BLOCK_COUNT*64,64)) #увеличение размера макроблока до 64x64, требование для использования с редактором CadEditor
imBig64.save("outStrip.png")
using CadEditor;
using System;
using System.Collections.Generic;
using System.Drawing;
public class Data
{
public OffsetRec getScreensOffset() { return new OffsetRec(0x10625 - 16 * 96, 1, 16*96); }
public int getScreenWidth() { return 16; }
public int getScreenHeight() { return 96; }
public int getBigBlocksCount() { return 256; }
public string getBlocksFilename() { return "jackal_1.png"; }
public GetBigTileNoFromScreenFunc getBigTileNoFromScreenFunc() { return getBigTileNoFromScreen; }
public SetBigTileToScreenFunc setBigTileToScreenFunc() { return setBigTileToScreen; }
public bool isBigBlockEditorEnabled() { return false; }
public bool isBlockEditorEnabled() { return false; }
public bool isEnemyEditorEnabled() { return false; }
public int getBigTileNoFromScreen(int[] screenData, int index)
{
int w = getScreenWidth();
int noY = index / w;
noY = (noY/8)*8 + 7 - (noY%8);
int noX = index % w;
return screenData[noY*w + noX];
}
public void setBigTileToScreen(int[] screenData, int index, int value)
{
int w = getScreenWidth();
int noY = index / w;
noY = (noY/8)*8 + 7 - (noY%8);
int noX = index % w;
screenData[noY*w + noX] = value;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment