Разработка и ромхакинг > Программирование
[SMD] SGDK
<< < (40/42) > >>
Sharpnull:

--- Цитата: ALKOSHA от 18 Июль 2022, 20:23:51 ---Ничего не поменялось. Оффсет адреса тот же.
--- Конец цитаты ---
Вы передали указатель на указатель: SPR_setVRAMTileIndex(sprites,ind);, а у вас массив из указателей, нужно SPR_setVRAMTileIndex(sprites[0], ind);. Включите как можно больше предупреждений компилятора, читайте их и исправляйте.
ALKOSHA:
Оо, дело сдвинулось с мёртвой точки.
Но будто бы графика спрайта задевает состояние регистров сдвига слоя.
Хотя тут вроде бы с запасом впереди после графики спрайта ещё char-set есть, а дальше уже каша из состояний сдвига, разве не так?
странно покосило слой прокрутки


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

--- Цитата: Sharpnull от 18 Июль 2022, 21:26:58 ---Вы передали указатель на указатель: SPR_setVRAMTileIndex(sprites,ind);, а у вас массив из указателей, нужно SPR_setVRAMTileIndex(sprites[0], ind);. Включите как можно больше предупреждений компилятора, читайте их и исправляйте.

--- Конец цитаты ---
тут ты не прав.
Sprite sprites[8] - тут sprites это указатель на первый обьект Sprite в массиве
а sprites[0] - это уже экземплаяр самого Sprite

так что передать sprites в качестве указателя на первый объект в массиве это вполне правильно

можно даже на второй и третий передавать вот так: sprites + 1, sprites + 2, вместо &sprites[1] и &sprites[2]
и разницы к тому же никакой нет, компилятор одинаково представит и sprites, и &sprites[0]
Sharpnull:

--- Цитата: Segaman от 21 Июль 2022, 06:41:16 ---Sprite sprites[8] - тут sprites это указатель на первый обьект Sprite в массиве
--- Конец цитаты ---
Там Sprite *sprites[80];, а Sprite sprites[80] не получится, ведь SPR_addSprite() возвращает указатель на Sprite.
ALKOSHA:
Я изначально использую квадовую топологию. И вот щас думаю, а не поторопился ли я с таким решением. Может два триангла СДК закрашивает быстрее, чем один квад? Как думаете? Или там один универсальный алгоритм на любой тип многоугольников, и роли не играет?
lupus:
Чили-Вилли выложил свой набор для разработки:
https://segaxtreme.net/threads/my-current-devkit-for-md-cd-32x.25273/
GremLinN:
Всем привет! вливаюсь в sgdk. сам я нубас в программировании, и у меня возникла куча вопросов по базовым вещам.

первое это память.

1. как в SGDK следить за загрузкой оперативной памяти, чтобы не превышать её?
2. как вообще разделяется память на то что лежит в роме и что сейчас находится в ОП.
Допустим, вот рекомпайлер компилирует картинку. он генерирует константу в которой есть палитра, тайлсет, тайлмап. и записывает ее объявление в заголовок resources.h( кстати, где в проекте, и  в какой форме у этой картинки после компиляции хранится реализация?)
Я так понимаю что все это как то отправится в ром.  а вот если я объявлю массив в теле программы.
u8 array[MAX_NUM] = {1,0,1,0,1,0,0,0....};
то он сразу займет место в оперативной памяти? как сделать так чтобы этот массив тоже сначала в ром записался, а я его потом по ссылке мог вызвать?
3 сгдк сам то жрет ченить по памяти? или он начинает жрать после объявления функций типа SPR_init();?


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

--- Цитата: ALKOSHA от 27 Август 2022, 19:55:32 ---Я изначально использую квадовую топологию. И вот щас думаю, а не поторопился ли я с таким решением. Может два триангла СДК закрашивает быстрее, чем один квад? Как думаете? Или там один универсальный алгоритм на любой тип многоугольников, и роли не играет?

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

обычно в 3д производительность зависит от количества точек (векторов) в модели и площади заполнения.
топология с квадами используется только для качественного сабдивижна.
Sharpnull:

--- Цитата: GremLinN от 07 Сентябрь 2022, 23:07:03 ---1. как в SGDK следить за загрузкой оперативной памяти, чтобы не превышать её?
--- Конец цитаты ---
Глобальную память должен отслеживать компилятор и выдать ошибку на этапе компиляции, но я не пробовал. Поэтому глобальную память нужно беречь, туда же относится static память в функциях, она ведь глобальная. Переменные определённые в функциях исчезнуть после вызова, это обычная логика языка C и не только.
В memory.c есть динамическое выделение памяти, которую также использует сам SGDK, там есть MEM_getFree(), чтобы узнать свободное место и MEM_alloc() вернёт NULL, если не получилось выделить. Также можно узнать о нехватке памяти, не проверяя возврат MEM_alloc(), через просмотр лога в эмуляторе, который поддерживает KDebug (KLog), например, видно использование KLog_*(): https://github.com/Stephane-D/SGDK/blob/868f2d55f3d28270750a924e275c0e53e4d6ec67/src/memory.c#L270. Также в pool.c, но не вижу KLog.

--- Цитата: GremLinN от 07 Сентябрь 2022, 23:07:03 ---кстати, где в проекте, и  в какой форме у этой картинки после компиляции хранится реализация?
--- Конец цитаты ---
В out хранятся временные файлы, если был res\resources.res, то после компиляции будет res\resources.h и out\res\resources.o с данными, но всё что в out вас не должно волновать и можно удалить.

--- Цитата: GremLinN от 07 Сентябрь 2022, 23:07:03 ---вот если я объявлю массив в теле программы.
u8 array[MAX_NUM] = {1,0,1,0,1,0,0,0....};
то он сразу займет место в оперативной памяти? как сделать так чтобы этот массив тоже сначала в ром записался, а я его потом по ссылке мог вызвать?
--- Конец цитаты ---
Да, скорее всего. Нужно объявлять глобальные переменные как const, чтобы они были в роме, при этом, если вы делаете массив из константных указателей на константные данные, то const нужно указывать 2 раза. Локальные переменные в main() очевидно тоже будут занимать память на протяжении всей игры.

