Разработка и ромхакинг > Ромхакинг и программирование
SGDK
<< < (37/40) > >>
ALKOSHA:

--- Цитата: rep-stosw от 11 Декабрь 2021, 11:36:42 ---Гружу  карту уровня таким кодом:


--- Код: --- int idx2=ind;
 ind+=BG1_Map.tileset->numTile;

 VDP_loadTileSet(&BG1_Tileset,idx2,DMA);
 BG1=MAP_create(&BG1_Map,BG_A,TILE_ATTR_FULL(PAL1,FALSE,FALSE,FALSE,idx2));
 VDP_setPalette(PAL1,BG1_Map.palette->data);

--- Конец кода ---

Вопрос,  как повысить приоритет отдельным тайлам - платформам в уровне - в пределах одного плейна?   Второй плейн отдан под фон.

Проще говоря, хочется задавать разный приоритет тайлам в пределах одной плоскости, как на картинках ниже:

(Ссылка на вложение) (Ссылка на вложение)

(Ссылка на вложение)

--- Конец цитаты ---
макрос TILE_ATTR_FULL() задаёт флаги сразу целому массиву тайлов.
Индивидуально задаётся атрибут через TILE_ATTR(), где второй флаг отвечает за приоритет.

На высоком уровне я бы просто разбил слой на две части, и грузил бы их по отдельности.

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

--- Цитата: rep-stosw от 11 Декабрь 2021, 14:23:33 ---Внезапно,  нашёл решение, проверил - работает:
--- Конец цитаты ---
А, ну или так. Просто  я давно не следил за развитием фишек сгдк.
Ti_:

--- Цитата: Werton от 09 Декабрь 2021, 14:23:32 ---Так к примеру, с этим можно сделать эффект персонажа (спрайта) ходящего за стеклом
--- Конец цитаты ---
Почему нет? Как раз стекло, за которым яркость падает. В месте 'стелка' у обоих фонов должно быть приоритет лоу. А во всех остальных местах у скролла А - хайх. Или что имеется ввиду?
Werton:

--- Цитата: Ti_ от 11 Декабрь 2021, 17:07:04 ---Почему нет? Как раз стекло, за которым яркость падает. В месте 'стелка' у обоих фонов должно быть приоритет лоу. А во всех остальных местах у скролла А - хайх. Или что имеется ввиду?
--- Конец цитаты ---
Да не, не просто затенение, а наложение "текстуры" стекла на "текстуру" перса. Стекло в 2д играх, ведь обычно не просто однотонной серой областью изображают, там всё равно, какие то блики минимальные обозначают, + немного голубоватое или вообще цветное, что то типа такого:
rep-stosw:

--- Цитата: ALKOSHA от 11 Декабрь 2021, 16:43:04 ---На высоком уровне я бы просто разбил слой на две части, и грузил бы их по отдельности.
--- Конец цитаты ---

Как это сделать?

Сделал два PNG:  в одном платформы с высоким приоритетом, в другом PNG - платформы с низким приоритетом.

В res добавил так:


--- Код: ---PALETTE Pal "BG1pal.png"

TILESET BG1_Tileset "BG1pal.png" NONE ALL

MAP BG1_Map_LO "BG1LO.png" BG1_Tileset NONE 0
MAP BG1_Map_HI "BG1HI.png" BG1_Tileset NONE 0

--- Конец кода ---

Код:


--- Код: --- int idx2=ind;
 ind+=BG1_Map_LO.tileset->numTile;

 VDP_loadTileSet(&BG1_Tileset,idx2,DMA);

 BG1=MAP_create(&BG1_Map_LO,BG_A, idx2|TILE_ATTR(PAL0,FALSE,FALSE,FALSE) );
 BG1=MAP_create(&BG1_Map_HI,BG_A, idx2|TILE_ATTR(PAL0,TRUE ,FALSE,FALSE));


 VDP_setPalette(PAL0,Pal.data );

--- Конец кода ---

В итоге показываются  те платформы, что были загружены последними.  Старые затираются.

Как сделать загрузку мапы по слоям отдельно?
rep-stosw:

--- Цитата: ALKOSHA от 11 Декабрь 2021, 16:43:04 ---А, ну или так. Просто  я давно не следил за развитием фишек сгдк.
--- Конец цитаты ---

У этого способа есть недостаток.  Для платформ с высоким приоритетом нужно дублировать цвета палитры, иначе они не устанавливаются.

Желтые платформы - с высоким приоритетом
Синие платформы -  с низким.

Если сдублировать цвета жёлтых платформ (значения с +128), то  всё хорошо.



Если же сверху убрать цвета жёлтых платформ,  то они будут чёрного цвета, так как устанавливаются только цвета синей платформы.



Проще говоря,  этот метод  не учитывает, что цвета приоритетных платформ могут сидеть с индексами от +128, и палитра ставится только по первым 16 индексам.  Работает только мапа.

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

В GIMP это делается по-уродски.
rep-stosw:

--- Цитата: rep-stosw от 12 Декабрь 2021, 09:07:15 ---И ещё.  Поимел гоморой с клонированием цветов и назначением их на тайлы.  Есть какие-нибудь редакторы, которые позволяют жёстко переназначать цвета на разные индексы?

В GIMP это делается по-уродски.
--- Конец цитаты ---

Короч.  Всё свелось к написанию своей утилиты,  которая на входе получает 2 BMP файла (платформы, разделённые по приоритету) и даёт на выходе итоговый BMP, в котором платформы кодируются разными индексами цвета, в зависимости от приоритета.  Причём, утилита  сравнивает палитры с обоих файлов - объединяет  в одну палитру, повторяющиеся цвета выкидывает и переиндексирует пиксели.

Теперь платформы можно рисовать любыми цветами, независимо от приоритета.  :)
rep-stosw:
По спрайтам вопрос.

Дока на сегу говорит, что на X- и Y-координаты выделено 10 бит, то бишь X и Y могут быть в диапазоне 0..1023
И левый верхний угол экрана это X=128, Y=128.

Тогда почему, когда даёшь по X спрайту координату 512 - он снова появляется на экране ровно в том месте как и при X=0 ?

Хочется гонять спрайты немного за пределами кадра,  например для движущихся платформ, и не заморачиваться с онанизмом управления видимости Show/Hide спрайта.
Ti_:
Что за дока?
В офф. доке страница 53,  X = от 1 до 1FF,   Y от 0 до 1FF.   Только в interlace mode2 до 3FF и только для Y.  Плюс на следующей странице пометка о случае с X=0.
rep-stosw:

--- Цитата: Ti_ от 15 Декабрь 2021, 18:31:31 ---Что за дока?
В офф. доке страница 53,  X = от 1 до 1FF,   Y от 0 до 1FF.   Только в interlace mode2 до 3FF и только для Y.  Плюс на следующей странице пометка о случае с X=0.
--- Конец цитаты ---

Да, ошибся с докой.
В заблуждение ввели вот эти утверждения:


--- Цитата ---index + 0 = vertical coordinate
 ; ---- --yy yyyy yyyy

index + 6 = horizontal coordinate
 ; ---- --yy yyyy yyyy

--- Конец цитаты ---

https://huguesjohnson.com/programming/genesis/spritelist/

///

Столкнулся с новым явлением.

При использовании инициализированных переменных, типа:


--- Код: ---int p=5;
char d=8;

--- Конец кода ---

Их начальные значения присваиваются только при Hard Reset (включение питания приставки).

При Soft Reset (на приставке "обычная" кнопка Reset) сохраняются последние значения в этих переменных.

На эмуляторах тоже самое.

Это вообще - нормально?

Я конечно могу сделать что-то типа:


--- Код: ---void InitAllVariables()
{
}

--- Конец кода ---

и вызвать её в main().  Но это уже попахивает костылями.

Подскажите, что надо подправить в стартапе, чтобы при обоих ресетах оно присваивалось всегда как при Hard Reset.
Werton:

--- Цитата: rep-stosw от 18 Декабрь 2021, 13:10:01 ---Это вообще - нормально?

--- Конец цитаты ---
нормально

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

