Войти
ФлеймФорумПрограммирование

Подчистер геймпаков для старых консолей

Страницы: 1 2 Следующая »
#0
(Правка: 11:58) 11:57, 1 июня 2019

Давно уже столкнулся с такой бедой, что скачав набор ROM-ов для какой нибудь старой консоли типа сеги или денди возникают некоторые излишества и неудобства, которые мешают.
1. архивы стало модно паковать в 7zip, но большинство эмуляторов которыми я пользуюсь не умеют налету открывать оттуда ромы, а только из zip или rar
2. архивы набиты кучей разных вариантов одной и той же игры в результате и архивы набухают, и некоторые эмуляторы не дают понять какой именно файл они закачивают, просто берут первый попавшийся видимо, плюс бывает просто забываешь какой именно ром из кучи вариантов открыл и этим затрудняется загрузка старых сохранений в эмуляторе.
Да и зачастую хочется отсортировать список файлов по размеру и смотреть "самые жирные" ромы, т.к. в них зачастую самые прогрессивные в том поколении игры встречаются.
Но ввиду вышеописанных проблем это становится неточно и проблематично.

В общем все эти проблемы заставили сегодня взять и сказать
Изображение
и написать простенькую программку которая вычищает все эти авгиевы конюшни в удобоваримый простой вид без явных дубляжей.

Программа требует установленного WinRAR для манипуляций, так что ограничена виндой.
Что она делает:
- в папке откуда запущена перебирает все .7z-файлы в подпапке work
- каждый распаковывает (без подпапок) в подпапку tmp
- анализирует какой файл является самым лучшим для выживания прежде всего отдавая предпочтение тем где в имени есть [ ! ], [ U ], [ UE ] или [ E ] (последний с меньшим приоритетом). Так же есть еще несколько эвристик, которые лень объяснять, смотрите код если надо.
- запаковывает избранный файл в подпапку out в .zip-архив тут же и удаляет файл-источник из подпапки work

Таким образом мы получаем подчищенную папку где ровно 1-zip = 1-rom и всё чинно и благородно.
Для Game Boy и Game Boy Color еще и производит деление архива на gb и gbc части, т.к. в одном исходном .zip бывает лежат две версии игры для разных платформ.

В общем суть какая - если кому то это интересно, то могу дать исходники с пояснениями как адаптировать под свои архивы. Писать или сюда или в личку. Заранее выкладывать не вижу смысла если не будет интереса.


#1
13:48, 1 июня 2019

=A=L=X=
> 7zip
> Программа требует установленного WinRAR
Решаем проблему отсутствующего бесплатного архиватора платным архиватором? Мсье знает толк.

> анализирует какой файл является самым лучшим
А что делать, если твоя программа не угадала, какой надо файл?

> большинство эмуляторов которыми я пользуюсь не умеют налету открывать оттуда
> ромы
Может лучше тогда допилить эти эмуляторы, а не пилить сторонние приблуды?

#2
(Правка: 14:06) 14:04, 1 июня 2019

Panzerschrek[CN]
> платным архиватором?
Изображение

А вообще там ровно два вызова system( cmd ) - на запаковку и распаковку, можно поменять на что угодно.

> А что делать, если твоя программа не угадала, какой надо файл?

Тогда она распакует все те что набрали одинаковое количество баллов. Количество файлов даже увеличивается, т.к. архив Contra Force.7z превращается в разные Contra Force [!].zip и Super Contra 6 [!].zip, но только если формальные критерии дают в точности одинаковое число оценочных баллов и только для тех файлов где число баллов стало равно.
Т.е. всякие [p1] и [p2] - хаки и полухаки с большой степенью вероятности окажутся за бортом и хоть что-то за бортом не окажется.

> Может лучше тогда допилить эти эмуляторы

Допиливай, как допилишь тащи сюда.

#3
5:33, 2 июня 2019

в чем проблема распаковать архив 7Zip'ом ?

#4
5:58, 2 июня 2019

endeavour_pr
> в чем проблема распаковать архив 7Zip'ом ?

там тысячи игр в типовом архиве, распаковывать замучаешься.

#5
6:01, 2 июня 2019

Провёл у себя зачистку и подчистку архивов (как правило это так называемые GoodROM) для GB, GBC, NES, SMD, SNES - каждый раз требуется небольшая переадаптация программы под встречаемые расширения, но в целом всё работает. Прикольно, теперь не надо распаковывать всякий раз когда хочется какой нибудь ROM запустить.

#6
(Правка: 8:57) 8:54, 2 июня 2019

=A=L=X=

> system( cmd )
Ойфу, это 10 строчек на баше.

PS. И да, go github, я создал.

#7
9:58, 2 июня 2019

Ghost2
> это 10 строчек на баше

Я не умею в столь сложный баш, там же надо по массивам строк и чисел коэффициентики уменьшать/увеличивать по паттернам в имени файлов чтобы выбрать максимальные совпадения.

#8
(Правка: 10:09) 10:08, 2 июня 2019

=A=L=X=
Я джвадцать двжа года ждал подобную тулзу.
Вутренняя лень не давала накодить самому

#9
(Правка: 12:25) 12:23, 2 июня 2019

Окай, тогда вот исходник: repack7z.cpp

Он обязательно требует правки перед использованием под ваши типы архивов, поэтому экзешник даже не предлагаю.
Никаких защит от дурака, код рукожопный, лишь бы работал.
В начале файла нужно исправить путь до rar, если он где то не так лежит. Можно использовать любой другой архиватор и переписать под линупсы - для этого исправить код перед двумя вызовами system( ... ) для нужной командной строки.

