Приставки > Картриджи / диски
Дампинг, обсуждаем, делимся ромами своих дампов
stargazer:
Все, я победил этот странный баг с искаженными цветами :cool: Обновил архив с исходниками и скомпилированными файлами ядра.
Проблема никак не связана с моими правками и проявилась только из-за более новой версии компилятора.
Вот функция, которая читает 16-битное слово из регистра VDP, в нашем случае из регистра данных с указателем в CRAM
--- Код: ---/* vdp_ctrl.c */
static unsigned int vdp_68k_data_r_m5(void)
{
uint16 data = 0;
/* Clear pending flag */
pending = 0;
/* Check destination code (CD0-CD3) & CD4 */
switch (code & 0x1F)
{
case 0x00:
{
/* read two bytes from VRAM */
/* .... */
break;
}
case 0x04:
{
/* VSRAM index */
int index = addr & 0x7E;
/* .... */
break;
}
case 0x08:
{
/* Read 9-bit word from CRAM */
data = *(uint16 *)&cram[addr & 0x7E];
/* Unpack 9-bit CRAM data (BBBGGGRRR) to 16-bit bus data (BBB0GGG0RRR0) */
data = ((data & 0x1C0) << 3) | ((data & 0x038) << 2) | ((data & 0x007) << 1);
/* Unused bits are set using data from next available FIFO entry */
data |= (fifo[fifo_idx] & ~0xEEE);
/* .... */
break;
}
case 0x0c: /* undocumented 8-bit VRAM read */
{
/* .... */
break;
}
default:
{
/* Invalid code value (normally locks VDP, hard reset required) */
break;
}
}
/* Increment address register */
addr += reg[15];
/* Return data */
return data;
}
--- Конец кода ---
А вот функция чтения 32-битного значения из памяти при эмуляции инструкций CPU 68000, например для инструкций типа "move.l (a0),d1".
Переменная "temp->read16" для данного случая содержит указатель на функцию, приведенную выше.
--- Код: ---/* m68kcpu.h */
INLINE uint m68ki_read_32(uint address)
{
cpu_memory_map *temp;
uint val;
m68ki_set_fc(FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */
m68ki_check_address_error(address, MODE_READ, FLAG_S | m68ki_get_address_space()) /* auto-disable (see m68kcpu.h) */
temp = &m68ki_cpu.memory_map[((address)>>16)&0xff];
if (temp->read16) val = ((*temp->read16)(ADDRESS_68K(address)) << 16) | ((*temp->read16)(ADDRESS_68K(address + 2)));
else val = m68k_read_immediate_32(address);
#ifdef HOOK_CPU
if (UNLIKELY(cpu_hook))
cpu_hook(HOOK_M68K_R, 4, address, val);
#endif
return val;
}
--- Конец кода ---
Найдете ошибку? :)
Порядок вызовов read16 в строке "val = ((*temp->read16)(ADDRESS_68K(address)) << 16) | ((*temp->read16)(ADDRESS_68K(address + 2)));" не определен. При этом результат зависит от этого порядка, так как внутри read16 -> vdp_68k_data_r_m5 происходит увеличение внутреннего адреса VDP.
В данном случае, компилятор почему-то решил, что выгоднее сначала посчитать правую часть выражения, а затем - левую. В результате в 32-битном значении старшее и младшее слова оказались перепутанными.
Этот баг относится к классу "Undefined Behavior"
warezhunter_:
Попалась мне в руки вот такая китайская многоигровка:
https://aliexpress.ru/item/1005003016654103.html
Она интересна тем, что содержит в себе хакнутые версии игр. Например на кнопку Select в некоторых играх восстанавливается здороаье, в Felix The Cat можно трансформироваться в различные формы на кнопку Select. Мне даже удалось сдампить меню этой многоигровки и запустить через Fceux. Надо как то игры все повытаскивать оттуда.
aquasnake:
--- Цитата: stargazer от 20 Июль 2025, 23:29:42 ---doragasu
--- Конец цитаты ---
S29GL064: Spansion Nor-flash 64Mbit
YX5200: 悦欣 sigle chip mp3 decoder(www.yxin18.com)
HCT377: Latch, Octal D-type flip-flop
The dumpped 4MB ROM may not be the full data, the full ROM I guess should be the size of 8MB. Despite having almost half of the data redundancy, the data at certain addresses is different. In principle, a RAM chip is needed, but by doubling the redundant data and using a latch to control the switching of the highest address bit, cost reduction can be achieved.
Werton:
--- Цитата: stargazer от 23 Июль 2025, 23:37:39 ---Этот баг относится к классу "Undefined Behavior"
--- Конец цитаты ---
Нет, это Unspecified Behavior :)
warezhunter_:
Попалась на глаза мне вот эта одноигровка:
https://aliexpress.ru/item/1005002165797973.html
и значит решил я её сдампить. Смотрю на плату а на ней квадратная микросхема SMD133 и еще две микросхемы CS18LV20483 и S29GL064N.
Начинаю гуглить SMD133 это маппер MMC3, S29GL064N - 64 mbit флэш-память, CS18LV20483 - 256k SRAM-память. При попытке сдампить под MMC3 ничего не работает, помучался немного и полез гуглить как эта микросхема SMD133 работает и наткнулся на маппер 268 на сайте nesdev.org, еще раз внимательно разглядываю картридж и вижу надпись на нём Mindkids, вижу в таблице, что это маппер 268.0 или 268.1, дамплю как --mapper 268.0. Открываю его в Fceux 2.6.6 и он работает! Надо было додуматься еще одноигровку на нём сделать. :wacko:
JRBVZ:
Видимо для китайца S29GL064 дешевле чем аналогичная память меньшего объема, а вся сборка дешевле, чем что-то подобное на dip микросхемах. Так что вопрос только в экономике.
warezhunter_:
А вот еще один экземпляр на маппере 268.1
покупался примерно года 3 назад, сделан на базе Pocket Games 150 in 1
warezhunter_:
И еще один, вот этот:
https://aliexpress.ru/item/1005004232303718.html
Только разобрать у меня его не получилось, ломать его я не хочу, но он сдампился с маппером 268.0, после чего запустился на эмуляторе.
Rumata:
--- Цитата: JRBVZ от 05 Сентябрь 2025, 11:52:34 ---Видимо для китайца S29GL064 дешевле чем аналогичная память меньшего объема,
--- Конец цитаты ---
Это же всё б/у, по наклейке даже моно узнать откуда. Им, небось, ещё и заплатили за утилизацию отходов
warezhunter_:
Всё не дает мне покоя этот картридж на аналоге MMC3 (микросхема AX5202P).
Причем первые две части Rockman видимо перехачены под маппер MMC3.
Сдампил я его под маппер MMC3 при помощи команды
--- Код: ---famicom-duper dump --reset --mapper mmc3 --prg-size 256k --chr-size 256k --file rockman6in1(1).nes
--- Конец кода ---
Команду --reset приписал для того, чтобы при запуске предварительно переключилось в меню с выбором игр, так как при включении консоли стартует игра Rockboard и при нажатии на Reset переключается в нужное меню. При запуске полученного дампа через Fceux из меню стартует только одна игра Rockman 5.
При изучении сдампленного рома, я обнаружил, что меню встроено в игру Rockman 5, а обращения к дополнительным регистрам такие:
--- Код: ---Режим адрес значение hex
start 6000 00
Rockman1 6800 12
Rockman2 6800 16
Rockman3 6800 04
Rockman4 6800 19
Rockman5 6800 00
Rockman6 6800 1B
--- Конец кода ---
То есть при выборе игры через меню, по адресу 6800 записывается определенное значение (для Rockman 1 - 12, для Rockman 2 - 16 и т.д.). Можно сдампить все игры по отдельности, предварительно записав нужное значение по адресу 6800, но я ковяряюсь уже второй день и не пойму как это сделать.
Функционал дополнительного регистра похоже, что такой:
0: 0 - MMC3-256, 1 - MMC3-512;
1, 2, 3: PRG addr, bit2 видимо также используется как старший адрес CHR;
4: 0 - CHR ROM, 1 - CHR RAM
Обращение по 6800 вероятно лочит регистр от записи.
Прошу помощи в написании скрипта для кластеровского дампера, чтобы сдампить данный картридж. В программировании C# я не силен, что то более простое написать могу.
mutabor:
--- Цитата: warezhunter_ от 10 Август 2025, 10:52:46 ---Мне даже удалось сдампить меню этой многоигровки и запустить через Fceux. Надо как то игры все повытаскивать оттуда.
--- Конец цитаты ---
Надо разбираться как управляется маппер, зашитый в ПЛИС. При загрузке CHR RAM используются такие регистры:
5003 0
5005 0
5002 B
5006 0
5001 10
5006 1
5001 11
...
5006 F
5001 1F
Вероятно 5001 (и 5002?) управляют PRG банком, надо писать в этот регистр и смотреть что дампится.
--- Цитата: warezhunter_ от 05 Сентябрь 2025, 11:31:24 ---Попалась на глаза мне вот эта одноигровка:
SMD133 это маппер MMC3, S29GL064N - 64 mbit флэш-память, CS18LV20483 - 256k SRAM-память.
--- Конец цитаты ---
Ага, такое относительно часто попадается, повезло что 256k CHR.
Vlad666:
Можно ли как-то вытащить Super Mario Bros и Lost Levels из Super Mario All-Stars на SNES?
warezhunter_:
--- Цитата: mutabor от 09 Сентябрь 2025, 21:01:15 ---Вероятно 5001 (и 5002?) управляют PRG банком, надо писать в этот регистр и смотреть что дампится.
--- Конец цитаты ---
А можно какой то пример, как сделать запись в регистр а потом снять дамп? Я всю документацию на дампер этот пересмотрел, не могу понять как это сделать.
Yoti:
--- Цитата: Vlad666 от 09 Сентябрь 2025, 21:26:52 ---Можно ли как-то вытащить Super Mario Bros и Lost Levels из Super Mario All-Stars на SNES?
--- Конец цитаты ---
В этой теме дампят картриджи. Лучше сходи на поклон к великой платной нейросети с этим вопросом. :biggrin:
mutabor:
--- Цитата: warezhunter_ от 10 Сентябрь 2025, 04:25:39 ---А можно какой то пример, как сделать запись в регистр а потом снять дамп?
--- Конец цитаты ---
У тебя же кластеровский дампер? Надо писать скрипт для этого маппера.
dumper.WriteCpu(0x5000, 0x00); // записываем 0 по адресу 0x5000
warezhunter_:
--- Цитата: mutabor от 10 Сентябрь 2025, 19:27:40 ---У тебя же кластеровский дампер? Надо писать скрипт для этого маппера.
dumper.WriteCpu(0x5000, 0x00); // записываем 0 по адресу 0x5000
--- Конец цитаты ---
Да, есть у меня кластеровский дампер, и я видел эту команду в реализации некоторых мапперов. Попробую просто вставить эту команду в отдельный скрипт, обзову его как MyScript.cs и потом попробую выполнить дамп такой примерной командой:
--- Код: ---famicom-dumper dump --mapper MMC3 --file game.nes --cs-file MyScript.cs
--- Конец кода ---
И посмотрю что получится.
Добавлено позже:
Для начала я попытался сдампить все игры по одной в том картридже 6 in 1 Rockman с предварительной записью по адресу 6800, при записи любого значения по этому адресу дампится только Rockman 6, пока я не могу понять как сдампить остальные игры.
Данный картридж ведет себя странно, только что дампился Rockman 5 с записью 6800, а теперь это не дает никакого эффекта, дампится меню и запускается одна игра Rockman 5.
Обнаружил, что скорее всего у меня в память ничего не записывается, вот код скрипта:
--- Код: ---class MyScript
{
void Run(IFamicomDumperConnection dumper)
{
dumper.WriteCpu(0x6800, 0x12); //записываем 12 по адресу 0x6800
}
}
--- Конец кода ---
Как только я его выполняю командой:
--- Код: ---famicom-dumper script --cs-file MyScript.cs
--- Конец кода ---
Получаю:
--- Код: ---Running MyScript.Run()...
--- Конец кода ---
Только проблема в том, что никуда ничего не записывается, светодиод на дампере гаснет на несколько секунд картридж перезапускается, как будто нажали на Reset или выключили питание.
mutabor:
--- Цитата: warezhunter_ от 13 Сентябрь 2025, 11:24:28 ---Только проблема в том, что никуда ничего не записывается, светодиод на дампере гаснет на несколько секунд картридж перезапускается, как будто нажали на Reset или выключили питание.
--- Конец цитаты ---
Ну так нужно не только в регистр записать, но и собственно ром сдампить. Возьми для примера скрипт для дампа NROM и добавь перед собственно дампом запись в регистр.
warezhunter_:
--- Цитата: mutabor от 13 Сентябрь 2025, 20:15:38 ---Ну так нужно не только в регистр записать, но и собственно ром сдампить. Возьми для примера скрипт для дампа NROM и добавь перед собственно дампом запись в регистр.
--- Конец цитаты ---
А куда вставлять то?
Я пробовал вставить
--- Код: ---public void DumpPrg(IFamicomDumperConnection dumper, List<byte> data, int size)
{
Console.Write("Reading PRG... ");
dumper.WriteCpu (0x6800, 0x12);
data.AddRange(dumper.ReadCpu((ushort)(0x10000 - size), size));
Console.WriteLine("OK");
}
public void DumpChr(IFamicomDumperConnection dumper, List<byte> data, int size)
{
Console.Write("Reading CHR... ");
dumper.WriteCpu (0x6800, 0x12);
data.AddRange(dumper.ReadPpu(0x0000, size));
Console.WriteLine("OK");
}
--- Конец кода ---
Снял дамп до добавления dumper.WriteCpu (0x6800, 0x12) и после, они абсолютно ничем не отличаются. Значит запись Cpu либо игнорируется, либо Cpu залочена. Если записать по адресу 00D4 значение 10, а в 0040 значение от 0 до 5, то стартует сразу выбранная мгра 0 - Rockman, 1 - Rockman 2, 2 - Rockman3, 3 - Rockman3, 4 - Rockman5, 5 - Rockman6, но я пробовал добавлять всё это через WriteCpu, чтобы из меню стартовала нужная игра перед дампом, но реакции на команду WriteCpu никакой.
mutabor:
--- Цитата: warezhunter_ от 14 Сентябрь 2025, 08:48:50 ---Я пробовал вставить
--- Конец цитаты ---
Да, так верно
--- Цитата: warezhunter_ от 14 Сентябрь 2025, 08:48:50 ---Снял дамп до добавления dumper.WriteCpu (0x6800, 0x12) и после, они абсолютно ничем не отличаются.
--- Конец цитаты ---
А тут уже возможны варианты. Во первых можно добавить ресет перед прочими действиями:
dumper.Reset();
Во вторых может на самом деле маппер управляется по другому, либо нужна какая-то инициализация. Хоть и редко, но бывает так, что маппер работает с дампером не так, как с реальной приставкой - например постоянно ресетается или неправильно работают операции (особенно это касается обращений к нижней половине адресного пространства). Тут уже разбираться гораздо сложнее.
Для начала можно поэкспериментировать на чем-то известном и безпроблемном, например простом MMC3 или SMD133. Точно разобравшись как работает запись и дамп - переходить уже к другим.
В случае с рокманом - там судя по фото доп регистры реализованы на рассыпухе - т.е. если ничего не получается - можно составить схему и разобраться с ее логикой.
warezhunter_:
--- Цитата: mutabor от 14 Сентябрь 2025, 09:11:32 ---Во первых можно добавить ресет перед прочими действиями:
dumper.Reset();
--- Конец цитаты ---
Этот картридж устроен так, что при включении приставки запускается игра Rockboard, затем при нажатии на Reset вылазит вот это меню, Rockboard мне не нужна, поэтому я сразу перед дампом даю команду Reset, и еще одно выполнение Reset из меню вызовет переключение обратно на Rockboard надо двойной Reset получается делать. Я думал стартовать выбранную игру через запись в адрес 0040 значений от 0 до 5, после каждой записи в 0040 выполнять 00D4:10 (нажатие кнопки Start), но ощущение такое, что WriteCpu не работает вообще, команда либо игнорируется, либо память залочена и ошибок никаких не выдает. После изучения записи с другими картриджами, было выяснено, что запись сильно ограничена, дампер записывает только в некоторые области памяти.
Навигация
Перейти к полной версии