--- Цитата: rep-stosw от 18 Декабрь 2021, 13:10:01 ---Подскажите, что надо подправить в стартапе, чтобы при обоих ресетах оно присваивалось всегда как при Hard Reset.
--- Конец цитаты ---


--- Код: ---int main(int hard_reset) {

    if (!hard_reset) {
        SYS_hardReset();
    }
}
--- Конец кода ---
rep-stosw:

--- Цитата: Werton от 18 Декабрь 2021, 14:36:35 ---int main(int hard_reset) {

    if (!hard_reset) {
        SYS_hardReset();
    }
}
--- Конец цитаты ---

Спасибо! Теперь работает как следует.

///

Со спрайтами есть вопрос.

При смене персонажей игрока спрайты пересоздаются каждый раз.  Из-за этого их приоритет (по отношению к другим спрайтам) становится ниже, чем у спрайтов, которые были созданы раньше.  Выделение-освобождение спрайтов сделано пока как по умолчанию - аллокация аппаратных спрайтов на совести SGDK.

Используются такие функции:


--- Код: ---SPR_releaseSprite();  //освобождаем спрайт

SPR_defragVRAM(); //дефрагментируем видеопамять - чтобы "приструнить" актуальные спрайты один к другому, без тайловых "дырок"

SPR_addSprite(); //добавляем новый спрайт

--- Конец кода ---

Можно ли сделать так? :

1. Спрайты игрока - задать их номер жёстко (к примеру с 1 по 7).
2. Остальные спрайты - динамически аллоцировать средствами SGDK  (но начиная с номера 8 и далее)

Какими функциями и их флагами нужно воспользоваться?

//

По звукам вопрос.  Использую XGM для воспроизведения музыки и звуков.

Раскладка каналов такая :  5 FM + 1 DAC(CH1) + 4 PSG - музыка.    DAC (CH2,3,4) - звуки.

Некоторые звуки звучат очень "сопливо" (как бы рывками, дёрганно).  Особенно которые сильно пищат или с ВЧ-шумами.  Также иногда слышится хруст на стыке повторяющихся фрагментов звука.  При этом, в музыке ударная партия (CH1) очень хорошо звучит всегда.  Проблема именно в звуках:


--- Код: ---//init:
 XGM_setPCM(70,start_sfx,sizeof(start_sfx));

//in game loop:
XGM_startPlayPCM(70,15,SOUND_PCM_CH2);

--- Конец кода ---

Смотрел волну в Audacity - там виден эффект "склейки" фрагментов семпла.  В оригинальном семпле такого нет.

Пробовал конвертить семпл ffmpeg'ом сразу в нужный формат:   8 bit, unsigned, 1 channel(mono), 14 000 Hz.  Улучшений не дало.

Чем это можно пофиксить?
rep-stosw:

--- Цитата: rep-stosw от 19 Декабрь 2021, 05:07:27 ---Какими функциями и их флагами нужно воспользоваться?
--- Конец цитаты ---

Вопрос с приоритетом вновь созданных спрайтов решён.
Помогла функция с флагом:


--- Код: ---SPR_setDepth(SPR_MIN_DEPTH);
--- Конец кода ---

Ещё раз констатирую гениальность Стефа - создателя SGDK!  :)

P.S. Вопрос со звуками в предыдущем посте остаётся в силе...

rep-stosw:

--- Цитата: rep-stosw от 19 Декабрь 2021, 11:51:26 ---P.S. Вопрос со звуками в предыдущем посте остаётся в силе...

--- Конец цитаты ---

Оригинал звука:

 Original.flac

Звук на эмуляторе:

 fromXGM.flac



Почему-то страдает именно этот звук.  Остальные идут нормально.

Почему  второй вариант звучит с треском и сопливо ?
rep-stosw:
Загрузил чистый синус.  Таже самая фигня.

Складывается впечатление, что данные подгружаются - из-за этого вывод звука подтормаживается.   Есть ли способ убрать эту противную задержку?  Или это издержки обращения Z80 к памяти M68K ?



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

--- Цитата: rep-stosw от 19 Декабрь 2021, 15:10:05 ---Загрузил чистый синус.  Таже самая фигня.

