Вот доработанная версия с **общими переменными между основной программой и модулями**. Мы создадим единую структуру `GameState`, которая будет передаваться в каждый модуль. --- ### **1. Общий заголовок (SHARED.H)** ```c // Структура для общих переменных игры 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)** ```c #include #include #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)** ```c #include #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)** ```c #include #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. Сборка** ```bash # Компиляция модулей с их библиотеками 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. Механика общих переменных** 1. **Основная программа**: - Создаёт глобальную структуру `GameState`. - Передаёт **указатель** на неё в модули через `header->entry(&game_state)`. 2. **Модули**: - Читают и изменяют `GameState` через полученный указатель. - Могут проверять: ```c if (state->is_paused) { ... } ``` - Могут изменять: ```c state->lives--; ``` 3. **Синхронизация**: - Все изменения мгновенно видны в основном модуле и других модулях. --- ### **7. Пример работы** 1. Основная программа: - Устанавливает `lives = 3`, `score = 0`. 2. Модуль MDEC: - Уменьшает `lives` до 2, если игрок ошибся. 3. Модуль GPU: - Отображает текущие `lives` и `score` на экране. 4. Основная программа: - Видит изменения и может реагировать (например, завершить игру при `lives == 0`). --- ### **8. Важные нюансы** - **Безопасность**: Модули могут **перезаписать любые данные** в `GameState`. Добавьте проверки: ```c if (state->lives < 0) state->lives = 0; // Защита от отрицательных значений ``` - **Производительность**: Частый доступ к общим переменным может замедлить работу. Оптимизируйте: ```c int local_lives = state->lives; // Кэширование в локальную переменную ``` - **Конфликты**: Если модули работают с одними данными, добавьте **флаги блокировки**. --- Теперь модули могут **полноценно взаимодействовать** с основной программой, проверяя и изменяя глобальное состояние игры! 🎮