--- Цитата: GremLinN от 07 Сентябрь 2022, 23:07:03 --- сгдк сам то жрет ченить по памяти? или он начинает жрать после объявления функций типа SPR_init();?
--- Конец цитаты ---
Он будет жрать и так, конечно, но вы правильно заметили, что инициализация подсистем будет отнимать память, в некоторых случаях в документации указано, сколько примерно будет съедено памяти. Лучше всего смотреть исходный код. Например, SPR_init() это SPR_initEx(420), где 420 - сколько будет зарезервировано тайлов в VRAM, а в исходном коде SGDK будет видно, что сразу выделяется RAM для спрайтов через POOL_create(MAX_SPRITE, sizeof(Sprite)). Кстати, только сейчас узнал у новом pool.h, как там и написано, это например подходит для пуль, в играх для современных систем (ПК, консоли) без пула объектов никуда, каждый раз выделять память очень медленно.
Вот небольшая инструкция по установке SGDK и сборке проекта, которую я писал для одного человека:
# SGDK
Установка как здесь https://github.com/Stephane-D/SGDK/wiki/SGDK-Installation. После обновления SGDK стоит всегда запускать build_lib.bat для сборки библиотек lib\libmd.a и lib\libmd_debug.a.
Для последней версии SGDK скачать репозиторий (https://github.com/Stephane-D/SGDK, Code > Download ZIP и запуск build_lib.bat), но, кроме исправлений, там могут быть проблемы (например, у меня сейчас не происходит сборка релизного рома, только в debug режиме).
Я использую GDK_WIN из переменных среды как путь к SGDK, поэтому в переменные среды нужно добавить GDK_WIN с путём вида C:\sgdk.
Информации на wiki мало, полезнее посмотреть код примеров в sample. Документация по функциям в sgdk\doc\index.html. Чтобы разобраться лучше и написать свои версии функций, придётся смотреть код реализации в src. При обновлении SGDK часто происходит переименовывание функций и констант, тогда нужно адаптировать код, в чём помогут доки и примеры.

# Сборка кода в SGDK
В папке проекта src, inc, res, out (https://github.com/Stephane-D/SGDK/wiki/SGDK-Usage). В inc заголовочные файлые .h. В res ресурсы и описываются они в .res файлах, для каждого там генерируется .h, чтобы обращаться в коде. В src код .c, там генерируется папка boot один раз и после обновления sgdk её нужно удалять, иначе будет ошибка, в ней rom_head.c где можно изменить данные заголовка рома. В out временные файлы после сборки и сам ром.
Для сборки рома нужно выполнить в командной строке, находясь в папке проекта:
%GDK_WIN%\bin\make -f %GDK_WIN%\makefile.gen
Если не указывать GDK_WIN в переменных среды, то вместо %GDK_WIN% должен быть путь до SGDK.
Если ресурсы изменились или были изменения в .h файле, то сборщик будет использовать старые данные из out и будет ошибка и неверное поведение, тогда перед сборкой нужно очистить вызовом:
%GDK_WIN%\bin\make -f %GDK_WIN%\makefile.gen clean
Также можно просто удалить папку out. Если файлы проекта добавлялись, удалялись, у них менялись имена, то после очистки останутся файлы, так что периодически стоит удалять out для экономии места.
Проще всего написать команды выше в .bat файл чтобы делать сборку его запуском.Но вообще я не эксперт.
UPD: Не знаю как делают профи в SGDK, но получение свободной RAM во время игры думаю возможно, хотя бы частично, силами эмулятора (Lua или сам эмулятор), если разобрать как выделяется память в SGDK.
GremLinN:
спасибо за ответ!

--- Цитата: Sharpnull от 08 Сентябрь 2022, 02:28:34 ---В memory.c есть динамическое выделение памяти, которую также использует сам SGDK, там есть MEM_getFree(), чтобы узнать свободное место и MEM_alloc() вернёт NULL, если не получилось выделить. Также можно узнать о нехватке памяти, не проверяя возврат MEM_alloc()
--- Конец цитаты ---

а я правильно понимаю что эти команды это аналог стандартных malloc(); calloc();realloc(); free() ?  то есть стандартные библиотеки си в CGDK работать не будут вообще, и стеф все переписал?

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

значит поставил я сгдк по этому туториалу https://www.ohsat.com/tutorial/megapong/megapong-2/ на VScode. там есть спец плагин gencode, все очень удобно включается, но я совершенно не понимаю как это все работает в связке.

моя цель понять общие правила работы с фреймворками(сдгк ведь считается фреймворком? или это просто библиотека?), исходным кодом, и вообще как проекты настраиваются в популярных IDE. Есть ли общие правила для всех IDE или для каждой IDE все индивидуально? допустим в VScode добавляет в проект какие то папки с файлами настройки .vscode в которых я наощупь прописал пути. Но в других семплах для сгдк ,которые я скачивал для обучения, нет ничего подобного. ну или лежат какие то фалы настройки вообще в другом месте  и в другом формате. как тут разобраться?

Я начал смотреть как программы компилируются. и чето прям все не то что надо. по си  справочники про это говорят как то вскользь , делают упор на самом языке.
вот на хабре нашел общую информацию
что есть прекомпайлер , котом компайлер в ассемблер, потом подключается линковщик, после собирается файл. Где это все относительно сгдк смотреть? а есть еще какие то сборщики. вот что делает make.exe в сгдк? почему он создает libmd с расширением .a? если это статическая библиотека под виндоус она же должна иметь расширение . lib?
как вообще это гуглить? у меня полный сумбур в голове. Я раньше разбирался в юнити там все просто было, там одно средство и одни правила поведения.

Вот например компилятор.  Есть расширение с\с++ для VScode,  без него не будет возможности программировать под си. в настройках этого расширения нужно принудительно указать компилятор из большой визуал студии. (да я поставил еще и саму студию 19 лол).
и все вроде бы идет нормально. но тут я читаю форумы и люди пишут что Стэф использует какой то свой компилятор. Бдыщь. ну правильно думаю, нужен же компилятор под 68к, ан нет он использует какойто стандартный gcc старой версии. но он же для для х86? он что поставляется вместе с сгдк?  а как он тогда прописывается в VScode у меня же в настройках стоит от визуал студии?

еще в VScode  есть терминал. там можно выбирать профиль терминала. то есть получается для каждого компилятора свои терминал? их можно как-то настраивать. с сгдк у меня работает только профиль gen code  просто если я выбираю какой-нибудь повершелл, компиляция не проходит сыпет ошибками.


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



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

--- Цитата: lupus от 28 Август 2022, 17:14:49 ---Чили-Вилли выложил свой набор для разработки:
https://segaxtreme.net/threads/my-current-devkit-for-md-cd-32x.25273/

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

например, как мне взять эти тулзы и настроить их с VScode под виндоус? там нет четкой инструкции. что делать в такой ситуации?
Born_Free:
Ведь в туториал для SGDK указано, что он под Си язык.. Разве это Си? У меня при создании нового проекта вышло так. Ну, я недавно начал изучать и может не до конца разобрался..

--- Код: ---int main()
{
VDP_drawText("Hello World!!", 10,13);
while(1)
{
//For versions prior to SGDK 1.60 use VDP_waitVSync instead.
SYS_doVBlankProcess();
--- Конец кода ---

Разве не так должно быть? 🤷🏼‍♂️

--- Код: ---int main()
printf("Hello World");
return 0;
--- Конец кода ---
Sharpnull:

--- Цитата: Born_Free от 02 Март 2024, 19:25:19 ---Разве не так должно быть?
--- Конец цитаты ---
Вы путаете функции и язык. Если добавить фигурные скобки, то оба куска кода на языке C. В SGDK нет функции printf(), для вывода текста используется своя. Ещё учитывайте, что в разных версиях SGDK некоторые функции меняют имя и набор аргументов, а также константы меняются.
Born_Free:

--- Цитата: Sharpnull от 02 Март 2024, 19:37:16 ---Вы путаете функции и язык. Если добавить фигурные скобки, то оба куска кода на языке C. В SGDK нет функции printf(), для вывода текста используется своя. Ещё учитывайте, что в разных версиях SGDK некоторые функции меняют имя и набор аргументов, а также константы меняются.

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


Ужас! 😮 Возникает тогда вопрос, а чем это тогда упрощает процесс создания игрушки с нуля?

Последняя у меня версия SGDK 2.00 (January 2024).
Cyneprepou4uk:
Born_Free, сега это не консольное приложение, там свои приколы. И никто тебе не запрещает писать игру непосредственно на ассемблере, если думаешь что это проще.
Talking_Sword:
Кстати, не совсем понимаю, для чего нужно "while(1)"?
Беларус:
Обычно ожидание ответа, в данном случае от SYS_doVBlankProcess();. Наверно, ждёт возвращения луча или что-то такое, а пока программа далее не пойдёт.
Красивее делать while(true), т.к. 1 - это уже "магическое", непонятное число.
Sharpnull:

--- Цитата: Born_Free от 02 Март 2024, 21:56:44 ---чем это тогда упрощает процесс создания игрушки с нуля?
--- Конец цитаты ---
Смысл использования языка C для разработки игр для MD такой же как и смысл его существования. На C для MD можно писать не только с помощью SGDK, но SGDK включает много полезных функций и возможностей. В SGDK есть как "низкоуровневые" функции, так и "высокоуровневые", которые используют низкоуровневые и позволяют меньше тратить времени, но для продвинутой или специфичной игры придётся использовать низкоуровневые.
UPD: Кстати, в SGDK есть имитация консоли, но без printf. Есть отдельно похожие функции из библиотеки C такие как strlen(), strcmp() и sprintf(), которая заменяет printf(), например:

--- Код: ---char str[16];
sprintf(str, "%u/%u", currentImageIndex + 1, (u16)ARRAY_SIZE(images));
VDP_drawTextEx(BG_B, str, TILE_ATTR(PAL1, 0, 0, 0), 2, 2, CPU);
--- Конец кода ---

--- Цитата: Talking_Sword от 03 Март 2024, 07:41:36 ---для чего нужно "while(1)"?
--- Конец цитаты ---
Если это весь кусок, то только для отображения текста, нет смысла выходить из main(). Обычно в играх есть основной игровой цикл, для SGDK это выглядит как бесконечный цикл после инициализации, в котором ожидают VBlank через SYS_doVBlankProcess() (там происходит и доп. работа, в доках написано), туда ещё добавляют чтение ввода и остальную логику игры. Не обязательно делать один цикл и можно делать ожидание VBlank внутри этого цикла или можно в бесконечном цикле вызывать только функцию по указателю, который содержит разные функции во время игры, ожидающие VBlank сами. Возможно по аналогии с NES играми можно весь код засунуть в обработчик VBlank, тогда в main() будет просто бесконечный цикл.

--- Цитата: perfect_genius от 03 Март 2024, 13:29:16 ---Красивее делать while(true)
--- Конец цитаты ---
В случае с SGDK - while (TRUE). Мне ещё нравится for (;;) {}, а для непонятливых можно while ("the cartridge is inserted") {} - ром будет точно такой же как с while (TRUE) {}, я проверил, тривиальная оптимизация работает.
ALKOSHA:
Есть идеи, как подготовить ресурсы/прописать процедурку для реализации такого скейла?





Походу таким макаром сделано масштабирование спрайтов в Road Rash, Scitchin, в заставках BT&DD (текст и приближающаяся Земля).

Добавлено позже:
Я щас как раз озадачился реализацией псевдо-недо-3д движка на сегу.
И пока вот думаю, или таким вот растягиванием-скукоживанием тайлов каждого спрайта скейлить объекты. Ну или рисовать мип-мапы сразу тайлами BG_A или BG_B

https://t.me/sega_punk/150
Sharpnull:

--- Цитата: ALKOSHA от 09 Сентябрь 2025, 22:01:51 ---Есть идеи, как подготовить ресурсы/прописать процедурку для реализации такого скейла?
--- Конец цитаты ---
Про ресурсы не знаю, видно, что нужно создать изображения кратные 8 px, это делается как удобнее. В коде можно вручную задать смещения для каждого размера в массиве (по осям X и Y почему-то отличаются смещениями в данном пример), по данным координатам и размерам на выходе координаты каждого тайла.
ALKOSHA:

--- Цитата: Sharpnull от 10 Сентябрь 2025, 15:21:31 ---Про ресурсы не знаю, видно, что нужно создать изображения кратные 8 px, это делается как удобнее. В коде можно вручную задать смещения для каждого размера в массиве (по осям X и Y почему-то отличаются смещениями в данном пример), по данным координатам и размерам на выходе координаты каждого тайла.

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

Ну это муторно для каждого тайла создавать по целому файлу, а затем ещё и инициализировать по-тайлово... думал, может можно как-то автоматизировать сей процесс.

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

--- Цитата: ALKOSHA от 10 Сентябрь 2025, 22:16:45 ---по осям X и Y почему-то отличаются смещениями в данном пример
--- Конец цитаты ---
Та вроде линейная итерация. 
ALKOSHA:
 Yu Yu Hakusho: Makyo Toitsusen тоже таким же способом скейлит спрайты.
Но там сегменты не 8х8, а кастомные. И без мип-мапинга, ибо диапазон скейла сильно ограничен.





Но мне без мип-мапинга никак. У меня галубокое три дэээ... Пока тренюсь на строго фронтальном перемещении Z, без тригонометрии. Но мечтаю добавить ещë cos sin поворот камеры, чтоб реализовать сëрд-пëрсон 3д графон на спрайто-тайлах.
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

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