1. Друзья, в это тяжёлое и непонятное для всех нас время мы просим вас воздержаться от любых упоминаний политики на форуме, - этим ситуации не поможешь, а только возникнут ненужные ссоры и обиды. Это касается также шуток и юмора на тему конфликта. Пусть войны будут только виртуальными, а политики решают разногласия дипломатическим путём. С уважением, администрация Old-Games.RU.

    Скрыть объявление
  2. Пожалуйста, внимательно прочитайте правила раздела.
  3. Если Вы видите это сообщение, значит, вы ещё не зарегистрировались на нашем форуме.

    Зарегистрируйтесь, если вы хотите принять участие в обсуждениях. Перед регистрацией примите к сведению:
    1. Не регистрируйтесь с никами типа asdfdadhgd, 354621 и тому подобными, не несущими смысловой нагрузки (ник должен быть читаемым!): такие пользователи будут сразу заблокированы!
    2. Не регистрируйте больше одной учётной записи. Если у вас возникли проблемы при регистрации, то вы можете воспользоваться формой обратной связи внизу страницы.
    3. Регистрируйтесь с реально существующими E-mail адресами, иначе вы не сможете завершить регистрацию.
    4. Обязательно ознакомьтесь с правилами поведения на нашем форуме, чтобы избежать дальнейших конфликтов и непонимания.
    С уважением, администрация форума Old-Games.RU
    Скрыть объявление

Кодерский уголок

