dsp8195 Posted May 28, 2007 Report Posted May 28, 2007 (edited) Насколько мне известно, до нас доходят либо версии, "адаптированные" для США, либо пиратские рипы (что, в принципе, одно и тоже). Разумеется, русского языка в них не наблюдается. Потому я и работал над программой AnimED, чтобы стало возможным самостоятельно перевести тексты и графику в меню и задниках (это, собственно, и есть "аниме-моддинг в чистом виде". Сомневаюсь, что у нас кто-то захочет переозвучить или перерисовать персонажей, ибо это испортит стиль и атмосферу). Вполне возможно, что кто-то уже сделал утилиты для вскрытия (у "Триады" они точно были, т.к. я встречал переведённую графику в их релизах). Но, сделать нечто подобное самостоятельно, да ещё и получить бесценную экспу в кодинге... Поэтому, кто сказал, что моддинг необходим только хитам вроде The Elder Scrolls IV? И "маленькие" игры заслуживают внимания (особенно если в них подчас заложено столько юмора и жизнерадостности, сколько нет ни в какой GTA). Эта тема создана очень давно (первая тема и первое сообщение вашего покорного слуги на анимефорум.ру), но не использовалась по прямому назначению (поэтому не обращайте внимания на два последующих ответа - они более не имеют логической связи с содержимым темы). Поскольку сейчас объём реверз-инженируемого кода более не органичивается одними только архивами визуалок, рекомендую вести дискуссию по вскрываемым форматам именно здесь. Тем более, что есть повод. ;) Edited February 2, 2008 by WinKi-тян (see edit history) Quote
u-jinn Posted May 29, 2007 Report Posted May 29, 2007 Эмм.. Если поставить прогу, будет русский перевод? Или он не входит в архив? Quote
JaveLiner Posted May 29, 2007 Report Posted May 29, 2007 Что-то мне подсказывает, что это дохлый номер. Quote
dsp8195 Posted February 2, 2008 Author Report Posted February 2, 2008 Serke, несколько минут назад я получил исходники кода анпакера графики в формате GGP, который наповерку оказался шифрованным по ксор-ключу PNG. //It's compressed, but not that difficult. Just a masked PNG. //The structure as follows: (don't care about the member names!) typedef unsigned long UInt32; // 32-bit unsigned integer typedef unsigned short UInt16; // 16-bit unsigned integer struct GGP { char sig[8] = "GGPFAIKE"; // master string UInt32 depth; // 0:use image's value / 32:ARGB / 24:RGB char xor[8]; // sub string UInt32 offset, length; UInt32 regionOffset, regionLength; char ggxRegion[regionLength]; char data[length]; // masked PNG image }; struct GGxRegion { UInt16 destLeft, destTop; // destination position UInt16 left, top, width, height; // source bounds }; //The data can be unmasked using xor-ing (GGP.sig xor GGP.xor) (confusing!) //so an unoptimized code would be: for(i = 0; i < length; i++) data[i] ^= sig[i % 8] ^ xor[i % 8]; //ggxRegion is used for overlay images of the message window and the like. Quote
Solanacean Posted February 19, 2008 Report Posted February 19, 2008 (edited) Поскольку депресняк пока не думает отступать, а время идет, решил кинуть код анпакера GGD в таком виде, в каком он есть. Он полностью работоспособен, не хватает разве что комментариев и кода проверки GGD-файлов по идентификатору. #include <stdio.h> #include <windows.h> int ExtractGGD( HANDLE hFile, BYTE *pDst, DWORD Size ); int BufferizedRead( HANDLE hFile, BYTE *lpBuf, DWORD NumOfBytesToRead, BOOL IsInit ); int main( int argc, char **argv) { struct t_GGDHeader { BYTE id[4]; WORD width; WORD height; } GGDHeader; char szoutf[ MAX_PATH ]; HANDLE hFile, hOutf; DWORD BytesRead, BytesWritten, DataLen; BYTE *pGGDData; printf( "IKURA GGD images extractor 0.01\n" ); printf( "Extraction code is a courtesy of IKURA;-)\n" ); if( argc > 1 ) { hFile = CreateFile( argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile != INVALID_HANDLE_VALUE ) { ReadFile( hFile, &GGDHeader, sizeof( GGDHeader ), &BytesRead, NULL ); DataLen = ( ( ( GGDHeader.width * 3 + 3 ) >> 2 ) << 2 ) * GGDHeader.height; pGGDData = (BYTE *)malloc( DataLen ); ExtractGGD( hFile, pGGDData, DataLen ); wsprintf( szoutf, "%s%s", argv[1], ".unpacked" ); hOutf = CreateFile( szoutf, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); WriteFile( hOutf, pGGDData, DataLen, &BytesWritten, NULL ); free( pGGDData ); CloseHandle( hOutf ); CloseHandle( hFile ); } else printf( "Cannot open file %s\n", argv[1] ); } else printf( "Usage: unpack_ggd filename<.ggd>\n" ); return 0; } ////////////////////////////////////////////////////////////////////////////// // Глобальные переменные, используемые ф-ей BufferizedRead // struct t_cyc_buf { BYTE array1[0x800]; BYTE array2[0x800]; } cyc_buf; DWORD DataBlockLen; BYTE *pDataBlockCurrByte; BOOL IsLastBlock; int ExtractGGD( HANDLE hFile, BYTE *pDst, DWORD Size ) { BYTE *pDstEnd, *pSrc; BYTE ctrlb; BYTE buf[8]; int i; BufferizedRead( NULL, NULL, 0, TRUE ); // инициализация глобальных переменных используемых ф-ей BufferizedRead() pDstEnd = Size + pDst; while( pDst < pDstEnd ) { if( BufferizedRead( hFile, &ctrlb, 1, FALSE ) == -1 ) return 1; switch( ctrlb ) { case 0: if( BufferizedRead( hFile, buf, 1, FALSE ) == -1 ) return 1; buf[1] = *( pDst - 3 ); buf[2] = *( pDst - 2 ); buf[3] = *( pDst - 1 ); for( i = 0; i < buf[0]; i++ ) { *pDst++ = buf[1]; *pDst++ = buf[2]; *pDst++ = buf[3]; } break; case 1: if( BufferizedRead( hFile, buf, 2, FALSE ) == -1 ) return 1; pSrc = pDst - ( buf[1] * 3 ); for( i = 0; i < buf[0] * 3; i++ ) *pDst++ = *pSrc++; break; case 2: if( BufferizedRead( hFile, buf, 3, FALSE ) == -1 ) return 1; pSrc = pDst - MAKEWORD( buf[1], buf[2] ) * 3; for( i = 0; i < buf[0] * 3; i++ ) *pDst++ = *pSrc++; break; case 3: if( BufferizedRead( hFile, buf, 1, FALSE ) == -1 ) return 1; pSrc = pDst - ( buf[0] * 3 ); *pDst++ = *pSrc++; *pDst++ = *pSrc++; *pDst++ = *pSrc; break; case 4: if( BufferizedRead( hFile, buf, 2, FALSE ) == -1 ) return 1; pSrc = pDst - MAKEWORD( buf[0], buf[1] ) * 3; *pDst++ = *pSrc++; *pDst++ = *pSrc++; *pDst++ = *pSrc; break; default: for( i = 0; i < ctrlb - 4; i++ ) { if( BufferizedRead( hFile, buf, 3, FALSE ) == -1 ) return 1; *pDst++ = buf[0]; *pDst++ = buf[1]; *pDst++ = buf[2]; } break; } } return 1; } int BufferizedRead( HANDLE hFile, BYTE *lpBuf, DWORD NumOfBytesToRead, BOOL IsInit ) { int i; void *pTemp; DWORD BytesRead; if( IsInit ) { pDataBlockCurrByte = NULL; DataBlockLen = 0; IsLastBlock = FALSE; return 0; } if( pDataBlockCurrByte == NULL ) { ReadFile( hFile, cyc_buf.array1, 0x1000, &DataBlockLen, NULL ); if( DataBlockLen < 0 ) return -1; pDataBlockCurrByte = cyc_buf.array1; if( DataBlockLen < 0x1000 ) IsLastBlock = TRUE; } if( (DataBlockLen <= 0) || (DataBlockLen < NumOfBytesToRead) ) return -1; for( i = 0; i < NumOfBytesToRead; i++ ) { lpBuf[ i ] = *pDataBlockCurrByte++; DataBlockLen--; if( pDataBlockCurrByte > &cyc_buf.array2[0x7FF] ) pDataBlockCurrByte = cyc_buf.array1; } if( (DataBlockLen >= 0x800) || IsLastBlock ) return NumOfBytesToRead; pTemp = cyc_buf.array1; if( pDataBlockCurrByte < cyc_buf.array2 ) pTemp = cyc_buf.array2; ReadFile( hFile, pTemp, 0x800, &BytesRead, NULL ); if( BytesRead >= 0 ) { if( BytesRead < 0x800 ) IsLastBlock = TRUE; DataBlockLen += BytesRead; return NumOfBytesToRead; } IsLastBlock = TRUE; return NumOfBytesToRead; } Идентификатор id в GGDHeader это строка (НЕ оканчивающаяся нулем) зашифрованная по методу NOT (или XOR 0xFF, если так больше нравится). Может иметь значения 'FULL', 'HIGH', '256G' и возможно, какие-то еще. Если будешь писать конвертер графики, выложу соответствующую информацию. Функция буферизованого чтения (BufferizedRead) вытащена исключительно из любви к искусству. Тебе она, по большому гамбургскому счету, нафиг не нужна - проще прочитать один раз весь файл в память, а затем 'скармливать' его функции распаковки по кусочкам, как это делает анпакер GG2. Вопросы сюда. >__< EDIT: слегка подправил код. Edited February 19, 2008 by Serke (see edit history) Quote
dsp8195 Posted February 19, 2008 Author Report Posted February 19, 2008 (edited) Спасибо! -_- Правда... теперь депресняк у меня... если сейчас прикоснусь к Дельфи, заброшу перевод. FULL - видимо, 24-битные.HIGH - 16-и.256G - 256-цветные с палитрой. Edited February 19, 2008 by WinKi-тян (see edit history) Quote
Solanacean Posted March 11, 2008 Report Posted March 11, 2008 (edited) WinKi, ты когда-нибудь с NScripter'ом работал? У меня проблема - экзешник из скачанного архива с последней версией NScripter'а отказывается работать с игрой на базе более старой версии движка, выдавая в качестве объяснения какой-то мунспик =). Собственно, меня интересует, нужно ли каким-то образом обрабатывать взятые "из коробки" экзешники движков онскриптера и энскриптера напильником для каждой конкретной игры. P.S. NScripter "внутри" просто кошмарен. Код настолько уродлив, что им можно детей пугать... Edited March 11, 2008 by Serke (see edit history) Quote
dsp8195 Posted March 11, 2008 Author Report Posted March 11, 2008 nScripter устарел (и пользоваться им не стоит, даже переключив язык системы для не-Unicode программ на японский - код там действительно ужасен). OnScripter - иной разговор. Доводить EXE до нужной кондиции, как правило, не требуется (только русский он, зараза, всё равно не держит - для этого был придуман POnScripter (скину ссылку на мой экземпляр исходников в личку - они, кхм, неофициальные) ). Однако, об этом уже говорили на Gemot'е: существует так называемый "прародитель" - Scripter3 (или как там его). В общем, не совместим он с асм-подобным языком nScripter'а. ;); Quote
Solanacean Posted March 11, 2008 Report Posted March 11, 2008 WinKi, наверное, мне нужно было объяснить мою задачу. Я ищу способ хакнуть движок NScripter'а так, чтобы он воспринимал однобайтовые символы и производил text wrapping, также пытаюсь заставить его работать с шрифтом, символы в котором переменной, не фиксированной ширины. Отсутствие поддержки русского языка меня волнует в последнюю очередь. NScripter никак не может быть отсталым по сравнению с ONScripter'ом, потому что он есть модель для этого самого ONScripter'а - сначала нововведения появляются в NScripter'е, потом с большим опозданием они перекочевывают в ONScripter. Собственно говоря, причиной, по которой я вынужден ковырять NScripter является отсутствие поддержки многих функций, используемых игрой, текущей версией ONScripter'а. [url="http://www.baka-tsuki.net/project/index.php?title=Talk:Umineko_no_Naku_Koro_ni" target="_blank" rel="nofollow">http://www.baka-tsuki.net/project/index.ph...no_Naku_Koro_ni[/url] Поскольку Umineko no Naku Koro ni у меня пока нет, я сперва решил "потренироваться" на экзешнике Higurashi no Naku Koro ni, потом сообразил, что поскольку Umineko использует NScripter более новой версии, имеет смысл ковырять экзешник самой последней версии движка. Проблема в том, что экзешник последней версии почему-то отказывается работать с Higurashi, ругаясь на какое-то место в скрипте. код там действительно ужасенЯ имел в виду бинарный код самого движка, не скриптовый язык =). И еще такой вопрос... В коде движка есть обработка управляющего символа '#', который, как я понимаю, задает цвет текста. Код цвета задается в шестнадцатиричной форме сразу после этого символа (напр. так: #fffff). Движок преобразует этот код из символьной в бинарную форму, затем производит над полученным числом странные манипуляции. Например, такие (color_code - полученный из скрипта код цвета): dword_5DC3F0 = color_code / 65536; v89 = color_code & 0x8000FFFF; if ( v89 < 0 ) v89 = ( ( v89 - 1 ) | 0xFFFF0000 ) + 1; v90 = v89 / 256; v91 = v89 & 0x800000FF; dword_5DC3E8 = v90; if ( v91 < 0 ) v91 = ( ( v91 - 1 ) | 0xFFFFFF00 ) + 1; dword_5DC3E0 = v91; v1 = some_array[ 256 * dword_5DC3F0 ]; v2 = some_array[ 256 * v90 ]; v3 = some_array[ 256 * v91 ]; Есть идея, что это может означать? =) Конкретно интересует, что из себя представляют глобальные переменные dword_XXXXXX и что из себя представляет массив some_array. Quote
dsp8195 Posted March 11, 2008 Author Report Posted March 11, 2008 (edited) Я ищу способ хакнуть движок NScripter'а так, чтобы он воспринимал однобайтовые символы и производил text wrapping, также пытаюсь заставить его работать с шрифтом, символы в котором переменной, не фиксированной ширины.Документацию POnScripter'а прочитай... :);; Всё вышеперечисленное + смена TypeFace шрифта на лету!Я имел в виду бинарный код самого движка, не скриптовый язык =)....это и имелось ввиду. >_<Есть идея, что это может означать? =) Конкретно интересует, что из себя представляют глобальные переменные dword_XXXXXX и что из себя представляет массив some_array. dword_5DC3F0 = color_code / 65536; //Тоже самое, что (R+G+B) div 3. Получается пиксель в оттенках серого. v89 = color_code & 0x8000FFFF; // Убивает каналы A и R (присваивает им нули), а в v89 получается G и B. Код, мягко говоря, извращённый. if ( v89 < 0 ) // меньше нуля? хм... всё верно - цвет может записываться и как отрицательное число (TColor в Delphi) v89 = ( ( v89 - 1 ) | 0xFFFF0000 ) + 1; // вот это я вообще не понял... негатив A R ... только в чём смысл? O_o v90 = v89 / 256; // Ну, тут ясно -- получение оттенка серого из G и B v91 = v89 & 0x800000FF; // получается серый пиксель (т.е. канал B, просто отделённый от изображения) dword_5DC3E8 = v90; // это даже комментировать не стоит if ( v91 < 0 ) //и это v91 = ( ( v91 - 1 ) | 0xFFFFFF00 ) + 1; // по идее, получается 0 dword_5DC3E0 = v91; v1 = some_array[ 256 * dword_5DC3F0 ]; v2 = some_array[ 256 * v90 ]; v3 = some_array[ 256 * v91 ]; // Кхм.... такого дикого и абсолютно бесполезного преобразования цветов я ещё не видел... если честно, не могу вкурить, зачем ЭТО нужно... :-PПроблема в том, что экзешник последней версии почему-то отказывается работать с Higurashi, ругаясь на какое-то место в скрипте.Не повезло. Эта игра использует модифицированную версию движка (просто моё предположение, но скорее всего так оно и есть). Edited March 11, 2008 by WinKi-тян (see edit history) Quote
Solanacean Posted March 11, 2008 Report Posted March 11, 2008 (edited) WinKi, ты надо мной издеваешься что-ли? :) . Я не сомневаюсь в том, что опенсорсный ONScripter и его ветки поддерживают весь набор трутайп шрифтов, юникод и прочее. Проблема в том, что он не поддерживает ряд графических эффектов последних версий NScripter'а, а значит перевести на него игры, использующие этот набор (вроде вышеупомянутой Umineko...) нельзя. Неужели ты думаешь, что я от нечего делать ковыряюсь в этой помойке? ;) ...это и имелось ввиду. >_<Т.е. ты тоже дизасмил экзешник NScripter'а? :D За комментарии к листингу - большое спасибо :) . Edited March 11, 2008 by Serke (see edit history) Quote
dsp8195 Posted March 11, 2008 Author Report Posted March 11, 2008 (edited) он не поддерживает ряд графических эффектов последних версий NScripter'а, а значит перевести на него игры, использующие этот набор (вроде вышеупомянутой Umineko...) нельзя.Нельзя так нельзя. Надо было сказать сразу. :) Edited March 11, 2008 by WinKi-тян (see edit history) Quote
Solanacean Posted March 11, 2008 Report Posted March 11, 2008 Нет графических эффектов? Каких интересно? Чего-то вроде "oldmovie" или "sunblick"?Не знаю. Игры у меня пока нет. Если их отстутствие не испортит игру, то закомментировать проблемные участки скрипта и вперёд!"Это не наш метод" ©. Можно вообще дать страждущим скрипт (в виде текстового файла), выдранный набор картинок и указания, где какой mp3 файл включать в винампе =). Ключевое слово здесь - экспириенс и он должен быть если не аутентичным, то хотя бы максимально приближаться к таковому. Мои пять центов. А если нужны как воздух - обращаться прямо к Peter'у. Мы с Mion'ом добавили поддержку locale.utf, может и тебе повезёт.Сомневаюсь. Затраты времени на поддержку локали и эмуляцию (или, скорее, симуляцию) граф. эффектов несравнимы. или сделать копи-паст декомпилированного кодаКопи-паст сделать не получится, но идея мне нравится. Попробую. Кстати, в ONScripter'е мне категорически не нравится то, что он использует для проигрывания OGG и MP3 библиотеку sdl_mixer. Не радует ни качество звука, ни лаги в проигрывании пожатого аудио, выражающиеся в появлении щелчков и потрескиваний. Quote
dsp8195 Posted March 11, 2008 Author Report Posted March 11, 2008 Кстати, в ONScripter'е мне категорически не нравится то, что он использует для проигрывания OGG и MP3 библиотеку sdl_mixer. Не радует ни качество звука, ни лаги в проигрывании пожатого аудио, выражающиеся в появлении щелчков и потрескиваний.Вот и повод опробовать BASS. ;) Quote
Solanacean Posted March 11, 2008 Report Posted March 11, 2008 WinKi, я нашел еще более крутую библиотеку - . Очень внушительный поддерживаемых платформ, очень внушительный список поддерживаемых форматов и библиотеку используют очень внушительные компании, такие как Blizzard. Цена тоже очень и очень внушительна, но для некоммерческого использования библиотека бесплатна. По отзывам тех, кто пользовался и BASS и FMOD, последняя гораздо лучше первой. И качество звука великолепно и скорость работы выше всяческих похвал. Quote
Solanacean Posted March 13, 2008 Report Posted March 13, 2008 (edited) Какая жалость, что OllyDbg не поддерживает удаленную отладку через TCP/IP - фичу, при ковырянии новелл и вообще любых графических аппликаций, совершенно незаменимую. Отладчик IDA Pro ее поддерживает, но он a) тормозной и б) неудобный (ИМХО) и наконец, в) в "японифицированных" виндах не отображаются регистры. ;) WinKi, ты на уровне WinAPI, или вернее, GDI32 API, с графикой работал? Edited March 13, 2008 by Serke (see edit history) Quote
dsp8195 Posted March 13, 2008 Author Report Posted March 13, 2008 (edited) WinKi, ты на уровне WinAPI, или вернее, GDI32 API, с графикой работал?Нет пока... -_- Насчёт регистров... шрифт в самом отладчике поменять пытался? Или (изврат конечно, и вряд ли бы сработало, но) запускать отладчик на японизированной винде через AppLocale? Edited March 13, 2008 by WinKi-тян (see edit history) Quote
Solanacean Posted March 14, 2008 Report Posted March 14, 2008 (edited) Я крупно стормозил. Настолько крупно, что даже неудобно в этом признаваться. Японский для неюникодных приложений должен быть установлен на машине-сервере, на которой выполняется программа. На машине-клиенте же (т.е. на компьютере, с которого и происходит весь процесс управления отладкой) может быть установлен хоть суахили. Еще возникло несколько вопросов. Во-первых, ф-ей setwindow задается в том числе и размер шрифта. Вопрос: в каких единицах он задается? В коде NScripter'а есть такой участок: if ( WriteVertical == TRUE ) { //... } else { font_cx = 3 * font_width / 2; font_cy = 3 * font_height; } hFont = CreateFontA( font_cy, font_cx, cOrientation, cOrientation, v19, 0, 0, 0, SHIFTJIS_CHARSET, 0, 0, 0, 1, &pszFaceName ); font_cy и font_cx - размеры шрифта в логических единицах (logical units). font_width и font_height - параметры, переданные команде setwindow.Как видно из вышеприведенного листинга, реальный размер шрифта отличается от заданного ф-ей setwindow. Есть подозрение, что выводимые на экран символы шрифта размера width = font_cx, height = font_cy рендерятся движком в квадратную битмапку размерностью width = font_width, height = font_height (посимвольно), затем каждый символ копируется на экран API-функцией BitBlt (растровая операция SRCCOPY). Ты не мог бы взглянуть в исходники ONScripter'а и подтвердить/опровергнуть это? И еще один вопрос: что представляет из себя поставляемый с бинарниками онскриптера шрифт default.ttf? Он вообще фиксированной или переменной ширины? =) UPD: Можешь объяснить принцип работы ф-и locate? (той, которая "changes the position of characters without changing the position of the text window") Она только на строку, следующую непосредственно за ней оказывает эффект или вообще на весь выводимый текст? Вообще, хотелось бы заиметь хоть какой-нибудь мануал по командам/функциям ONScripter'а. Смог найти только перечень с кратким описанием на сайте Haeleth. Кстати, и этот перечень неплохо было бы иметь в виде CHM-файла или хотя бы HTMLок... Edited March 15, 2008 by Serke (see edit history) Quote
апкиш Posted March 15, 2008 Report Posted March 15, 2008 товарищи!! я это хотеть!!!!!знаю ассемблер, есть опыт вскрытия коммерческих продуктов на предмет регистрации.вскрывал при помощи оллидебагера и softice'алюблю хигурашу.просто скажите что откуда качать и что нужно выдрать из этого скаченного, я с радостью попытаюсь это сделать Quote
Solanacean Posted March 16, 2008 Report Posted March 16, 2008 (edited) Тут, в общем, опыт вскрытия ПО мало пригодится, нужны опыт реверсинга, опыт работы с IDA Pro (как дизассемблером, так и отладчиком) и знание GDI32 API... Речь, кстати, идет не о хигураши, а о новой игре от создателей Higurashi (студии 07 Expansion) - Umineko no Naku Koro ni. Игры у меня на данный момент нет, пока она идет ко мне по почте, я набиваю руку, ковыряя Higurashi no Naku Koro ni (она на базе того же движка, что и Umineko..., только более старой версии). Higurashi..., иначе как в обучающих целях, ковырять нет смысла, так как ее скрипт совместим с последними версиями ONScripter'а - опенсорсного аналога популярного движка NScripter, на котором бегают все игры от 07 Expansion (и куча других игр). А вот скрипт Umineko... содержит ряд команд, отсутствующих в ONScripter'е, поэтому выхода два: "учить" NScripter работать с английским текстом или "научить" ONScripter этим новым командам. Мне ближе первый вариант :) Edited March 16, 2008 by Serke (see edit history) Quote
dsp8195 Posted March 16, 2008 Author Report Posted March 16, 2008 И еще один вопрос: что представляет из себя поставляемый с бинарниками онскриптера шрифт default.ttf? Он вообще фиксированной или переменной ширины? =)Фиксированной. И в этом главный бич nScripter'а и OnScripter'а (поэтому я и дал исходники POnScripter'а). Вообще, хотелось бы заиметь хоть какой-нибудь мануал по командам/функциям ONScripter'а. Смог найти только перечень с кратким описанием на сайте Haeleth. Кстати, и этот перечень неплохо было бы иметь в виде CHM-файла или хотя бы HTMLок... Держи: Quote
Solanacean Posted March 16, 2008 Report Posted March 16, 2008 (edited) Фиксированной. И в этом главный бич nScripter'а и OnScripter'а (поэтому я и дал исходники POnScripter'а).Этот "главный бич" сильно упрощает задачу... Пришел к неутешительному для себя выводу, что для того, чтобы полноценно хакнуть этот ужас, потребуется как минимум месяц работы. И это только для того, чтобы заставить движок понимать ASCII-строки. Код парсинга строк в NScripter'е размазан тоненьким слоем по всему движку. В общем, этим путем я решил не идти. =) Английский текст, как и японский, будет в Shift-JIS, врезать в движок код, осуществляющий преобразование символов из Shift-JIS в ASCII перед выводом их на экран, думаю, будет несложно. Есть и другая, совершенно фантастическая по степени извращенности идея - врезать в код движка свой парсер. Английский текст будет, как ему и полагается, в ASCII, при загрузке скрипта, после его декодирования, управление получит мой парсер, который строку за строкой просмотрит весь скрипт и заменит предваренный символом '`' ASCII-текст на аналогичный текст в Shift-JIS... Большое спасибо за списочек команд. :) Edited March 16, 2008 by Serke (see edit history) Quote
dsp8195 Posted March 16, 2008 Author Report Posted March 16, 2008 (edited) Большое спасибо за списочек команд.Ммм... в дистрибутиве nScripter'а есть и более свежий ( [url="http://www.nscripter.com/nscr.lzh" target="_blank" rel="nofollow">http://www.nscripter.com/nscr.lzh[/url] ). На японском, но это лечится Atlas'ом... Edited March 16, 2008 by WinKi-тян (see edit history) Quote
Zakonnic Posted March 17, 2008 Report Posted March 17, 2008 Ребят, извините что вмешиваюсь, но просмотрел тему и нифига не понял, о чем вы говорите. Я, конечно, глобально не в курсе, т.к. даже не знаю, что из себя все эти игры представляют... но родилось все же пару мыслей. И по такому случаю, не расскажете ли в трех словах, что конкретно требуется сделать? Пока я понял, что надо заставить яп. прогу понимать анг., рус. и др. Это не то случаем? -> СпойлерЕсли под автором имеется ввиду непосредственный автор программы, то ему нужно просто в функции CreateFont() использовать нужный параметр, определяющий Charset. А если вы хотите исправить уже откомпилированный файл, то нужно найти место в программе, где вызывается функция CreateFont(), и подредактировать место, где определяются параметры для этой функции. Для этого лучше использовать дизассемблер и шестнацетиричный редактор. Дело в том, что у функции CreateFont очень много параметров, и для втоматического исправления кода нужен достаточно надежный анализатор этого кода. На создание такого анализатора вы потратите уйму времени, а на анализ кода при помощи дизассемлера требуется от силы полчасика. Итак, приступим к изучению программы. 1. Если программа упакована каким либо пакером, то нужно её распаковать, вернее - это уже отдельная тема (взлом упакованой программы). А если нет, как в случае с антиспаем, то переходим к следующему шагу. 2. Нужно найти библиотеки импорта. Для этого можно использовать depends.exe от microsotf. Эта программа показывает все библиотеки и импортируемые программой функции из этих библиотек (в упакованном виде весит примерно 380 Кб, могу выслать). Нас интересует библиотека GDI32.DLL и функция CreateFont(). 3. Теперь о функциях API создания шрифта. Это могут быть CreateFontA() / CreateFontW() CreateFontIndirectA() / CreateFontIndirectW() CreateFontIndirectExA() / CreateFontIndirectExW() Поясню: CreateFontA() и CreateFontW() это разные реализации одной и той же функции, т.е. они выполняют одну и ту же работу, только отличаются типом параметров. CreateFontA() в качестве строкового параметра принимает ANSI строки, а CreateFontW() - строки в Юникоде. С остальными функциями - так же. У функции CreateFont() очень много параметров-14, а все остальные принимают только указатель на структуру, в которой уже собраны все эти парамеры.С антиспаем - используется CreateFontA(). 4. Теперь про CreateFontA(). BOOL CreateFont(int nHeight, // определяет высоту шрифта в логических единицах int nWidth, // определяет ширину шрифта, (обычно равен 0,ширина по умолчанию) int nEscapement, // наклон в десятых градуса базовой линии текста (обычно 0) int nOrientation, // наклон в десятых градуса базовой линии символа (обычно 0) int nWeight, // вес символа (жирность) (обычно 400) BYTE bItalic, // курсив (обычно 0) BYTE bUnderline, // подчеркивание (обычно 0) BYTE cStrikeOut, // зачеркивание (обычно 0) BYTE nCharSet, // определяет национальность шрифта (то что нам нужно) BYTE nOutPrecision, // без комментариев (можно 0) BYTE nClipPrecision, // без комментариев (можно 0) BYTE nQuality, // без комментариев (можно 0) BYTE nPitchAndFamily, // без комментариев (можно 0) LPCTSTR lpszFacename);// название шрифра (например "Arial") 5. Нашли нужную функцию в импорте - теперь нужно найти место в программе, где она вызывается, проанализировать её парамеры, и попытаться исправить nCharSet. Здесь нужен какой либо дизассемблер. В антиспае - nCharSet равен 0, что соответсвует америке. А нам нужен RUSSIAN_CHARSET, его значение 204 или 0CCh. Как исправить? Для передачи параметров функции используется стек, первым с стек помещается последний параметр функции (lpszFacename), последним - первый (nHeight), а затем call [адрес в таблице импорта]. Трудность исправления значений параметров заключается в том, что много нулевых параметров и оптимизатор кода при компиляции программы сделал следующим образом: обнулил какой то регистр (например ebx), а затем, когда требуется записать в стек 0, выполняется команда push ebx. Эта команда занимает только один байт. Команда push 204 занимает уже два байта, и просто так ей не вставишь (нет места). Я же сделал так: nPitchAndFamily не был нулевым, и на него тратилось два байта, я его обнулил (заменил на push ebx), а освободившийся байт использовал для nCharSet. При этом все параметры между ними сместились на один байт. Это я проделал в двух местах. Для этого нужен шестнадцатиричный редактор. И все - антиспай у меня стал показывать нормальный текст. Всего хорошего. На описание того что я сделал потребовалось больше времени, чем на сам патч. Quote
Solanacean Posted March 19, 2008 Report Posted March 19, 2008 Это не то случаем? -> СпойлерКакой "умник" это писал?! Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.