Разработка и ромхакинг > Ромхакинг и программирование
конвертация аудио сэмплов и планы на треккер
<< < (2/6) > >>
SeregaZ:

--- Цитата: Sharpnull от 23 Март 2020, 05:53:40 ---где ~ инвертирует все биты (~0x20 = 0xDF (для однобайтовой переменной)), а & - побитовое И.
--- Конец цитаты ---
не помогло :) три раза перечитал... мои три класса церковно приходской не дают осилить сей глубокомысленный момент программирования на С. я больше как бы практикой знакомлюсь с языком (своим, не С) и в этой самой практике я не встречал и просто не понимаю зачем может понадобится подобное инвертирование бит. зеркалирование - вот да :) это понимаю. а инвертирование... как-то не вижу такой задачи где оно нужно. но в целом замысел этого инвертирования как бы понял. из всяких 1010 делать 0101. про & тоже вроде понятно. своего рода обрезка значения в нужных пределах.

Добавлено позже:
про loop ничего не скажу. в архиве только один пример. может в каком-то другом случае вылезет боком. тоже посмотрел - функция большая. раз большая - наверное важная :))) хотя не вижу где она вызывается. в объявлениях есть, сама функция есть. а в init она просто упомянута в комментарии в конце функции:

--- Цитата ---   //loop:
   // [see gems_loop]
--- Конец цитаты ---
но тут я не советчик... в архиве еще asm файлы есть с родным GEMS как он на приставке работает. но там я понимаю еще меньше того малого что понимаю в С. но может там какой ответ на этот животрепещущий вопрос есть. хотя не вижу я там loop... или вижу, но не различаю...
Sharpnull:
SeregaZ, сделал библиотеку, не очень хорошо, но работает.
В папке Release: dll, lib и GEMSPlayClient.exe, которая тестирует dll (запускать GEMSPlayClient.bat как у вас).
Заголовочный файл GEMSPlayLibrary.h, функции такие:
// Инициализация. Указатели на массивы из байтов: patches, envelopes, sequences, samples.
// Возвращает 1 - если получилось инициализировать и есть хотя бы одна последовательность, иначе 0. (int в VC++ - 4 байта)
// Размер не передаётся в оригинале, видимо как-то определяется конец.
// Каждый вызов будет очистка gemsplay_cleanup(), если не было.

--- Код: ---int gemsplay_init(
const unsigned char* PatPtr, const unsigned char* EnvPtr,
const unsigned char* SeqPtr, const unsigned char* SmpPtr);
--- Конец кода ---
// Очистка выделенной памяти.

--- Код: ---void gemsplay_cleanup(void);
--- Конец кода ---
// Остановка.

--- Код: ---void gemsplay_stop(void);
--- Конец кода ---
// Переключать паузы.

--- Код: ---void gemsplay_pause(void);
--- Конец кода ---
// Воспроизведение. Повторный вызов начнёт воспроизведение сначала.

--- Код: ---void gemsplay_play(void);
--- Конец кода ---

GEMSPlayClient.exe принимает только 4 аргумента, начинается воспроизведение, Enter, пауза, Enter, продолжается воспроизведение, Enter, выход.

Не разобрался что такое song, sequences и т. п., в GEMSPlay.exe есть всякие настройки воспроизведения, я оставил значения по умолчанию.
Я не использовал статическую компоновку в dll и GEMSPlayClient.exe, поэтому требуется распространяемый компонент Microsoft Visual C++ для Visual Studio 2015, 2017 и 2019 (как вариант).
Надеюсь вам не надо поддерживать WinXP.
Попробуйте библиотеку и отпишитесь.
SeregaZ:
поет :) но на счет возврата 1 если есть хоть одна "мелодия" в банках есть - видимо что-то не то... так как GEMSInit(0, 0, 0, 0) возвращает единицу. по идее раз 0 в секвенциях - значит здесь точно нет треков и по идее должно было вернуть 0 в качестве результата работы функции. еще будет интересно посмотреть как библиотека себя поведет если мелодия в ней будет, и скажем там 5 инструментов использовалось, а в банке инструментов будет всего 1 инструмент к примеру. хотя я и буду это отсекать при формировании банков в памяти и выдавать ошибку еще до библиотеки. это я проверю еще.