Тема в разделе "Мастерская", создана пользователем Dimouse, 10 сен 2006.

  1. Dimouse King of Mice

    Dimouse

    Администратор Переводчик

    Регистрация:
    18 апр 2003
    Сообщения:
    35.151
    В соответствии с назначением раздела, в этой теме предполагается обсуждать конкретные вопросы, которые у вас возникают при создании своих программ (в частности - игр), помогать другим, размещать полезные ссылки на статьи и материалы, которые могут пригодиться другим.

    Что здесь не допускается:
    - беспорядочный флуд на всевозможные темы, в том числе общие обсуждения языков программирования без конкретики (карается по статье "флуд и оффтопик" *),
    - разжигания на темы "что лучше, Си или Си++ и чем они отличаются?", "какой язык программирования лучше X или Y?" и т.п. (карается по статье "флейм и участие в холиварах" *),
    - мерение пиписьками в стиле "я лучше программирую" или "ты не умеешь программировать" (карается по статье "оскорбление участников и их взглядов" *).

    Всё это допускается в специально созданной теме "Беседка для программистов или «Бутерброд с кодом».

    * по усмотрению модератора также возможно применение блокировки в данной теме.

    Оригинальное сообщение
     
    Последнее редактирование модератором: 24 ноя 2014
    CY8R4Y нравится это.
  2.  
  3. beha_r

    beha_r

    Хелпер

    Регистрация:
    29 янв 2009
    Сообщения:
    1.203
    Прошу помощи.
    Суть дела такова: Пишу widescreen fix для игры VTM-Bloodlines - asi модуль, подгружается через asi loader. Поскольку игра на древнем движке source, она использует тучу своих dll подгружая их функцией LoadLibraryA. У меня встала проблема: нужно пропатчить одну dll до выполнения в ней DllMain функции. Тоесть, как я понимаю, мне нужен аналог функции LoadLibraryA с возможностью выполнить свой код до вызова функции DllMain в dll. Может есть у кого пример на с++
     
  4. Рыжий Тигра Сам себе «пират»

    Рыжий Тигра

    Регистрация:
    3 май 2012
    Сообщения:
    1.823
    Увы, только в файле:
    Хуже - тут нужен свой аналог загрузчика исполняемых модулей, а это часть операционки. :-(
    А кстати, зачем патчить именно перед DllMain()'ом? Что интересного это может дать?
     
  5. beha_r

    beha_r

    Хелпер

    Регистрация:
    29 янв 2009
    Сообщения:
    1.203
    Да эта зараза из DllMain() уже добрую часть hud считает. Она еще default_fov из DllMain() инициализировала, но с ним я разобрался - подменил данные в трех местах потом. А вот с HUDом не все так красиво - там порядка 400 вызовов, возможно не все нужно трогать, но править их потом еще то извращение.
     
    Последнее редактирование: 18 дек 2014
  6. Рыжий Тигра Сам себе «пират»

    Рыжий Тигра

    Регистрация:
    3 май 2012
    Сообщения:
    1.823
    beha_r, понятно. :-(
    Увы, способов разделить загрузку .dll'ы и выполнение DllMain()'а (так, чтобы получить управление в промежутке между ними) мне не известно.

    ---------- Сообщение добавлено в 06:15 ---------- Предыдущее сообщение размещено в 06:07 ----------

    Ёпс, сунулся в google( загрузка dll без dllmain ) - получил: http://forum.vingrad.ru/forum/topic-284117/view-all.html - люди пишут, что LoadLibraryEx( ..., ..., DONT_RESOLVE_DLL_REFERENCES ) делает именно то что нам надо: грузит, но DllMain() не вызывает.
    Осталась фигня - выяснить, чем вызвать DllMain() после того как всё что надо пропатчишь.

    ---------- Сообщение добавлено в 06:30 ---------- Предыдущее сообщение размещено в 06:15 ----------

    google( loadlibraryex DONT_RESOLVE_DLL_REFERENCES ):
    http://blogs.msdn.com/b/oldnewthing/archive/2005/02/14/372266.aspx !!!
    http://www.transl-gunsmoker.ru/2010/02/loadlibraryexdontresolvedllreferences.html - перевод
    А вот это http://www.experts-exchange.com/Programming/Editors_IDEs/Q_23277732.html м.б. и сгодится - идею я примерно уловил, но пробовать не пробовал.

    ---------- Сообщение добавлено в 06:34 ---------- Предыдущее сообщение размещено в 06:30 ----------



    ---------- Сообщение добавлено в 06:59 ---------- Предыдущее сообщение размещено в 06:34 ----------

    И ещё немного библиотечного трюкачества нарыл:
    http://mognovse.ru/tct-dll-bolee-slojnie-metodi-programmirovaniya.html
     
    Последнее редактирование модератором: 18 дек 2014
  7. daemolisher

    daemolisher

    Регистрация:
    2 дек 2009
    Сообщения:
    1.704
    а dll-ку точно надо потрошить?

    наверно fov где-то сохранён должен быть - скорей всего из ini-файла читается (начиная с какой-то версии движка Source в настройках графики появился ползунок fov, так что где-то это настройка уж точно сохраняется)

    или в файл autoexec добавить команду fov 110, например




    вот по ссылкам есть некий widescreen fix:

    http://www.wsgf.org/dr/vampire-masquerade-bloodlines
    http://www.wsgf.org/forums/viewtopic.php?f=61&t=14990

    - но он только разрешение меняет, естественно HUD выглядит от этого не очень - растянуто

    опять же предлагают править engine.dll

    неужели разрешения прямо так захардкодили в игре?
    неверится, что так глупо
    ладно если бы были 90-е, но игра вполне современная, вполне могли бы написать поддержку любых разрешений.



    мне вот подумалось:
    а Steam никак не отслеживает патч dll?
    не забанит за это?




     
  8. beha_r

    beha_r

    Хелпер

    Регистрация:
    29 янв 2009
    Сообщения:
    1.203
    Точно надо. У этой игры версия движка ниже чем у утекшей альфы half-life 2. Поэтому многих наворотов движка Source там еще нет.
    Запись fov 110 в autoexec ничего не даст. Это нужно вбивать в консоль игры, причем каждый раз после запуска игры.

    Знаю этот фикс.
    Разрешения я уже разблокировал. Там стояла проверка разрешений со своим списком.
    Hud как и игра заточены только под 4/3 разрешения.

    Насколько я знаю не забанят.
     
    nop и daemolisher нравится это.
  9. beha_r

    beha_r

    Хелпер

    Регистрация:
    29 янв 2009
    Сообщения:
    1.203
    И все таки я своего добился, вот куски кода:

    Код:
    typedef BOOL(WINAPI *PDLL_MAIN)(HMODULE, DWORD, PVOID);
    PDLL_MAIN pDllMain;
    
    
    HMODULE LoadLibraryNoDllMain(LPCSTR module) {
    	HINSTANCE hInstLib;
    	PIMAGE_NT_HEADERS ntHeader;
    	DWORD pDataDirImportRVA;
    	DWORD pDataDirImportSize;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
    	PCHAR ptr;
    	HANDLE handle;
    	PIMAGE_THUNK_DATA pThunkDataIn;
    	PIMAGE_THUNK_DATA pThunkDataOut;
    	DWORD dw;
    	unsigned long protect;
    
    
    
    	// Грузим DLL в память
    	hInstLib = LoadLibraryEx(module, NULL, DONT_RESOLVE_DLL_REFERENCES);
    	if (!hInstLib) {
    		WriteLog("ERROR: unable to load: %s\n", module);
    		return NULL;
    	}
    
    	// Исправляем импорт
    	ntHeader = (PIMAGE_NT_HEADERS)(PCHAR(hInstLib) + PIMAGE_DOS_HEADER(hInstLib)->e_lfanew);
    	pDataDirImportRVA = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    	pDataDirImportSize = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size;
    	if (pDataDirImportSize) {							// Если размер таблицы 0 - нет Import Table
    		pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hInstLib + pDataDirImportRVA);
    
    		for (; pImportDesc->Name; pImportDesc++) {
    			ptr = (PCHAR)((DWORD_PTR)hInstLib + pImportDesc->Name);
    			handle = GetModuleHandle(ptr);
    			if (!handle) { handle = LoadLibraryEx(ptr, NULL, NULL); }
    			if (!handle) {
    				WriteLog("ERROR: unable to load %s for: %s\n", ptr, module);
    				FreeLibrary(hInstLib);
    				return NULL;
    			}
    			if (pImportDesc->TimeDateStamp == -1) {
    				WriteLog("ERROR: New style bound import in: %s\n", module);
    				FreeLibrary(hInstLib);
    				return NULL;
    			}
    			else {
    				pThunkDataOut = (PIMAGE_THUNK_DATA)((DWORD)hInstLib + (DWORD)pImportDesc->FirstThunk);
    				if (!pImportDesc->Characteristics) { pThunkDataIn = pThunkDataOut; }
    				else { pThunkDataIn = (PIMAGE_THUNK_DATA)((DWORD)hInstLib + (DWORD)pImportDesc->Characteristics); }
    
    				while (pThunkDataIn->u1.AddressOfData) {
    					// Получаем импорт
    					if ((DWORD)pThunkDataIn->u1.Ordinal & IMAGE_ORDINAL_FLAG) {			// no name, just ordinal
    						dw = (DWORD)GetProcAddress((HMODULE)handle, MAKEINTRESOURCE(LOWORD(pThunkDataIn->u1.Ordinal)));
    					}
    					else{
    						PIMAGE_IMPORT_BY_NAME pImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)hInstLib + (DWORD)pThunkDataIn->u1.AddressOfData);
    						dw = (DWORD)GetProcAddress((HMODULE)handle, pImportByName->Name);
    					}
    
    					// Пишем импорт
    					VirtualProtect((LPVOID)pThunkDataOut, 0x4, PAGE_READWRITE, &protect);
    					pThunkDataOut->u1.Function = (DWORD)dw;
    					VirtualProtect((LPVOID)pThunkDataOut, 0x4, protect, NULL);
    
    					pThunkDataIn++;
    					pThunkDataOut++;				
    				}
    			}
    		}
    	}
    	pDllMain = (PDLL_MAIN)((LPBYTE)hInstLib + ntHeader->OptionalHeader.AddressOfEntryPoint);
    	return hInstLib;
    }
    
    
    
    HMODULE WINAPI LoadClient(LPCSTR module) {
    	HINSTANCE hInstLib = LoadLibraryNoDllMain(module);
    
    	// Здесь делаем свое грязное дело
    
    	pDllMain(hInstLib, DLL_PROCESS_ATTACH, NULL);
    	return hInstLib;
    }
    
    Из асмового куска вместо LoadLibraryA вызывается LoadClient, которая делает тоже самое плюс дает внести свои изменения до вызова DllMain().

    ЗЫ
    Поскольку это мой второй проект на с++, код скорее всего кривой, однако он работает. Буду рад если его кто-нибудь исправит или дополнит.
     
    Последнее редактирование: 20 дек 2014
  10. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    Между тем Lua выпустила уже второй релиз кандидат версии 5.3.0 и это значит, что, скорее всего, уже до НГ выйдет релиз. Для нас новый Lua хорош тем, что там наконец-то появились битовые операторы, поддержка (очень слабая) UTF8 и целые числа. Библиотека при этом по-прежнему имеет минимальные размеры и очень высокую скорость выполнения кода.
     
    Последнее редактирование: 20 дек 2014
  11. Рыжий Тигра Сам себе «пират»

    Рыжий Тигра

    Регистрация:
    3 май 2012
    Сообщения:
    1.823
    Хм. Знаешь, это ж почти чистый Си, только изгаженный С++'ным стилем оформления.
    Может, тебе лучше на Си перейти? :-)
     
  12. Steel Rat Stainless

    Steel Rat

    Регистрация:
    28 дек 2006
    Сообщения:
    3.260
    ДА!
    С++ программист:
    Код:
    if (b == true)
    {
       b = false;
    }
    else if (b == false)
    {
        b = true;
    }
    else
    {
       std::throw(MegaException());
    }
    
    С программист:
    Код:
    b = !b;
     
    AxXxB и Рыжий Тигра нравится это.
  13. beha_r

    beha_r

    Хелпер

    Регистрация:
    29 янв 2009
    Сообщения:
    1.203
    Да я как то специально Си++ не выбирал, похожие исходники просто мне на нем попались. Я до этого только на питоне писал, ну и с ассемблером игрался. Ну а тут ассемблер муторно, а питон было бы еще то извращение. А вообще надо бы посмотреть, может для меня Си будет получше чем Си++.
     
    Последнее редактирование: 20 дек 2014
    Рыжий Тигра нравится это.
  14. Рыжий Тигра Сам себе «пират»

    Рыжий Тигра

    Регистрация:
    3 май 2012
    Сообщения:
    1.823
    beha_r нравится это.
  15. Dimouse King of Mice

    Dimouse

    Администратор Переводчик

    Регистрация:
    18 апр 2003
    Сообщения:
    35.151
    Товарищ дизассемблировал Supaplex и выложил код: habrahabr.ru/post/246027
     
    binarymaster и Tigoro нравится это.
  16. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Допилил я компиляцию libsidplayfp под DOS. Однако вот беда: на медленных компах, типа 486, проигрывает безнадежно медленно, а на быстрых, типа P4 - безнадежно быстро. И вот я думаю, как решить хотя бы вторую проблему. Внутри библиотеки средств синхронизации не предусмотрено, так как синхронизация осуществляется либо через ресэмплинг в случае эмуляции SID, либо самим железом в случае HardSID. Мне ни то, ни другое не подходит, и нужно придумывать что-то самому. Кто-нибудь знает, как получать высокоточные (измеряемые в микросекундах) значения времени из-под DOS (защищенный режим)?
     
  17. Bato-San Чеширский волк-киборг

    Bato-San

    Регистрация:
    24 июн 2010
    Сообщения:
    14.136
  18. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Я тут случайно нашел какой-то экзотический вид задержки, вроде бы через контроллер дисплея:

    Код:
    sysex_wait      PROC Delay              ;Delay after System Exclusive message
                    USES ds,si,di           ;transmissions
    
                    mov ax,40h              ;wait n VBL periods (14 ms/period min,
                    mov ds,ax               ;requires CGA/EGA/VGA/XGA video)
    
                    mov dx,ds:[63h]         ;get CRTC Address register location
                    add dl,6                ;get CRTC Status register location
    
                    mov cx,[Delay]
                    jcxz __exit
    
    __sync_1:       in al,dx
                    test al,8
                    jz __sync_1
    
    __sync_2:       in al,dx
                    test al,8
                    jnz __sync_2
    
                    loop __sync_1
    
    __exit:         ret
                    ENDP
    
    Интересно, 14ms - это, наверное, 14 миллисекунд, а не микросекунд?
     
  19. Bato-San Чеширский волк-киборг

    Bato-San

    Регистрация:
    24 июн 2010
    Сообщения:
    14.136
    Geryon, Про миллисекунды и как что пишется туть.
     
  20. nop

    nop

    Регистрация:
    5 дек 2014
    Сообщения:
    2.297
    Эмм.. Я вижу явную попытку поставить телегу впереди лошади. Если у тебя аудио-плеер, то он должен быть завязан на скорость проигрывания сэмплов звуковой картой. Т.е. звуковая карта пережевывает блоки со строго заданной скоростью, по своим внутренним таймерам, и вызывает прерывания, когда обработка очередного блока окончена. Когда она их вызывает, начав воспроизведение следующего, ты генерируешь новый блок, проэмулировав для этого нужное количество тактов виртуальной машины (число может быть дробным, тогда дробная часть переносится на следующую итерацию). Никаких других средств синхронизации не нужно!
    Синхронизация по vbl - это последнее, что стоит делать. Она же разная в разных графических режимах, очень грубая, не вызывает прерываний (на PC) и даже может чуть по-разному работать на разных VGA.
    По таймеру надо тогда уж, но это в любом случае ошибочный подход. Еще в него любит вмешиваться операционка(если не под настоящим досом) либо посторонние программы-резиденты.
    Самый простой способ "зацепиться" на этот таймер - проверять байт по адресу 0040:006C. Он должен инкрементироваться 14318180/12/65536 = примерно 18.2 раза в секунду.
    Или речь идет о том, что, крутя на звуковой карте циклический буфер, хочется его модифицировать по частям чаще, чем вызывается IRQ?
     
    Последнее редактирование: 12 янв 2015
  21. Geryon

    Geryon

    Регистрация:
    13 май 2008
    Сообщения:
    1.228
    Я публикую сведения о проекте отрывочно, поэтому у тебя сложилось неверное впечатление.

    Цель - получить плеер SID-подобных файлов, работающий под чистым DOS или Win98-окном со звуковой картой Innovation SSI-2001. Я взял эмулятор (libsidplayfp), выбросил оттуда эмуляцию SID, заменив работой с картой.

    Сама карта представляет из себя по сути дела просто MOS6581, регистры которого выставлены начиная с порта 280h (по умолчанию). Поэтому никаких сэмплов, IRQ, DMA, буферов и т.п. нет - в порты направляются команды для SID, а он выдает сразу аналоговый звук.

    Насчет синхронизации по VBL - этот кусок кода взят из SDK Turtle Beach Multisound. Я не планировал его использовать из-за низкого разрешения (миллисекунды вместо микросекунд). Однако за предупреждение спасибо - я не знал, что это ненадежный метод.

    Что касается 0040:006C - там действительно разрешение 1/18 секунды, и тоже не подходит.
     
    Последнее редактирование: 12 янв 2015
  22. nop

    nop

    Регистрация:
    5 дек 2014
    Сообщения:
    2.297
    Ну.. тогда таймер. Вешается свой обработчик int 8, вместо того, что крутит счетчик по 0040:006C, после чего программируются пользовательские задержки через порты таймера. Точность - чуть хуже микросекунды + время реакции на прерывание + время на запись новых значений в регистры. Линк я дал, там все есть, но, наверное, можно найти более удобочитаемые руководства на русском языке. Есть еще вариант c RDTSC.

    Там явно нужна была очень грубая задержка с точностью до десятков миллисекунд, причем на компе с экзотической видеокартой, либо вообще без нее, могло бы попросту зависнуть.
     
    Последнее редактирование: 12 янв 2015
  1. На этом сайте используются файлы cookie, чтобы персонализировать содержимое, хранить Ваши предпочтения и держать Вас авторизованным в системе, если Вы зарегистрировались.
    Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie.
    Скрыть объявление