Складывается впечатление, что данные подгружаются - из-за этого вывод звука подтормаживается.   Есть ли способ убрать эту противную задержку?  Или это издержки обращения Z80 к памяти M68K ?
--- Конец цитаты ---

Найден виновник:


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

Без неё звучание чистое, но нет спрайтов (((

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

--- Цитата: rep-stosw от 19 Декабрь 2021, 15:10:05 ---Найден виновник:

Код:

SPR_update();

Без неё звучание чистое, но нет спрайтов (((
--- Конец цитаты ---

Расковырял SPR_update().   Основной тормоз в DMA_allocateAndQueueDma()

Что делать?  Как быть?
Ti_:

--- Цитата: rep-stosw от 19 Декабрь 2021, 15:10:05 ---Загрузил чистый синус.  Таже самая фигня.

Складывается впечатление, что данные подгружаются - из-за этого вывод звука подтормаживается.   Есть ли способ убрать эту противную задержку?  Или это издержки обращения Z80 к памяти M68K ?

(Ссылка на вложение)

Добавлено позже:
Найден виновник:


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

Без неё звучание чистое, но нет спрайтов (((

Добавлено позже:
Расковырял SPR_update().   Основной тормоз в DMA_allocateAndQueueDma()

Что делать?  Как быть?

--- Конец цитаты ---
Во время dma, у z80 нет доступа к ROM. Некоторые драйвера это обходят подгружая из rom в ram z80, и уже оттуда играют. xgm скорее всего это не делает, как и большинство драйверов. Ну можешь попробовать где-то без DMA сделать, если скорости хватит.
rep-stosw:

--- Цитата: Ti_ от 19 Декабрь 2021, 17:38:28 ---Ну можешь попробовать где-то без DMA сделать, если скорости хватит.
--- Конец цитаты ---

Попробовал.  Идея так себе. В SGDK через DMA идёт и обновление спрайтов и обновление тайлов.  Попробовал с помощью CPU это всё дело грузить.   Со спрайтами прокатило. Но этого мало.  Там через DMA ещё и обновление тайлов когда спрайт анимированный.  Повешать апдейт тайлов на VInt Не вышло - спрайты артефачили.

Из памяти M68k   в VRAM VDP перекидывал так:


--- Код: ---#define VDP_CONTROL_32 (*(volatile u32*)0xC00004)
#define VDP_DATA_32    (*(volatile u32*)0xC00000)

#define VDP_VRAM_WRITE(a)  VDP_CONTROL_32=0x40000000+(((a)&0x3FFF)<<16)+((a)>>14)

void MEM_68k_to_VRAM_VDP_via_CPU(void)
{
 u32 *src=(u32*)vdpSpriteCache;
 u32 n=(sizeof(VDPSprite)*(highestVDPSpriteIndex+1))>>2;
 VDP_VRAM_WRITE(0xF400);
 while(n--)VDP_DATA_32=*src++;
}

--- Конец кода ---

Потом  вешал на VINt:


--- Код: --- SYS_setVIntCallback(MEM_68k_to_VRAM_VDP_via_CPU);
--- Конец кода ---

В в цикле в main() вызывал:


--- Код: ---My_SPR_update()
--- Конец кода ---

Который выглядит так:


--- Код: ---void My_SPR_update(void)
{
    Sprite* sprite;

    // iterate over all sprites
    sprite = firstSprite;
    while(sprite)
    {
        u16 status = sprite->status;

        // trivial optimization
        if (status & NEED_UPDATE)
        {
            // ! order is important !
            if (status & NEED_FRAME_UPDATE)
                status = updateFrame(sprite, status);
            if (status & NEED_VISIBILITY_UPDATE)
                status = updateVisibility(sprite, status);

            // sprite not visible ?
            if (!sprite->visibility)
            {
                // need to update its visibility (done via pos Y) ?
                if (status & NEED_ST_POS_UPDATE)
                {
                    // hide sprite
                    updateSpriteTableHide(sprite);
                    status &= ~NEED_ST_POS_UPDATE;
                }
            }
            // only if sprite is visible
            else
            {
                if (status & NEED_TILES_UPLOAD)
                {
                 GlobalSprite=sprite;
                 My_loadTiles();
                }

                if (status & NEED_ST_ALL_UPDATE)
                    updateSpriteTableAll(sprite);
                else if (status & NEED_ST_POS_UPDATE)
                    updateSpriteTablePos(sprite);

                // tiles upload and sprite table done
                status &= ~(NEED_TILES_UPLOAD | NEED_ST_UPDATE);
            }

            // processes done !
            sprite->status = status;
        }

        // next sprite
        sprite = sprite->next;
    }
}


--- Конец кода ---

тайлы грузятся через CPU аналогично:


--- Код: ---void My_loadTiles(void)
{
 TileSet* tileset = GlobalSprite->frame->tileset;
 u16 lenInWord = (tileset->numTile * 32) / 4;

 u32 *src=(u32*)FAR_SAFE(tileset->tiles, tileset->numTile * 32);
 VDP_VRAM_WRITE((GlobalSprite->attribut & TILE_INDEX_MASK) * 32);
 while(lenInWord--)VDP_DATA_32=*src++;
}

--- Конец кода ---

И тут я понял, что вся графическая под-система у Стефа на ДМА и нет смысла её всю переводить на CPU, ради звуков.

Вот этот вариант:


--- Цитата ---Некоторые драйвера это обходят подгружая из rom в ram z80, и уже оттуда играют.
--- Конец цитаты ---

Вот этот вариант более интересен.

Можно ли заставить XGM движок играть семпл из памяти  Z80, предварительно скопировав его из ROM ?
SeregaZ:
rep-stosw, колись как правильно подготовить сэмпл для более менее адекватного вопроизведения. может там какой секрет есть? типа в аквалайзере низкие и высокие подрезать, а средние подкрутить?

а докучи бы еще придумать алгоритм, который более менее ровно кодирует в 4 битные DPCM... а то у меня не очень :)


хотя в данном случае пережатие было из уже пожатого источника - из 10.4к кажись... в 6.5к. и после второй раз из 8бит в 4бита по таблице DPCM для MK3.
rep-stosw:

--- Цитата: rep-stosw от 20 Декабрь 2021, 11:17:02 ---И тут я понял, что вся графическая под-система у Стефа на ДМА и нет смысла её всю переводить на CPU, ради звуков.
--- Конец цитаты ---

И тут я более понял, что нужно посмотреть dma.c что там делается. И не зря.  Там творится полный ужас - останавливается Z80 когда идёт транзакция DMA:


--- Код: ---    // define z80 BUSREQ restore state
    if (Z80_isBusTaken()) z80restore = 0x0100;
    else z80restore = 0x0000;

#if (HALT_Z80_ON_DMA != 0)
    vu16 *pw = (vu16*) Z80_HALT_PORT;

    // disable Z80 before processing DMA
    *pw = 0x0100;

    flushQueue(i);

    // re-enable Z80 after all DMA (safer method)
    *pw = z80restore;
#else
    flushQueueSafe(i, z80restore);
#endif
--- Конец кода ---

Весьма сопливое решение, когда нужно воспроизводить семплы через DAC и оперировать спрайтами-тайлами-скроллом через DMA.

В config.h  уставновил в 0 дефайн:


--- Код: ---#define HALT_Z80_ON_DMA     0
--- Конец кода ---

На свой страх и риск.

А перед SPR_update()  ждать пока Z80 не освободит шину:


--- Код: ---while(Z80_isBusTaken());
--- Конец кода ---

Всё отлично работает!  DMA успевает пролететь раньше - сразу же после освобождения шины Z80,  до того как Z80 снова её займёт.

Я рад!  Сопли в звуке прошли - все семплы  чётко и  ровно звучат, и спрайты не артефачат.  :)

Странно, что никто не пытался глубже ковырнуть этот SDK.

///


--- Цитата: SeregaZ от 21 Декабрь 2021, 13:15:47 --- колись как правильно подготовить сэмпл для более менее адекватного вопроизведения. может там какой секрет есть? типа в аквалайзере низкие и высокие подрезать, а средние подкрутить?
--- Конец цитаты ---

Ещё компрессия нужна. А вообще, это палка о двух концах.  Срезание верхов и низов делают звук плоским как из мыльницы, что не айс.


--- Цитата: SeregaZ от 21 Декабрь 2021, 13:15:47 ---а докучи бы еще придумать алгоритм, который более менее ровно кодирует в 4 битные DPCM... а то у меня не очень
--- Конец цитаты ---

IMA ADPCM сжимает обычный PCM в 4 раза.  Исходники есть в интернете, алгоритм достаточно прост.  Странно, что он ещё  не интегрирован в SGDK.

Глянул ваши видео, в частности движок звука GEMS.   Пока более интересен XGM, потому что он даёт 4 PCM канала:  1 на ударные в VGM,  и 3 - на звуки.

Рассматриваю ещё Echo, интересен конвертером треков XM в формат для сеги.

Вот если бы написали конвертер XM/IT/S3M  в VGM - было бы круто :)   

А вот VGMMaker может MOD импортировать в VGM(VGE), с подбором инструментов. Мне понравилось! Откопал банк TFI-инструментов и WAV-ударных около 30 000 с разных игр.
SeregaZ:

--- Цитата ---Пока более интересен XGM, потому что он даёт 4 PCM канала:  1 на ударные в VGM,  и 3 - на звуки.
--- Конец цитаты ---
и я и я и я того-же мнения, что для МК3 больше подошел бы XGM как раз из этого мультисэмплинга, точнее микширования сэмплов. НО! к сожалению игра содержит некое количество эффектов, которые воспроизводятся с помощью FM звуков. XGM такое не умеет. ему подавай спецэффекты в виде сэмплов - wav'ок. поэтому мы предали XGM анафеме.

по поводу размеров сэмплов - может IMA ADPCM и круче в плане занимаемого места, но для MK3 не подходит. там не оригинальный дравер GEMS - а химиченый, где добавили возможность играть два сэмпла одновременно, но правда ценой говёного качества - 6.5k (против 14к у XGM и против 10.4k у оригинального GEMS). поэтому в целях совместимости надо пережимать сэмпл в его родной DPCM, по таблице из 16 значений. понятно что будут потери... но оригинальные сэмплы звучат прям очень даже неплохо. хотелось бы знать каким образом они подходили к этому делу, чтобы можно было делать более менее похоже и хорошо. то есть знать бы какие предварительные танцы с бубном эти наши пращуры делали в 90годах, когда пилили МК3.

второй момент почему этого нет в XGM - видимо экономят циклы процессоров, чтобы не тратить производительность на разжатие. может быть vgm файлы и стали бы меньше по размеру, но это не имеет смысла, так как сэмплы там (по моему и это не точно) играют путем спама содержимого сэмпла в регистр... эээ... $2A? то есть по байтно бомбит в этот регистр ямахи и ямаха это играет. этот спам по идее записан в vgm файле. впрочем это могут быть и оптимизированные vgm'ки - где сэмплы вынесены в специальный раздел файла, и проигрывание происходит путем вызова из этой библиотеки, а не побайтная запись значений регистра во времени в файле. хотя система все равно должна будет бомбить этот регистр для проигрывания.

поэтому я вот и страдаю в поисках подобного алгоритма пережатия в DPCM и предварительной подготовки самого сэмпла.
rep-stosw:

--- Цитата: SeregaZ от 21 Декабрь 2021, 19:19:45 ---второй момент почему этого нет в XGM - видимо экономят циклы процессоров, чтобы не тратить производительность на разжатие. может быть vgm файлы и стали бы меньше по размеру, но это не имеет смысла, так как сэмплы там (по моему и это не точно) играют путем спама содержимого сэмпла в регистр... эээ... $2A? то есть по байтно бомбит в этот регистр ямахи и ямаха это играет. этот спам по идее записан в vgm файле. впрочем это могут быть и оптимизированные vgm'ки - где сэмплы вынесены в специальный раздел файла, и проигрывание происходит путем вызова из этой библиотеки, а не побайтная запись значений регистра во времени в файле. хотя система все равно должна будет бомбить этот регистр для проигрывания.
--- Конец цитаты ---

К сожалению у Генезиса нет DMA для семплов, как это сделано в SNES и даже в NES.   Зилог ручками пуляет каждый семпл в YM2612 и даже без FIFO.

В VGM семплы DAC хранятся в единственном количестве.  Очень давно, я прикручивал YM2612 к LPT-порту компа и писал свой плеер-парсер VGM.  Правда, из-за ограниченной скорости самого LPT-порта, некоторые ударные через DAC играли медленно и затормаживали воспроизведение VGM (например, из игр: Alien3, T2 Arcade game).


--- Цитата ---0x67, 0x66, tt, ss, ss, ss, ss – конкретно:
0x67 – маркер блока данных для DAC
0x66 – конец потока (здесь эта под-команда игнорируется!)
tt – тип данных (должно =0 – это значит YM2612 PCM data)
ssssssss – объём данных для DAC в байтах
Здесь логично запомнить смещение данных для DAC, тоесть начальный указатель
на PCM data в VGM-файле. Указатель музыкального потока увеличивается на ssssssss+7.

0x8* - конкретно:
A1=0 – выбираем Bank0
[0x2A]=Digital[Offset]
Задержка на * сэмплов
Увеличиваем Offset на 1 (указатель на PCM data)
Увеличиваем указатель потока на 1
Попросту говоря, данная команда пихает в DAC один байт PCM-данных (указатель
на PCM вычисляется командами 0x67 и 0xE0). Далее задержка на * сэмплов и увеличение
указателей музыкального потока и PCM data на 1.

0xE0, dd, dd, dd, dd – вычисление увеличения указателя на PCM data. Итоговое
значение указателя PCM data в данный момент: Offset=dddddddd+Адрес начала данных
для DAC в VGM-файле (адрес байта, следующего сразу после команды 0x67, 0x66, tt, ss,
ss, ss, ss). Указатель музыкального потока увеличивается на 5.

--- Конец цитаты ---


--- Цитата: SeregaZ от 21 Декабрь 2021, 19:19:45 --- НО! к сожалению игра содержит некое количество эффектов, которые воспроизводятся с помощью FM звуков. XGM такое не умеет. ему подавай спецэффекты в виде сэмплов - wav'ок. поэтому мы предали XGM анафеме.
--- Конец цитаты ---

При написании игры, я сразу решил, что SFX - будут оцифровки, BGM -> 5FM + DAC + 4 PSG.

Сейчас озадачен выбором фоновой музыки для игры:

1. Брать VGM-ки с сеговских игр или демо из трекеров не хочется, так как это баяны, хоть и шедевральные, и с музыкой там всё ОК.

2. Пробовали VST GennyFL. Результат не понравился: итоговый VGM получается на несколько МБ, ноты проглатываются или наоборот вылезают. Часть каналов пропадает на реальной сеге.

3. Пробовали Deflemask.  В техническом плане для сеги - он очень крут: трек звучит также как и написали.  Но: большинство просто не могут написать полноценную музыкальную композицию с началом, раскачкой, активной частью, припевом, завершением, скруглением.   В итоге у большинства получается просто простой цикл на 10 - 20  секунд, и его повторы, разбавленные парой инструментов.

4. Лично пробовал переносить безымянные треки в формате MOD (с Амиги, 4 канала до 14 инструментов(?)) в VGE(VGM) с помощью VGMMaker и банка инструментов.   За шесть часов более-менее удалось подобрать схожие инструменты, подтюнить октавы.   Получается тот же трек что и MOD, но сыгранный инструментами YM2612.   Отдельно вручную прописывал ударные партии на 6-й канал  (DAC). В некоторых MOD, ударные размылены на несколько каналов - приходится  сводить в 1 канал.   К сожалению, OpenMPT далёк от удобного функционала - не хватает функции объединения выбранных инструментов в одну дорожку.
Результат порадовал - композиция трека сохраняется (нотная партия), музыка на несколько голов сложнее, чем простой копирование "тупо одного цикла по 10 с".

5. MID2VGM. Пока не успел с ним разобраться.

6. XM2ESF.  С наскоку не понял  как с ним возиться.

Для меня конечно, пока предпочтителен способ (4),  чем способы (2) и (3).  Как показала практика, фрилансеры ничего путного не напишут.
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

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