по поводу статической компоновки - это я не понимаю, так-же как и обязательное наличие: распространяемый компонент Microsoft Visual C++ для Visual Studio 2015, 2017 и 2019. и Windows XP по идее нужна. предполагалось что работать редактор будет везде, на любом компьютере. лишь бы 1024х768 разрешение экрана было, иначе не все элементы интерфейса будут видны. гордость в том то и состоит что не требуются всяких нетфреймворков и прочего. просто это как-то глупо, что для редактирования игры из 90 требуется дополнительно установить софт из 2020 какогонить.

Добавлено позже:
если производить эти операции 2 раза, то все работает. на третий происходит вылет:

--- Код: ---GEMSStop() ; стоп мелодии, если играла на момент загрузки другого комплекта банков
GEMSCleanup() ; очистка
GEMSInit(*GEMSPatches, *GEMSEnvelopes, *GEMSSequences, *GEMSSamples) ; инициализация с новыми данными

--- Конец кода ---
SeregaZ:
и по всей видимости сэмплы не проигрываются. либо возможно гранаты не той системы... GEMS бывают 2 байтовый офсет для сэмпла и 3 байтовый. возможно дело в этом.

Добавлено позже:
оригинальный ехе этот набор банков проигрывает нормально, с сэмплами.
Sharpnull:

--- Цитата: SeregaZ от 23 Март 2020, 23:02:52 ---поет :) но на счет возврата 1 если есть хоть одна "мелодия" в банках есть - видимо что-то не то... так как GEMSInit(0, 0, 0, 0) возвращает единицу. по идее раз 0 в секвенциях - значит здесь точно нет треков и по идее должно было вернуть 0 в качестве результата работы функции.
--- Конец цитаты ---
Действительно, эта ошибка из оригинальной программы, там в LoadSongList() предполагается, что GetDataPtr(0x02); может вернуть NULL и тогда будет seq_count = 0, но, на самом деле, если все NULL передать (GEMSInit(0, 0, 0, 0)), то будет нулевая последовательность. Значит возвращается 0 только если не сработал sound_init().

--- Цитата: SeregaZ от 23 Март 2020, 23:02:52 ---просто это как-то глупо, что для редактирования игры из 90 требуется дополнительно установить софт из 2020 какогонить.

--- Конец цитаты ---
Это нормально. Нужно либо компилировать в VC6++ (ужас), либо включать в каждую dll и exe исполняемые библиотеки, что увеличивает размер файлов и потребление RAM, хоть и не большое.
--- Цитата: SeregaZ от 23 Март 2020, 23:02:52 ---Windows XP по идее нужна. предполагалось что работать редактор будет везде, на любом компьютере
--- Конец цитаты ---
Надеюсь поддержку Win98 не предполагаете. :) Вот статическая компоновка и поддержка WinXP, только не забудьте проверить на ней.

--- Цитата: SeregaZ от 23 Март 2020, 23:39:04 ---оригинальный ехе этот набор банков проигрывает нормально, с сэмплами.
--- Конец цитаты ---
Мой exe и/или GEMSPlay.exe? Всё зря?
UPD: Да в моей версии какая-то ошибка, попробую разобраться.

Добавлено позже:

--- Цитата: SeregaZ от 23 Март 2020, 23:02:52 ---если производить эти операции 2 раза, то все работает. на третий происходит вылет:
--- Конец цитаты ---
Это ещё не проверял.

Добавлено позже:
Ошибку с сэмплами нашёл, опечатка из-за которой просто не копировались сэмплы. С вылетом после нескольких вызовов ещё не нашёл, когда найду, то выложу обновлённую версию.
Sharpnull:
Исправил ошибку с повторным вызовов, как раз была из-за gems_loop(), который вызывался до sound_init(), о чём я писал ранее. Возможно там что-то ещё нужно инициализировать заново, это уже зависит от правильности инициализации.
Обновил GEMSPlayClient, теперь он 4 раза производит действия (паузы и очистка) и заменил на пример с сэмплами.
На счёт поддержки WinXP. Использую VS2019 с выбранным SDK для поддержки WinXP, он уже считается deprecated и больше не будет обновляться.
Нужно будет на github залить, как-нибудь позже. Пока что тестируйте.
SeregaZ:
я пока бегал со старой версией ХР - там работает. хотя если на 7 он два раза мог загрузить и вылетал на третий - то на ХР первый раз загружает и играет. при повторном - вылет. и сейчас осталось в требованиях наличие этого визуал как его там? просто видимо у меня что на 7 что на ХР он стоит и поэтому работает... весь вопрос будет ли у людей, которые используют редактор этот визуал...

