Автор Тема: SGDK  (Прочитано 74336 раз)

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

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5005
    • Просмотр профиля
SGDK
« Ответ #780 : 18 Июль 2022, 21:26:58 »
Ничего не поменялось. Оффсет адреса тот же.
Вы передали указатель на указатель: SPR_setVRAMTileIndex(sprites,ind);, а у вас массив из указателей, нужно SPR_setVRAMTileIndex(sprites[0], ind);. Включите как можно больше предупреждений компилятора, читайте их и исправляйте.

Оффлайн ALKOSHA

  • Пользователь
  • Сообщений: 805
  • Люблю донди.
    • ВКонтакте
    • Просмотр профиля
SGDK
« Ответ #781 : 18 Июль 2022, 21:59:27 »
Оо, дело сдвинулось с мёртвой точки.
Но будто бы графика спрайта задевает состояние регистров сдвига слоя.
Хотя тут вроде бы с запасом впереди после графики спрайта ещё char-set есть, а дальше уже каша из состояний сдвига, разве не так?
странно покосило слой прокрутки


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

Оффлайн Segaman

  • Пользователь
  • Сообщений: 3240
  • Пол: Мужской
  • Blast Processing!
    • Youtube
    • Просмотр профиля
SGDK
« Ответ #782 : 21 Июль 2022, 06:41:16 »
Вы передали указатель на указатель: 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

  • Пользователь
  • Сообщений: 5005
    • Просмотр профиля
SGDK
« Ответ #783 : 21 Июль 2022, 06:54:14 »
Sprite sprites[8] - тут sprites это указатель на первый обьект Sprite в массиве
Там Sprite *sprites[80];, а Sprite sprites[80] не получится, ведь SPR_addSprite() возвращает указатель на Sprite.

Оффлайн ALKOSHA

  • Пользователь
  • Сообщений: 805
  • Люблю донди.
    • ВКонтакте
    • Просмотр профиля
SGDK
« Ответ #784 : 27 Август 2022, 19:55:32 »
Я изначально использую квадовую топологию. И вот щас думаю, а не поторопился ли я с таким решением. Может два триангла СДК закрашивает быстрее, чем один квад? Как думаете? Или там один универсальный алгоритм на любой тип многоугольников, и роли не играет?

Оффлайн lupus

  • Пользователь
  • Сообщений: 3812
  • Пол: Мужской
  • man with no face
    • ВКонтакте
    • Просмотр профиля
SGDK
« Ответ #785 : 28 Август 2022, 17:14:49 »
Чили-Вилли выложил свой набор для разработки:
https://segaxtreme.net/threads/my-current-devkit-for-md-cd-32x.25273/

Оффлайн GremLinN

  • Пользователь
  • Сообщений: 2
  • sega-mega
    • Просмотр профиля
SGDK
« Ответ #786 : 07 Сентябрь 2022, 23:07:03 »
Всем привет! вливаюсь в sgdk. сам я нубас в программировании, и у меня возникла куча вопросов по базовым вещам.

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

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


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

обычно в 3д производительность зависит от количества точек (векторов) в модели и площади заполнения.
топология с квадами используется только для качественного сабдивижна.
« Последнее редактирование: 08 Сентябрь 2022, 02:13:07 от GremLinN »

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5005
    • Просмотр профиля
SGDK
« Ответ #787 : 08 Сентябрь 2022, 02:28:34 »
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.
кстати, где в проекте, и  в какой форме у этой картинки после компиляции хранится реализация?
В out хранятся временные файлы, если был res\resources.res, то после компиляции будет res\resources.h и out\res\resources.o с данными, но всё что в out вас не должно волновать и можно удалить.
вот если я объявлю массив в теле программы.
u8 array[MAX_NUM] = {1,0,1,0,1,0,0,0....};
то он сразу займет место в оперативной памяти? как сделать так чтобы этот массив тоже сначала в ром записался, а я его потом по ссылке мог вызвать?
Да, скорее всего. Нужно объявлять глобальные переменные как const, чтобы они были в роме, при этом, если вы делаете массив из константных указателей на константные данные, то const нужно указывать 2 раза. Локальные переменные в main() очевидно тоже будут занимать память на протяжении всей игры.
сгдк сам то жрет ченить по памяти? или он начинает жрать после объявления функций типа SPR_init();?
Он будет жрать и так, конечно, но вы правильно заметили, что инициализация подсистем будет отнимать память, в некоторых случаях в документации указано, сколько примерно будет съедено памяти. Лучше всего смотреть исходный код. Например, SPR_init() это SPR_initEx(420), где 420 - сколько будет зарезервировано тайлов в VRAM, а в исходном коде SGDK будет видно, что сразу выделяется RAM для спрайтов через POOL_create(MAX_SPRITE, sizeof(Sprite)). Кстати, только сейчас узнал у новом pool.h, как там и написано, это например подходит для пуль, в играх для современных систем (ПК, консоли) без пула объектов никуда, каждый раз выделять память очень медленно.

