6.1 KiB
6.1 KiB
Вот доработанная версия с общими переменными между основной программой и модулями. Мы создадим единую структуру GameState, которая будет передаваться в каждый модуль.
1. Общий заголовок (SHARED.H)
// Структура для общих переменных игры
typedef struct {
int lives; // Количество жизней
int level; // Текущий уровень
bool is_paused; // Состояние паузы
uint32_t score; // Счёт игрока
} GameState;
// Заголовок модуля
typedef void (*ModuleEntry)(GameState*); // Тип функции-входа
typedef struct {
uint32_t magic; // 0x55AA1234
ModuleEntry entry; // Функция входа
uint32_t size; // Размер модуля
} ModuleHeader;
2. Основная программа (MAIN.C)
#include <libetc.h>
#include <libcd.h>
#include "SHARED.H"
#define MODULE_ADDR 0x80030000 // Адрес загрузки модулей
GameState game_state = {
.lives = 3,
.level = 1,
.is_paused = false,
.score = 0
};
void load_and_run_module(int sector, int size) {
CdRead(sector, (uint32_t*)MODULE_ADDR, size);
CdReadSync(0);
ModuleHeader *header = (ModuleHeader*)MODULE_ADDR;
if (header->magic == 0x55AA1234) {
header->entry(&game_state); // Передаём указатель на game_state
}
}
int main() {
ResetGraph(0);
CdInit();
FntLoad(960, 256);
FntOpen(16, 16, 256, 224, 0, 512);
while (1) {
// Обновляем общие переменные
game_state.score += 10;
FntPrint("Main: Lives=%d, Score=%d\n", game_state.lives, game_state.score);
// Загружаем и выполняем модули
load_and_run_module(MODULE_MDEC_SECTOR, MODULE_MDEC_SIZE);
load_and_run_module(MODULE_GPU_SECTOR, MODULE_GPU_SIZE);
VSync(0);
}
}
3. Модуль для MDEC (MODULE_MDEC.C)
#include <libmdec.h>
#include "SHARED.H"
void module_entry(GameState *state) {
// Читаем и изменяем общие переменные
if (state->lives > 0) {
state->lives--; // Уменьшаем жизни
FntPrint("MDEC: Lives left=%d\n", state->lives);
}
// Декодируем видео только если игра не на паузе
if (!state->is_paused) {
uint8_t data[1024];
uint16_t buffer[256*256];
MDEC_DecodeFrame(data, buffer, MDEC_MODE_RGB24);
}
}
ModuleHeader __header__ __attribute__((section(".header"))) = {
.magic = 0x55AA1234,
.entry = module_entry,
.size = 0
};
4. Модуль для GPU (MODULE_GPU.C)
#include <libgpu.h>
#include "SHARED.H"
void module_entry(GameState *state) {
// Проверяем глобальный статус
if (state->is_paused) {
FntPrint("GPU: Game is paused!\n");
return;
}
// Рисуем HUD с общими переменными
char hud_text[32];
sprintf(hud_text, "LIVES: %d SCORE: %d", state->lives, state->score);
FntPrint(hud_text);
// Пример работы с GPU
RECT rect = {10, 10, 100, 100};
uint16_t color = state->lives > 1 ? 0xFF00 : 0xFF0000; // Красный если 1 жизнь
DrawPrim(&rect);
}
ModuleHeader __header__ __attribute__((section(".header"))) = {
.magic = 0x55AA1234,
.entry = module_entry,
.size = 0
};
5. Сборка
# Компиляция модулей с их библиотеками
ccpsx MODULE_MDEC.C -o MODULE_MDEC.BIN -lpsxmdec
ccpsx MODULE_GPU.C -o MODULE_GPU.BIN -lpsxgpu
# Основная программа (без лишних библиотек)
ccpsx MAIN.C -o MAIN.EXE
6. Механика общих переменных
-
Основная программа:
- Создаёт глобальную структуру
GameState. - Передаёт указатель на неё в модули через
header->entry(&game_state).
- Создаёт глобальную структуру
-
Модули:
- Читают и изменяют
GameStateчерез полученный указатель. - Могут проверять:
if (state->is_paused) { ... } - Могут изменять:
state->lives--;
- Читают и изменяют
-
Синхронизация:
- Все изменения мгновенно видны в основном модуле и других модулях.
7. Пример работы
- Основная программа:
- Устанавливает
lives = 3,score = 0.
- Устанавливает
- Модуль MDEC:
- Уменьшает
livesдо 2, если игрок ошибся.
- Уменьшает
- Модуль GPU:
- Отображает текущие
livesиscoreна экране.
- Отображает текущие
- Основная программа:
- Видит изменения и может реагировать (например, завершить игру при
lives == 0).
- Видит изменения и может реагировать (например, завершить игру при
8. Важные нюансы
- Безопасность: Модули могут перезаписать любые данные в
GameState. Добавьте проверки:if (state->lives < 0) state->lives = 0; // Защита от отрицательных значений - Производительность: Частый доступ к общим переменным может замедлить работу. Оптимизируйте:
int local_lives = state->lives; // Кэширование в локальную переменную - Конфликты: Если модули работают с одними данными, добавьте флаги блокировки.
Теперь модули могут полноценно взаимодействовать с основной программой, проверяя и изменяя глобальное состояние игры! 🎮