Автор Тема: [SEGA] Нужна помощь с реверсом звукового драйвера  (Прочитано 4913 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
SeregaZ, ты не понял. Пока что мне интересно, как DAC воспроизводится без инструментов. GYMка же воспроизводит.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
в dll'ке, что ValleyBell давал - есть команда:
PlayDACSample(номер чипа, размер, указатель на участок памяти с сэмплом, частота)
но это несколько не верно по отношению к YM2612 :) на самом деле на приставке воспроизведение происходит следующим образом:
сначала идет регистр $2B:
OPN_Write(0, $2B, $80) ; DAC enable register
это включает возможность проиграть сэмпл и, видимо, отключает на время возможность играть FM на 6 канале.
после должен происходить спам регистра $2A по моему, где значением идет по байтно этот самый файл сэмпла.
как сэмпл закончил играть, то надо отключить DAC
OPN_Write(0, $2B, $00)

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
SeregaZ, это я видел)
Но вот как происходит воспроизведение этого "спама" в твоей программе?

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
никак. я ж говорю :) эта команда PlayDACSample была запилена товарищем ValleyBell'ом, так как он не хотел заморачиваться с полной 100% реализацией ym2612. я его уже ругал по этому поводу, когда возился с VGM. при проигрывании VGM, из-за неработающего правильно регистра $2A - надо изобретать велосипед, чтоб сэмплы заиграли. так что это тоже можно отнести к минусам библиотеки. но это хоть что-то. я и не надеялся и на такой результат, когда только начинал. эта библиотека очень помогла в моем проекте :)

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

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
SeregaZ, эмм....
Я выбираю сэмпл DAC, жму Play, и оно воспроизводит мне нормально.

При чём тут регистр $2A, $2B? В них я знаю что пишется, когда пишется, и зачем. Вот мне нужно самостоятельно эти сэмплы (я уже проикладывал voice sample 0) воспроизводить, из моего кода.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
да, GYM не пишет сэмплы... скатина :( нету $2A.

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

Добавлено позже:
импорт и что-то типа "объявления" для моего непутевого языка.
OPNhdll = LoadLibraryEx(?StartOPNDLL, ?EndOPNDLL)
If OPNhdll
  Prototype.i OpenDriver(chip.i)
  Prototype CloseDriver()
  Prototype OPNWrite(chip.i,register.i,value.i) 
  Prototype OPNPlayDACSample(chip.i, size.i, *Data, freq.i);
 
  Global OpenOPNDriver.OpenDriver = GetProcAddressEx(OPNhdll, "OpenOPNDriver")
  Global CloseOPNDriver.CloseDriver = GetProcAddressEx(OPNhdll, "CloseOPNDriver")
  Global OPN_Write.OPNWrite = GetProcAddressEx(OPNhdll, "OPN_Write")
  Global PlayDACSample.OPNPlayDACSample = GetProcAddressEx(OPNhdll, "PlayDACSample")
Else
  MessageRequester("ALERT!", "Critical Error!")
  End 
EndIf

после надо:
OpenOPNDriver(1) ; включение ядра так сказать

; потом по усмотрению использовать
OPN_Write(0, $2B, $80) ; DAC enable register

PlayDACSample(номер чипа, размер, указатель на участок памяти с сэмплом, частота)

; здесь наверное нужна пауза, чтоб программа ждала, пока длл доиграет сэмпл

OPN_Write(0, $2B, $00)

CloseOPNDriver() ; отключить драйвер


OPN_Write(0, reg, val) - туда можно слать все регистры, только что по таймеру - иначе у тебя вся мелодия зазвучит в одну секунду гыгыг.
« Последнее редактирование: 18 Январь 2018, 13:51:51 от SeregaZ »

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
PlayDACSample
Вот мне собственно и нужно понимать, как играется сэмпл на стороне оси. Про регистры связанные с DAC я понимаю.

Оффлайн MetalliC

  • Технический консультант
  • Сообщений: 9401
  • Пол: Мужской
  • Demul team / MAME developer
    • Просмотр профиля
в SGDK проигрыватели смотрел ? маловероятно что в игре играется именно так, но для общего ознакомления сойдет.
допустим плеерок Стефана: FM + 4 канала PCM с софтмиксом

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
именно так, но для общего ознакомления сойдет
Придётся. Не хочется таскать целую библиотеку, не понимая как она вообще работает. Это не мой подход:).

