Closed g0me3 closed 5 years ago
Спасибо за идеи. Я думал про реализацию режима генерации конфигов - либо отдельным плагином, либо в основном редакторе так как ты описал. Там есть пункт, который немного усложняет задачу 2.5 - кроме смещений, может задавать и код функций - как именно будут загружаться данные. Но вообще есть 3-4 стандартные функции, покрывающие большинство игр, можно выбор между ними просто сделать. Ну и ещё отдельная ветка для случае, когда слой бит палитры (атрибутов) хранится отдельно от описания блоками.
Thanks for suggestions. I think about config generation mode. There is additional paragraph 2.5 needed - selecting or writing a function for load/store data, but it possible to select this function from 3-4 standard cases. And an additional case for separate palette bits (attributes) layer.
по мне так было бы вообще достаточно скажем темплейта плагина. вписать туда все необходимые функции и операции, откоментить какая для чего нужна и вместо цифирей поставить заглушки.
вот я знаю, какого размера блоки, где они, где экраны/атрибуты и все такое, но все конфиги совершенно разные и хрен поймешь, где что для чего нужно и за что отвечает.
в мануальном режиме я бы может еще бы и подобрал сам методом тыка, но каждый раз грузить для этого конфиг - заманаешься.
ну вот например, у меня есть смещение либы макроблоков 2х2 по 4 байта на блок 12\34. есть размер экрана 16х15 блоков. есть смещение таблицы атрибутов, смещение палитры и смещение собственно экрана. ну и банк графики задать. всего 6 параметров, которые необходимо для отображения чего угодно. почему бы не задать какую-то одну функцию для плагина, куда надо занести вот эти 6 параметров и получить результат. а если их можно было бы складывать в списки, руками добавляя каждый отдельный экран своими параметрами, то и вообще все экраны занести можно.
по мне так было бы вообще достаточно скажем темплейта плагина. вписать туда все необходимые функции и операции, откоментить какая для чего нужна и вместо цифирей поставить заглушки.
Кроме цифр есть ещё способ загрузки блоков, макроблоков, экранов, атрибутов и остальных элементов - каждый из них может загружаться либо линейно (сначала описан один блок, потом второй и т.п.), либо по частям из массивов (сначала массив с 1 четвертинками блоков, потом массив со вторыми четвертинками). Далее для каждого из массивов может быть загрузка как построчно, так и постобцово. Ещё для многих массивов может быть маска - когда в одном байте номер блока хранится, например, в 6 битах, а оставшиемя два описывают атрибуты или физические свойства. Ещё может отличаться способ хранения атрибутов - они могут быть связаны с блоками, макроблоками либо храниться отдельным слоем.
Ещё что-то может быть сжато, или занимать вообще 9 бит, из которых 1 бит в отдельном массиве, или использовать какие-то симметрии для экономии места, или же биты, кодирующие номера блоков могут быть переставлены местами, или же строки экранов могут быть инвертированы между собой, или ещё какие угодно хитрости пришедшие в голову разработчиками - все случаи никак не опишешь универсальной функцией. Единственный способ отобразить это в редакторе, как это и сделано - это использовать раздельные функции для описания каждого базового строительного блока уровня (тайлы->блоки->(макроблоки)->экраны, с атрибутами или без) и иметь возможность комбинировать их между собой произвольным образом.
Невозможно это описать одной функцией - там комбинаторная сложность будет - есть очень странные комбинации в играх. Вот все встреченные в разных играх комбинации: https://spiiin.github.io/CadEditor/cadeditor-supported-games.html
Если разберёшься в формате этой таблицы - сможешь подобрать конфиг-шаблон для своего случая. Если я правильно понял формат, который ты описал - блоки размером 2x2, описанные линейно и построчно, макроблоки (соединения блоков) отсутствуют, атрубиты палитры отдельным массивом (по 1 байту на блок? могут быть ещё по 1 байту на 4 блока - по 2 бита), экраны 16x15. Этот вариант формата в точности: Можно брать любой из конфигов для этих игр и подставлять свои цифры. Ну и дампы chr памяти и палитры, с которыми отображать. Точнее, почти любой - атрибуты палитры почти всегда хранятся в 2х младших битах. Но в Metal Mech, к примеру - в 3-4 битах, так что там функция загрузки блоков чуть отличается).
У меня есть идея свои тестовые ромы сделать с разными форматами, и на примере них как раз шаблоны и написать, чтобы не завязывать шаблоны на конкретные игр.
в мануальном режиме я бы может еще бы и подобрал сам методом тыка, но каждый раз грузить для этого конфиг - заманаешься.
Можно руками обновлять конфиг в текстовом редакторе, а в самом CadEditor нажимать кнопку "Reload config" - это достаточно быстро, чтобы покрутить цифры как раз. Экраны тоже можно так вписывать по одному. Также можно делать "закладки", в которых описать, какие экраны с какими свойствами показывать. Согласен, что огромная проблема в том, что это недокументировано никак. Ну и визуально было бы конечно удобнее, буду двигаться в эту сторону со временем. Ещё попробую видео записать, как я сам конфиги делаю.
Вообще, наверное, для начала следующим апдейтом и составлю список "шаблонных" конфигов для основных случаев и откомментирую их детально. Это будут, если смотреть по таблице, ячейки, в которых список игр наибольший.
я вот чего до сих пор не могу понять, зачем рипать в отдельные файлы банки графики из рома, если они там в самом роме такие же и сам ром ты открываешь. почему нельзя тупо указать офсет банка в роме хотя бы? (хотя программа могла бы и сама рассчитывать осет по номеру банка лол). я глянул - там даже не конверт во что-то, а прямо такие рип банка. зойчем? ну я могу предположить, что иногда банки бывают составлены из нескольких разрозненных блоков в разных банках... но для некоторых мапперов такого вообще не бывает, скажем для ммц1 там всегда минимальный размер 4к.
На эму-ленде отвечал уже. В конфигах очень много возможностей. МОЖНО указать и оффсет банка и номер банка, если хочется. Пример конфига с описанием по адресу (функции getVideoOffset/getVideoObjOffset - отдельно для банков с фоном и банков с графикой спрайтов): https://github.com/spiiin/CadEditor/blob/master/CadEditor/settings_nes/little_mermaid/Settings_Mermaid-1.cs И по номеру банка (формулой): https://github.com/spiiin/CadEditor/blob/master/CadEditor/settings_nes/megaman_4/Settings_Megaman4-1.cs И составить банк из нескольких частей в ROM можно (примеров нет, правда, есть в duck tales 2 скрипт распаковки из нескольких RLE кусков в дампы).
Дампы чаще используются по нескольким причинам:
Это универсальнее - дамп подходит и для случая с CHR-ROM, и для случая с CHR-RAM, когда банк может храниться в сжатом виде. Так, можно копипастить шаблон конфига с дампом для игры c CHR-ROM и использовать его для игры, которая использует CHR-RAM, и в которой нельзя указать адрес в виде оффсета или номера банка.
Снятие дампов легко автоматизировать, что и сделано: https://github.com/spiiin/CadEditor/blob/master/Stuff/nes_lua/dump_chr_and_pal/dump_chr_and_pal.lua Когда счёт на сотни и тысячи конфигов, экономятся часы работы. Часто встречается, что один уровень использует 2-3 варианта CHR, намного быстрее сдампить их, чем сопоставить их с номерами банков в ROM (особенно, если игра использует банки меньше чем в 4 кб).
У меня есть скрипт для CadEditor, который по загруженному конфигу ищет, нет ли в ROM такого банка: https://github.com/spiiin/CadEditor/blob/master/CadEditor/Scripts/Script-FindChrDumpInROM.cs (это первый и простой вариант, только для поиска банка в 4 кб целиком, но можно и более сложные случаи добавить). Им можно будет потом и обновить все конфиги - подменить дампы на адреса в ROM. Но не вижу необходимости этим заниматься сейчас, кроме как уменьшить размер дистрибутива редактора.
хорошо, вот я видимо совсем не понимаю смысла второго параметра. он у всех вообще как будто рандомный. new OffsetRec(0x86E0, 1 , 16*15, 16, 15), я поставил везде 1 и получаю https://imgur.com/a/4vPrAT6 должно быть https://imgur.com/a/LlaBn7N конфиг https://pastebin.com/paTrbar0 что я делаю не так?
так ладно, разобрался. взял с дуру цпу офсеты, а не ромовые лол, минус 8000 и все вроде ок. работаем дальше
оффсеты не оттуда, ага
public OffsetRec[] getScreensOffsetsForLevels() {
var ans = new OffsetRec[] {
new OffsetRec(0x810, 1 , 16*15, 16, 15),
new OffsetRec(0x940, 1 , 16*15, 16, 15),
new OffsetRec(0xA70, 1 , 16*15, 16, 15),
new OffsetRec(0xba0, 1 , 16*15, 16, 15),
};
return ans;
}
Второй параметр означает количество экранов в группе. Можно вот так их описать, чтобы каждый отдельно не задавать:
public OffsetRec[] getScreensOffsetsForLevels() {
var ans = new OffsetRec[] {
new OffsetRec(0x810, 4 , 16*19, 16, 15), //4 экрана, начиная с офсета 0x810, размер экрана 16 блоков в ширину, 15 блоков в высоту, "шаг" между соседними экранами 16*19 байт.
};
return ans;
}
Дальше ещё слой атрибутов отдельно задаётся (атрибуты не связаны с блоками, как в Captain America). Следовательно, для описания слоя палитры отдельно уже другой пример нужен. Из MoonCrystal, например, там ещё функции, которые описывают, как декодируется слой палитры и сохраняется обратно.
https://github.com/spiiin/CadEditor/tree/development/CadEditor/settings_nes/silkworm Описал слой палитры. Функцию для Moon Crystal пришлось немного поправить, потому что там атрибуты хранились после описания экрана, а здесь атрибуты, относящиеся к экрану, хранятся перед описанием экрана.