Основное место требующее правки вот:

  std::vector< std::string > files1;
  //std::vector< std::string > files2;
  //std::vector< std::string > files3;
  //std::vector< std::string > files4;
  while ( (dirp = readdir( dp )) )
  {
    ...
    if ( strEndsWith( out_name, ".smc" ) )
    {
      files1.push_back( out_name );
    }
    /*
    else if ( strEndsWith( out_name, ".smd" ) )
     {
       files2.push_back( out_name );
     }
    else if ( strEndsWith( out_name, ".mdx" ) )
     {
       files3.push_back( out_name );
     }
    else if ( strEndsWith( out_name, ".32x" ) )
     {
       files4.push_back( out_name );
     }
     */
     else
     {
       std::cout << "Unknown file extension met!\n";
       ret = false;
       break;
     };
  };
  ...
  proc( files1, orig );
  //proc( files2, orig );
  //proc( files3, orig );
  //proc( files4, orig );

Сейчас оно заточено под обработку архива GoodSNES - ромпак для SNES где присутствует только одно расширение файлов - smc.
Для Sega Mega Drive нужно раскомментировать все строки с files2...4 - инициализацию в начале, сравнение с одним из возможных расширений (первое было bin) и отправка в обрабатывающую процедуру proc.
В архиве GB/GBC это было два расширения - gb и gbc.
Важно, что анализатор анализирует разные расширения как разные наборы файлов! Если хотите чтобы считалось за одно и то же - нужно добавлять в один и тот же массив files.

Если результат работы алгоритма вдруг не нравится, то можно его кастомизировать.
Первое что делает алгоритм - что если файл в архиве и с заданном расширении получается всего один, то он его безусловно перепаковывает как единственно возможный истинный вариант. Тут без вариантов.
А сердце тьмы заключено в следующих строках:

          std::vector< int > ratings;
          ratings.resize( files.size() );
    for ( int i = 0; i < files.size(); i++ )
    {
      int r = 0;
      if ( files[ i ].find( "[!]" ) != std::string::npos )
        r += 2;
      if ( files[ i ].find( "(U)" ) != std::string::npos )
        r += 2;
      if ( files[ i ].find( "(UE)" ) != std::string::npos )
        r += 2;
      if ( files[ i ].find( "(E)" ) != std::string::npos )
        r += 1;
      if ( files[ i ].find( orig ) != std::string::npos )
        r += 1;
      ratings[ i ] = r;
    };
    if ( try_to_apply( files, ratings, canErase ) )
      return;
    // else try to
    for ( int i = 0; i < files.size(); i++ )
    {
      int r = ratings[ i ];
      if ( files[ i ].find( "[a" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[b" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[B" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[t" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[T" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[o" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[h" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[p" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "[f" ) != std::string::npos )
        r--;
      if ( files[ i ].find( "V1.1" ) != std::string::npos )
        r++;
      ratings[ i ] = r;
    };
    try_to_apply( files, ratings, canErase, true );

Что тут происходит - сперва файлам в архиве выставляются рейтинги - рейтинги повышаются на 2 если в имени архива есть [ ! ], ( U ) или ( UE ) - причём каждое совпадение увеличивает на 2. И на 1 если есть ( E ). Если только один из файлов при этом выбился вперёд (и в двух третях случаев на этом всё и кончается), то он считается победителем.
Но если сразу несколько файлов получили одинаковый рейтинг, то проводится второй раунд - понижаются на 1 рейтинги файлов содержащие в себе типичные признаки хаков, модов и посторонних версий, зато повышается при признаке версии V1.1 и после этого распаковываются все файлы (последний параметр true у try_to_apply - forceExtract) получившие максимальный рейтинг.

Так что если посчитаете интересными какие то дополнительные аналитики и практики, то приветствую их публикацию в этой же теме.

#10
12:28, 2 июня 2019

Что интересно - суммарный размер ромпаков после процедуры только увеличивается процентов на 10 - видимо потому что многократные повторения ромов внутри одного архива прекрасно сжимаются опираясь на уже сжатые данные, а ведь действительно перехаченые ромы отличаются как правило несколькими байтами, так что практически не несут нагрузки. Ну и просто 7zip лучше сжимает, чем старенький zip. Так что и архивов станет больше и их размер станет больше, но зато всё это будет 1rom = 1zip.

#11
(Правка: 18:51) 18:48, 2 июня 2019

=A=L=X=
Пасиб! Забилдил :)

+ Если кто будет собирать на gcc
#12
19:10, 2 июня 2019

Pathetic Mike
> ему видите ли нужно <cstdlib>

Хм, по идее так и должно быть - если юзаешь cstdlib, то std::system, а если stdlib.h, то просто system. Даже не знаю почему мой mingw32 проглотил.

#13
15:10, 3 июня 2019

=A=L=X=
Самое интересное, что дома у меня не проглотило, а на работе - еще как проглотило. Мало того, на cstdlib  даже ругалось!
Хотя 2 идентчиные установки gcc.

крестопроблемы.....
#14
16:00, 3 июня 2019

Pathetic Mike
> Ну и С++11 нужно в настройках компилятора выставить.
  Шёл 2019-й год...

Страницы: 1 2 Следующая »
ФлеймФорумПрограммирование