сейчас буду пробывать новую версию.
Sharpnull:

--- Цитата: SeregaZ от 24 Март 2020, 00:47:03 ---и сейчас осталось в требованиях наличие этого визуал как его там?
--- Конец цитаты ---
Нет, в версии GEMSPlayLibrary_v1_winxp.7z (и в v2 оставил) я сделал статическую компоновку, все runtime библиотеки были вставлены в DLL и exe. Это и поддержка WinXP меняется в свойствах проектов и всё.
--------
Кстати, можно было делать не статическую компоновку, а класть dll, которые люди скачивают с левых сайтов, когда им пишет программа :) Так тоже экономится память, если несколько dll и exe лежат рядом, но я не знаю как там WinXP.
SeregaZ:
так что на 7 что на ХР играет замечательно, вылетов нет. загружал пару десятков раз попеременно эти комплекты. единственное - громкость. в треках есть команда называется mastervolume - для дюновского трека она 13. для не дюновского не знаю. видимо там вовсе не установлено этой команды. это глобальная громкость. чем число больше - тем тише. 1 или 0 максимальная громкость. по идее при сбросе, точнее при инициализации банков GEMS - этот параметр должен сбрасываться в максимальную громкость. сейчас же если запустить тот первый комплект с недюновским треком - он играет громко. после запустить дюновский (то есть сработает mastervolume) и после опять вернутся к первому - он будет играть тише, чем изначально он запускался. то есть сброс, точнее инициализации видимо происходит не совсем полностью.

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

Добавлено позже:

--- Цитата: Sharpnull от 24 Март 2020, 00:54:42 ---Нет, в версии GEMSPlayLibrary_v1_winxp.7z (и в v2 оставил) я сделал статическую компоновку, все runtime библиотеки были вставлены в DLL и exe. Это и поддержка WinXP меняется в свойства проектов и всё.
--- Конец цитаты ---
это просто колбаса! спасибо.
Sharpnull:
SeregaZ, есть какой-то

--- Код: ---static UINT8 MASTERATN; // [15CF] master attenuation is 7 frac bits (0 = full volume)
--- Конец кода ---
Он в начале 0, потому что глобальный, после меняется только в seqcmd() и в gems_loop(), если была команда. То есть получается, если не было явной команды, то будет что раньше.
В GemsPlay.c много глобальных переменных, которые не инициализруются в gems_init(), там даже осталось сообщение:

--- Код: ---// TODO: memzero everything else
--- Конец кода ---
Добавил обнуление в gems_init() для MASTERATN, попробуйте обновлённые dll и lib.
SeregaZ:
да, громкость восстанавливается :) засяду теперь за всепеределывание и играть в редакторе будет по человечески :)
SeregaZ:
Sharpnull, еще момент - там нет случаем переключателя PAL или NTSC?
Sharpnull:
SeregaZ, поиск PAL и NTSC по всем файл даёт результат только в vgmwrite.c, который не используется. Но там есть константы для частоты чипов:

--- Код: ---#define CLOCK_YM2612 7670454
#define CLOCK_SN76496 3579545
--- Конец кода ---
Значит если переставить, то наверно будет PAL:

--- Цитата ---FM sound chip: Yamaha YM2612, clocked at the 68000 clock speed (7.670454 MHz in NTSC, 7.600489 MHz in PAL)
PSG sound chip: Sega PSG (SN76496), clocked at the Z80 clock speed (3.579545 MHz in NTSC, 3.546894 MHz in PAL)
--- Конец цитаты ---
Там ещё просто число в коде есть 7670454, случайно заметил. Ещё есть:

--- Код: ---rate = SampleRate = 44100;
rateFMUpdate  = rate / 30;
rateDACUpdate = rate / 60;
// Different rate divisions; rateFMUpdate is how often YM2612 and SN76496 update, and rateDACUpdate is the DAC
--- Конец кода ---
Здесь возможно нужно менять на 25 и 50. Также встречаются 60, которые могут быть удобными делителями.
Вам нужен PAL?
Забыл сказать ранее, там же ещё есть режим, который компилируется отдельно:

--- Код: ---#ifdef DUAL_SUPPORT
printf("2xYM2612 support enabled.\n");
#endif
--- Конец кода ---
Вам такого не надо?
SeregaZ:
про Dual я на форуме моего языка все мозги прокомпосировал :) они так ничего толком не подсказали когда пытался портировать... я так понимаю там просто два ядра? точнее два комплекта по 2 чипа? по идее не надо - ведь на приставке только одна пара чипов - SN9какего там и YM2612. видимо это для особых случаев - помница в какой-то мелодии севенап не хватает каналов для проигрывания всего, что там одновременно играет.

по поводу PAL и NTSC - я фанат PAL. а здесь обратил внимание что чуть быстрее мелодии из Дюны играют вот и решил переспросить - может там какая-то команда для переключения есть. а так уже черновик набросал. доволен до безобразия :) спасибо еще раз.

еще шелу мозги покомпосирую почему сэмплы играют начиная с $30 "ноты", а не с 0 . это мне кажется странным. ведь если всего нот $5F - то $5F - $30 = 47 нот, сиречь сэмплов можно использовать. как-то маловато будет... я думал что можно от 0 до $5F - как количество нот. а так то это вроде не баг, так как шеловский комбайн так собирает. с $30 ноты нулевой сэмпл и дальше. я просто не понимаю логику почему. ведь если с 0 играло бы - больше сэмплов могло бы влезть. странно это.

Добавлено позже:
vgmwrite - это по всей видимости специально ответвление от проигрывателя с целью записей VGM файлов. автор - ValleyBell просто развивает это дело с VGM вот и видимо прикручивал дополнительно запись VGM. это тоже не надо. мне главное чтоб играло правильно, с поддержкой loop - зацикливаний и все модуляции и питчи... то что у меня наколхозено было - половину из этого не играло. только поверхностное представление о мелодии было. теперь же как в аптеке - все четко играет.
Sharpnull:

--- Цитата: SeregaZ от 25 Март 2020, 04:57:46 ---я так понимаю там просто два ядра? точнее два комплекта по 2 чипа?
--- Конец цитаты ---
Инициализируются два YM2612.

Оказалось, что частоты:

--- Код: ---#define CLOCK_YM2612 7600489
#define CLOCK_SN76496 3546894
--- Конец кода ---
Не влияют на скорость, только на звучание, причём на слух разницы не заметил, только при большем изменении значений.
Но я смог сделать медленнее через изменение (вместо 30 и 60):

--- Код: ---// sound.c
rateFMUpdate  = rate / 25;
rateDACUpdate = rate / 50;
// Stream.c
#ifdef WIN32
BUFFERSIZE = SampleRate / 50 * SAMPLESIZE;
--- Конец кода ---
Да, второй кусок только для Windows, а для Linux по-другому, там нет константы 60.
Вот DLL с такой скоростью (CLOCK тоже изменил), можно сказать для теста. Если нужно, могу добавить в gemsplay_init() как 5-й параметр.
SeregaZ:
а я где-то глюков понасадил... почему-то иногда вылетает. ну это ладно - этот самый YM видимо не совсем правильный. в смысле в оригинальном проигрывателе не совсем точный видимо использован. на эмуляторе (в архиве и 4 банка для проигрывателя и 1 файл ром для запуска в эмуляторе) звучит бочка глухо и коротко. в проигрывателе же какое-то эхо. потом в проигрывателе есть пиликания - не знаю как назвать - в самом начале некие скрипы такие с быстро меняющейся частотой - в эмуляторе такого нет.


Добавлено позже:
ясно. оригинальный код не обрабатывает модуляции :( или это я просто не правильно изначально посылаю модуляции в проигрыватель...

Добавлено позже:
вобщем думаю ошибка при загрузке envelopes.bin в оригинальном проигрывателе. что-то там где не то :)