Оффлайн MetalliC

  • Технический консультант
  • Сообщений: 9401
  • Пол: Мужской
  • Demul team / MAME developer
    • Просмотр профиля
я и имел в виду "букварь покурить", вот этот например
https://github.com/Stephane-D/SGDK/blob/master/src/z80_xgm.s80
чтоб понять как оно типично работает

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
а накой велосипед изобретать? в винде есть замищательная винапи:
sndPlaySound_(*snddest,#SND_MEMORY | #SND_ASYNC | #SND_NODEFAULT)*snddest указатель на память, где загружен сэмпл
#SND_MEMORY один из флагов, которые говорят что это память, а не из файла играется.

то есть алгоритм будет примерно такой:
получаем размер файла сэмпла. скажем 500 байт.
создаем хедер вав файла - кусочек памяти 44 байта, где будет указано что моно, что 8 бит, что частота такая-то.
читаем в памяти образ файла сэмпла.
склеиваем 44 байтовый хедер и образ файла.
подсовываем это дело винапи sndPlaySound_

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
MetalliC, ну, это уже другое - это когда я до инструментов доберусь.

А сейчас: я имею DAC 8-bit, который хочу сконвертировать в формат, который бы мог воспроизвести, например, через waveOut( ) API.

Добавлено позже:
SeregaZ, т.е. я могу просто взять и DAC-сэмпл в sndPlaySound() закинуть? А конвертировать не нужно?

Оффлайн MetalliC

  • Технический консультант
  • Сообщений: 9401
  • Пол: Мужской
  • Demul team / MAME developer
    • Просмотр профиля
в общем и в целом - в таких плеерах расчёты-вычисления бьются/дискретизируются на маленькие кусочки, каждый по размеру не более задержки между семплами. и весь код проигрывателя типично выглядит как:

начало:
- что-то немножко делаем или считаем.
- выводим семпл
- что-то еще делаем
- выводим следующий семпл

и так далее и тому подобное кучку раз, когда считать уже нечего цикл становится:
- цикл тупой задержки
- выводим очередной семпл
повторенное кучку раз, затем goto начало:

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
если обычные 8 бит - нет. если там было какое сжатие типа DPCM или ADPCM - то нужно. правда вот насчет 4 битных не сжатых надо тестировать. по идее должно играть. пойду испытывать. по моему я вчера видел игру с такими 4 битными. надо будет перепроверить это дело :)

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
MetalliC, на уровне драйвера я уже понял как DAC воспроизводится) мне же нужна ось - смотри выше.
SeregaZ, тогда это то, что я хотел) Попробую, спасибо.

Добавлено позже:
Попробую, спасибо.
Супер! Работает! Я юзал waveOut API, но суть та же! Крутяк)

Только сейчас подсчитаю точное число тактов задержки в драйвере, и, будет прям огонь!)
« Последнее редактирование: 21 Январь 2018, 13:16:09 от DrMefistO »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
так инструменты и ноты то нашел? разобрался в каком формате они хранятся?

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
SeregaZ, нашёл, но формат не разбирал. Скоро займусь.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
хы... а чего WAV не может быть 4 битный чтоль? :) смотрю во всех описаниях либо 8 либо 16. ставлю внаглую 4 - играет все равно как 8 бит :))

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
MetalliC, в общем, частота дискретизации ~5050Гц в игре.
Единственное, не понял, какое значение циклов прибавлять в случае (опкод: C4), если условие не выполняется:
call    nz, sub_237

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
а в случае, если сэмпл 4 битный и без сжатия - то видимо его надо будет превращать в 8 битный, чтоб винапи его проиграть могло. 4 битное оно не играет. надо брать по 4 бита значение, умножать на 16 и писать в файл как 8 бит.