Вот небольшая инструкция по установке SGDK и сборке проекта, которую я писал для одного человека:
Но вообще я не эксперт.

UPD: Не знаю как делают профи в SGDK, но получение свободной RAM во время игры думаю возможно, хотя бы частично, силами эмулятора (Lua или сам эмулятор), если разобрать как выделяется память в SGDK.
« Последнее редактирование: 08 Сентябрь 2022, 04:33:36 от Sharpnull »

Оффлайн GremLinN

  • Пользователь
  • Сообщений: 2
  • sega-mega
    • Просмотр профиля
SGDK
« Ответ #788 : 08 Сентябрь 2022, 18:39:25 »
спасибо за ответ!
В 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  просто если я выбираю какой-нибудь повершелл, компиляция не проходит сыпет ошибками.


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



Добавлено позже:
Чили-Вилли выложил свой набор для разработки:
https://segaxtreme.net/threads/my-current-devkit-for-md-cd-32x.25273/

например, как мне взять эти тулзы и настроить их с VScode под виндоус? там нет четкой инструкции. что делать в такой ситуации?

Оффлайн Born_Free

  • Пользователь
  • Сообщений: 13
    • Просмотр профиля
SGDK
« Ответ #789 : 02 Март 2024, 19:25:19 »
Ведь в туториал для 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

  • Пользователь
  • Сообщений: 5005
    • Просмотр профиля
SGDK
« Ответ #790 : 02 Март 2024, 19:37:16 »
Разве не так должно быть?
Вы путаете функции и язык. Если добавить фигурные скобки, то оба куска кода на языке C. В SGDK нет функции printf(), для вывода текста используется своя. Ещё учитывайте, что в разных версиях SGDK некоторые функции меняют имя и набор аргументов, а также константы меняются.

Оффлайн Born_Free

  • Пользователь
  • Сообщений: 13
    • Просмотр профиля
SGDK
« Ответ #791 : 02 Март 2024, 21:56:44 »
Вы путаете функции и язык. Если добавить фигурные скобки, то оба куска кода на языке C. В SGDK нет функции printf(), для вывода текста используется своя. Ещё учитывайте, что в разных версиях SGDK некоторые функции меняют имя и набор аргументов, а также константы меняются.


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

Последняя у меня версия SGDK 2.00 (January 2024).

Оффлайн Cyneprepou4uk

  • Пользователь
  • Сообщений: 205
  • Пол: Мужской
  • Самый лысый ромхакер
    • ВКонтакте
    • Просмотр профиля
SGDK
« Ответ #792 : 03 Март 2024, 00:49:30 »
Born_Free, сега это не консольное приложение, там свои приколы. И никто тебе не запрещает писать игру непосредственно на ассемблере, если думаешь что это проще.

Оффлайн Talking_Sword

  • Пользователь
  • Сообщений: 899
  • Happy Games Only!
    • Просмотр профиля
SGDK
« Ответ #793 : 03 Март 2024, 07:41:36 »
Кстати, не совсем понимаю, для чего нужно "while(1)"?

Оффлайн perfect_genius

  • Пользователь
  • Сообщений: 1144
    • ВКонтакте
    • Steam
    • Просмотр профиля
SGDK
« Ответ #794 : 03 Март 2024, 13:29:16 »
Обычно ожидание ответа, в данном случае от SYS_doVBlankProcess();. Наверно, ждёт возвращения луча или что-то такое, а пока программа далее не пойдёт.
Красивее делать while(true), т.к. 1 - это уже "магическое", непонятное число.

Оффлайн Sharpnull

  • Пользователь
  • Сообщений: 5005
    • Просмотр профиля
SGDK
« Ответ #795 : 03 Март 2024, 16:13:32 »
чем это тогда упрощает процесс создания игрушки с нуля?
Смысл использования языка 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);
для чего нужно "while(1)"?
Если это весь кусок, то только для отображения текста, нет смысла выходить из main(). Обычно в играх есть основной игровой цикл, для SGDK это выглядит как бесконечный цикл после инициализации, в котором ожидают VBlank через SYS_doVBlankProcess() (там происходит и доп. работа, в доках написано), туда ещё добавляют чтение ввода и остальную логику игры. Не обязательно делать один цикл и можно делать ожидание VBlank внутри этого цикла или можно в бесконечном цикле вызывать только функцию по указателю, который содержит разные функции во время игры, ожидающие VBlank сами. Возможно по аналогии с NES играми можно весь код засунуть в обработчик VBlank, тогда в main() будет просто бесконечный цикл.
Красивее делать while(true)
В случае с SGDK - while (TRUE). Мне ещё нравится for (;;) {}, а для непонятливых можно while ("the cartridge is inserted") {} - ром будет точно такой же как с while (TRUE) {}, я проверил, тривиальная оптимизация работает.
« Последнее редактирование: 03 Март 2024, 16:26:25 от Sharpnull »