Добавлено позже:
либо на единицу ошибается при чтении модуляции из этого файла при проигрывании. потому что первая модуляция - 0 по счету - как раз ничего не делает. заглушка.

другой косяк, связанный с модуляциями - что нельзя больше 10 инструкций писать. а там как раз для этого трека одна модуляция на 20 инструкций. но он на это эхо не влияет. просто после 10 инструкции зависает модуляция.
SeregaZ:
может быть что просто указатель путается и вместо Envelope загружается другой из файлов в оригинальном проигрывателе? вроде где-то здесь в трех местах это происходит.


--- Код: ---void SetROMFile(const UINT8* ROMPtr)
{
ROMData = ROMPtr;
PData = ROMPtr;
Tbls.PTBL68K[0] = Tbls.PTBL68K[1] = Tbls.PTBL68K[2] = 0x00;
EData = ROMPtr;
Tbls.ETBL68K[0] = Tbls.ETBL68K[1] = Tbls.ETBL68K[2] = 0x00;
SData = ROMPtr;
Tbls.STBL68K[0] = Tbls.STBL68K[1] = Tbls.STBL68K[2] = 0x00;
DData = ROMPtr;
Tbls.DTBL68K[0] = Tbls.DTBL68K[1] = Tbls.DTBL68K[2] = 0x00;

return;
}

void SetDataFiles(const UINT8* PatPtr, const UINT8* EnvPtr,
  const UINT8* SeqPtr, const UINT8* SmpPtr)
{
ROMData = NULL;
PData = PatPtr;
Tbls.PTBL68K[0] = Tbls.PTBL68K[1] = Tbls.PTBL68K[2] = 0x00;
EData = EnvPtr;
Tbls.ETBL68K[0] = Tbls.ETBL68K[1] = Tbls.ETBL68K[2] = 0x00;
SData = SeqPtr;
Tbls.STBL68K[0] = Tbls.STBL68K[1] = Tbls.STBL68K[2] = 0x00;
DData = SmpPtr;
Tbls.DTBL68K[0] = Tbls.DTBL68K[1] = Tbls.DTBL68K[2] = 0x00;

// Catch NULL-pointers in a way similar to most games.
if (DData == NULL)
DData = NullData;
if (SData == NULL)
SData = DData;
if (EData == NULL)
EData = SData;
if (PData == NULL)
PData = EData;

return;
}

const UINT8* GetDataPtr(UINT8 DataType)
{
if (DataType == 0x00)
return PData + Read24Bit(Tbls.PTBL68K);
else if (DataType == 0x01)
return EData + Read24Bit(Tbls.ETBL68K);
else if (DataType == 0x02)
return SData + Read24Bit(Tbls.STBL68K);
else if (DataType == 0x03)
return DData + Read24Bit(Tbls.DTBL68K);

return NULL;
}
--- Конец кода ---

типа EData = SData. то есть в итоге вместо envelope обрабатывается какой-то другой указатель и из-за этого происходит черти чо.

сами модуляции - эти envelope - состоят в банке по следующему алгоритму:
указатель на первую модуляцию - 2 байта
указатель на вторую модуляцию... и так далее по 2 байта указатели.
первая модуляция:
стартовый питч - 2 байта
повторяемый кусок:
значение питч, которое должно прибавляться или убавляться. - 2 байта
счетчик, сколько раз должно это прибавление или убавление на столько-то произойти - 1 байт
(как только в модуляции значение счетчика будет 0 - система понимает, что модуляция закончилась и начинается следующая модуляция. то есть как правило "конец" модуляции это 00 00 00 три нуля в банке модуляций)

