Files
SergObsidian/PERSONAL PROJECTS/PSX code - modules load and exec.md
2025-04-18 22:50:54 +05:00

193 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Вот доработанная версия с **общими переменными между основной программой и модулями**. Мы создадим единую структуру `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 <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)**
```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)**
```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. Сборка**
```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; // Кэширование в локальную переменную
```
- **Конфликты**: Если модули работают с одними данными, добавьте **флаги блокировки**.
---
Теперь модули могут **полноценно взаимодействовать** с основной программой, проверяя и изменяя глобальное состояние игры! 🎮