если 4 битные со сжатием - то надо искать таблицу в файле драйвера и формулу по какой он производит подсчет. как это было в МК3 - там таблица была выдернута из файла драйвера. с комиксзонным ADPCM таблица вроде тоже есть в файле драйвера, но вот формулу мне буржуи не объяснили :)

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
Если что, то на питоне вот (воспроизводилка voice сэмпла):
import pyaudio
import sys

if __name__ == '__main__':
    if (len(sys.argv)) < 2:
        print 'Please, specify voice sample file!'
        sys.exit(-1)

    p = pyaudio.PyAudio()

    stream = p.open(format=pyaudio.paUInt8,
                    channels=1,
                    rate=5100,
                    output=True)

    with open(sys.argv[1], 'rb') as f:
        voice = f.read()

        stream.start_stream()
        stream.write(voice)

        stream.stop_stream()

        stream.close()
        p.terminate()
« Последнее редактирование: 21 Январь 2018, 14:29:30 от DrMefistO »

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
съест твой код этот сэмпл? :))) 4 бита, 7300 по идее частота должна быть.


Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
SeregaZ, может я неправильно себе представляю 4 бита, но по идее, там старшие 4 бита должны быть равны 0 (ну или младшие), а они у тебя вполне 8-битные.
На 4300 вполне слышно переговоры по рации.

Оффлайн MetalliC

  • Технический консультант
  • Сообщений: 9401
  • Пол: Мужской
  • Demul team / MAME developer
    • Просмотр профиля
MetalliC, в общем, частота дискретизации ~5050Гц в игре.
Единственное, не понял, какое значение циклов прибавлять в случае (опкод: C4), если условие не выполняется:
call    nz, sub_237
10 если условие ложно (перехода не было), иначе 17

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
10 если условие ложно (перехода не было), иначе 17
Спасибо. Итоговая частота 5100Hz.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
да там не рация. там стадион ревет, а диктор орет типа "awesome baby!"

0000хххх - по твоей схеме это ж дикая трата места в роме :)
xxxxyyyy - 4 битный там пишется в одном байте, то есть 2 тика получается.

а про частоту сэмплов - там надо смотреть в таблице объявления сэмплов. там должен быть адрес в роме, размер, и или частота сэмпла или какой-то флаг обозначающий частоту. типа 1 - 5100, 2 - 6000, 3 - 7000... от фонаря цифры пишу. и эту теорию надо будет проверить в других играх с тем-же движком. то есть песни из других игр должны подходить к этой. здесь по всей видимости сэмплы все одной частоты 5100.

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
а про частоту сэмплов
в моём случае частота считалась суммированием тактов, необходимых на выполнение каждой инструкции в коде заливки сэмпла. А затем частоту процессора нужно поделить на эту сумму.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
а я все-таки голосую за таблицу :) эти игроделы максимально снижали ресурсоемкость всего, что только можно. если бы у них такая система подсчета стояла - то это сколько кода займет то? вагон. думаю все-таки коротенькая таблица индекс и значение, или просто явное указание частоты должно быть. ну это если ты конечно будешь делать универсальную программу для драйвера. если только частный случай с одной игрой - то и так пойдет конечно.

Оффлайн DrMefistO

  • Пользователь
  • Сообщений: 1319
  • Пол: Мужской
  • Sega Mega Drive reversing
    • Просмотр профиля
SeregaZ, даже у Стефа напротив критичных мест есть указание тактов инструкций.

Оффлайн SeregaZ

  • Пользователь
  • Сообщений: 2565
  • Пол: Мужской
  • ливнул с форума
    • Youtube
    • Просмотр профиля
[SEGA] Нужна помощь с реверсом звукового драйвера
« Ответ #59 : 25 Февраль 2018, 01:51:04 »
чото ты куда-то слился... давай доделывай :) хочу поглядеть на распакованные данные.
http://datacrystal.romhacking.net/wiki/THUNDER_FORCE2:Tutorials