известные баги: в оригинальном драйвере есть буфер для модуляции 128 байт. он общий для 4 разных модуляций, которые могут быть запущены одновременно. типа если трек содержит 5 разных модуляций одновременно - одна пойдет лесом. то есть получается по 32 байта на каждую. это не перезаписываемый буфер, как это делает сэмплы например. то есть там как доиграло до конца буфера, но сэмпл занимает больше места, чем буфер - там перезапись и сброс указателя на начало, то есть сэмпл доиграет до конца как полагается. с модуляцией система будет играть до 0 счетчика, либо тупо зависнет после 10 инструкции. то есть 32 байта = 2 байта стартовый питч, 9 * 3 байта инструкции (питч 2 байта и счетчик 1 байт), и в конце три нуля 00 00 00 - тогда все проиграется верно. ежели модуляция имела больше этих 9 инструкций, точнее 10 - ведь 00 00 00 это по сути тоже инструкция, пусть и финализирующая - то модуляция подвиснет к чертовой бабушке. возможно это как раз и происходит, то есть вместо банка модуляций проигрыватель почему-то читает... ээ... скажем банк с мелодиями. там по идее три нуля подряд не встречается, то есть с точки зрения модуляции - конец она не встречает и начинает проигрывать эту "модуляцию" и посему там происходит вакханалия.
Sharpnull:

--- Цитата: SeregaZ от 25 Март 2020, 20:42:08 ---типа EData = SData. то есть в итоге вместо envelope обрабатывается какой-то другой указатель и из-за этого происходит черти чо.

--- Конец цитаты ---
В вашем пример gemstest.zip, равен нулю SmpPtr (семплы) и DData устанавливается в NullData:

--- Код: ---static const UINT8 NullData[0x10] =
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
--- Конец кода ---
Там есть ошибки в коде может из-за этого. В формате я не разберусь.
SeregaZ:
буржуи люди нехорошие... чтоб им всем там икалось.

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

как можно прочитать при старте мелодии содержимое сих моментов?

--- Код: --- EnvOfs = Read24Bit(Tbls.ETBL68K) + (EnvNum << 1); // pointer to env table in 68k space
XFER68K(fpoffset, EData, EnvOfs, 2); // read 2 byte offset, into... local fpoffset (shared w/ fetchpatch)
fpoffset_s = Read16Bit(fpoffset);

EnvOfs = Read24Bit(Tbls.ETBL68K) + fpoffset_s; // pointer to env data
EcbBufIdx = EcbPtr[ECBBUFP] & 0x7F;
XFER68K(&ENV0BUF[EcbBufIdx], EData, EnvOfs, 32); // xfer the 32 byte env into this ECB's envelope buffer

--- Конец кода ---
в моем недоязыке в нужное место ставлю
Debug EnvOfs
и он мне показывает в окошке текстом значение. есть ли подобное в этом языке программирования?

вот мне не нравится еще EnvNum << 1. может быть там должно было быть + 1, а не сдвиг на 1 байт?

надо посмотреть что в итоге пишется здесь:
XFER68K(&ENV0BUF[EcbBufIdx], EData, EnvOfs, 32);
в память буфера, я так понимаю. то есть получается здесь файл envelope раньше прочитался, втулился куда-то в память. после пошла играть мелодия. там дошло до выбора номера модуляции - 0 номер. она 0 двигает на 1 байт, после пытается прочитать 32 байт в буфер? получается даже если модуляция меньше - все равно 32 прочитает. ну меньше то фиг с ним. вобщем мне в дебаге надо прочитать эти 32 байта в момент запуска модуляции чтоб понять на чтении косяк, или уже при самой обработке. знать бы еще как это делается :)
Sharpnull:
SeregaZ, до вашего сообщения я как раз добавил проект (Project) в это решение (Solution) для компиляции в оригинальный GEMSPlay.exe на основе изменённого кода для DLL, для тестирования.
Добавил на GitHub: https://github.com/infval/GEMSPlay.
После версии v2 + MASTERATN = 0, изменения в настройках проектов, по мелочи и одна ошибка оригинального кода при обработке seqcmd-seqgoto в GemsPlay.c:

--- Код: --- case 111: // 111 = goto
//seqgoto:
{
INT16 JmpOfs;
UINT32 FinalAddr;

CurArg = GETSBYTE(ChnCCB, CHBUFPTR); // Исправил CurArg на JmpOfs
JmpOfs = (GETSBYTE(ChnCCB, CHBUFPTR) << 8) | (JmpOfs << 0);
--- Конец кода ---
Я оставил замену проигрывателю GEMSPlay - функция main - для тестирования функций библиотеки, если компилировать GEMSPlay (без библиотек), в котором используются gemsplay_init() и т.п. Для переключения замените #if 0 на #if 1 в GEMSPlayLibrary.c:

--- Код: ---#if 0
int main(int argc, char* argv[])
--- Конец кода ---

--- Цитата: SeregaZ от 28 Март 2020, 05:48:45 ---какая студия используется? работает ли в ней сразу без ошибок оригинальный код проигрывателя? который не длл, а именно ехе оригинальный. себе поставлю такую-же.
--- Конец цитаты ---
<<< Ликбез по Visual Studio 2019 >>>
Установка
Ставить нужно Visual Studio 2019. В Visual Studio Installer выбрать язык Английский, из "Рабочих нагрузок" "Разработка классических приложений на C++", в "Отдельные компоненты" "Поддержка Windows XP на C++ для инструментов VS 2017".
Работа с проектами
Открывать GEMSPlayLibrary.sln, в Solution Explorer будет 3 проекта: GEMSPlay (оригинальное консольное приложение), GEMSPlayClient (тест библиотеки), GEMSPlayLibrary (библиотека).
Для выбора активного проект (отмечен жирным шрифтом), ПКМ по нему -> Set as Startup Project. При компиляции и запуске (F5/Ctrl+F5) он и будет использован. Для DLL нет смысла, можно просто сделать сборку всего решешения (Build -> Build Solution) или ПКМ -> Build/Rebuild.
Из-за использования одинакового кода для библиотеки и GEMSPlay, входной main() у GEMSPlay в GEMSPlayLibrary.c, также стоит учесть, подсветка синтасиса для макросов препроцессора зависит от того, из какого проекта открыт файл .c/.h (я использовал GEMSPLAY_NO_LIBRARY в GEMSPlay, чтобы убрать предупреждения компилятора).
Настройка проектов
У каждого проекта есть Properties (ПКМ по проекту, хранятся в .vcxproj-файле), где для каждого из Configurantion (Debug/Release) и Platform (Win32/x64) настраиваются доп. библиотеки и другое:
* General > Platform Toolset: v142 - для Win7+, v141_xp - для поддержки XP. Выбрал только для Release/x86 для GEMSPlayClient/Library, так как поиск ошибок IntelliSense (на основе открытых файлов c/cpp/h) не работает из-за этого. Для возвращения на v142 нужно также выбрать Windows SDK Version - 10.0 (latest installed version).
* C/C++ > Code Generation > Runtime Library: влияет на добавление библиотек Visual C++ в exe. Если Debug на конце - для Debug конфигураций, а DLL значит, что не будет включено в exe. Сделал для Release/x86 для GEMSPlayClient/Library.
* Для GEMSPlayLibrary оставил pch.h (Precompiled Header), который был сгенерирован, и использовал C/C++ > Advanced > Forced Include File, чтобы неявно включить pch.h во все .c-файлы. Это можно убрать, по-хорошему туда включают часто используемые неизменяемые библиотеки как windows.h для ускорения компиляции.
* Debugging > Command Arguments: аргументы командной строки при запуске (F5/Ctrl+F5).
* В Solution Properties > Project Dependencies добавил зависимость GEMSPlayClient от GEMSPlayLibrary, чтобы можно было собрать решение, а не по отдельности.

--- Цитата: SeregaZ от 28 Март 2020, 05:48:45 ---в моем недоязыке в нужное место ставлю
Debug EnvOfs
и он мне показывает в окошке текстом значение. есть ли подобное в этом языке программирования?
--- Конец цитаты ---
Про отладку
Установили аргументы командной строки и запускаете проект в конфигурации Debug с отладкой (F5, а не Ctrl+F5).
Чтобы выполнение остановилось, ставите breakpoint нажатием на область слева от номера строки кода. Можно делать шаги по строкам, как обычно.
Чтобы увидеть значение переменной, вводите её имя в панели Watch 1 внизу, во вкладках Auto и Locals отображаются соответствующие переменные на данный момент. Можно выводить в консоль через printf() или OutputDebugString() выводить в специальное окно, но там не строка форматирования (для решения этой проблемы смотрите ответы: How do I print to the debug output window in a Win32 app?).
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии