vault backup: 2025-04-18 22:40:53
This commit is contained in:
8
.obsidian/workspace.json
vendored
8
.obsidian/workspace.json
vendored
@@ -41,12 +41,12 @@
|
||||
"state": {
|
||||
"type": "markdown",
|
||||
"state": {
|
||||
"file": "PERSONAL PROJECTS/PSX code texture load unpack show and fade.md",
|
||||
"file": "PERSONAL PROJECTS/PSX code - modules load and exec.md",
|
||||
"mode": "source",
|
||||
"source": false
|
||||
},
|
||||
"icon": "lucide-file",
|
||||
"title": "PSX code texture load unpack show and fade"
|
||||
"title": "PSX code - modules load and exec"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -207,8 +207,9 @@
|
||||
},
|
||||
"active": "dd912cc876184c4f",
|
||||
"lastOpenFiles": [
|
||||
"PERSONAL PROJECTS/PS1 Gamepad.md",
|
||||
"PERSONAL PROJECTS/PSX code texture load unpack show and fade.md",
|
||||
"PERSONAL PROJECTS/PSX code - modules load and exec.md",
|
||||
"PERSONAL PROJECTS/PS1 Gamepad.md",
|
||||
"PERSONAL PROJECTS/PSX code - Load texture from SECTOR!.md",
|
||||
"PERSONAL PROJECTS/PSX code - Texture show from file.md",
|
||||
"PERSONAL PROJECTS/PS1 Vblank.md",
|
||||
@@ -250,7 +251,6 @@
|
||||
"WORK & PROJECTS/Ulab/Автобан/песок природный.xls",
|
||||
"WORK & PROJECTS/Ulab/Автобан/грунт песчаный.xlsx",
|
||||
"WORK & PROJECTS/Mol/Серверы/Alfa cloud prod_canvas2doc-data/newdoc-node_f3d0e9a6d4d8e6a7_fromCanvas.md",
|
||||
"WORK & PROJECTS/Mol/Серверы/Alfa cloud prod_canvas2doc-data/newdoc-node_f7aa319103f9c366_fromCanvas.md",
|
||||
"WORK & PROJECTS/Mol/Серверы/Alfa cloud prod.canvas",
|
||||
"PERSONAL PROJECTS/P2EP/cdRead.canvas",
|
||||
"P2EP/cdRead.canvas",
|
||||
|
||||
206
PERSONAL PROJECTS/PSX code - modules load and exec.md
Normal file
206
PERSONAL PROJECTS/PSX code - modules load and exec.md
Normal file
@@ -0,0 +1,206 @@
|
||||
Вот реализация вашей задачи для **PlayStation 1**, состоящая из трёх частей:
|
||||
1. **Основная программа** (MAIN.C) - загружает и запускает дополнительные модули.
|
||||
2. **Модуль 1** (MODULE1.C) - выводит сообщение и изменяет общую переменную.
|
||||
3. **Модуль 2** (MODULE2.C) - читает ту же переменную и выводит изменённое значение.
|
||||
|
||||
Все модули загружаются в **один адрес RAM (0x80030000)** и используют общие переменные через специальный заголовок.
|
||||
|
||||
---
|
||||
|
||||
### **1. Структура проекта**
|
||||
```
|
||||
project/
|
||||
├── MAIN.C (Основная программа)
|
||||
├── MODULE1.C (Модуль 1)
|
||||
├── MODULE2.C (Модуль 2)
|
||||
├── SHARED.H (Общие определения)
|
||||
└── SYSTEM.CNF
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **2. Общий заголовок (SHARED.H)**
|
||||
```c
|
||||
// Структура для общих переменных
|
||||
typedef struct {
|
||||
int counter;
|
||||
char message[32];
|
||||
} SharedData;
|
||||
|
||||
// Заголовок модуля (должен быть одинаковым во всех модулях)
|
||||
typedef void (*ModuleFunc)(SharedData*);
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic; // Магическое число 0x55AA1234
|
||||
ModuleFunc entry_point; // Точка входа
|
||||
uint32_t size; // Размер модуля
|
||||
} ModuleHeader;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **3. Основная программа (MAIN.C)**
|
||||
```c
|
||||
#include <sys/types.h>
|
||||
#include <libetc.h>
|
||||
#include <libgte.h>
|
||||
#include <libcd.h>
|
||||
#include "SHARED.H"
|
||||
|
||||
#define MODULE_LOAD_ADDR 0x80030000 // Фиксированный адрес загрузки
|
||||
#define MODULE1_SECTOR 1000 // Сектор начала MODULE1.BIN
|
||||
#define MODULE1_SIZE 50 // Размер MODULE1.BIN в секторах
|
||||
#define MODULE2_SECTOR 1100 // Сектор начала MODULE2.BIN
|
||||
#define MODULE2_SIZE 50 // Размер MODULE2.BIN в секторах
|
||||
|
||||
SharedData shared_data; // Общие данные
|
||||
|
||||
void load_and_run_module(int sector, int size) {
|
||||
// 1. Загрузка модуля в фиксированный адрес
|
||||
CdRead(sector, (uint32_t*)MODULE_LOAD_ADDR, size);
|
||||
CdReadSync(0);
|
||||
|
||||
// 2. Проверка заголовка
|
||||
ModuleHeader *header = (ModuleHeader*)MODULE_LOAD_ADDR;
|
||||
if (header->magic != 0x55AA1234) {
|
||||
FntPrint("Invalid module!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Вызов точки входа модуля
|
||||
header->entry_point(&shared_data);
|
||||
}
|
||||
|
||||
int main() {
|
||||
ResetGraph(0);
|
||||
InitPad(NULL, 0, NULL, 0);
|
||||
CdInit();
|
||||
SetVideoMode(MODE_NTSC);
|
||||
FntLoad(960, 256);
|
||||
FntOpen(16, 16, 256, 224, 0, 512);
|
||||
|
||||
// Инициализация общих данных
|
||||
shared_data.counter = 0;
|
||||
sprintf(shared_data.message, "Initial message");
|
||||
|
||||
// Загрузка и выполнение модулей по очереди
|
||||
while (1) {
|
||||
FntPrint("Main program running...\n");
|
||||
|
||||
// Загрузить и выполнить MODULE1
|
||||
FntPrint("Loading MODULE1...\n");
|
||||
load_and_run_module(MODULE1_SECTOR, MODULE1_SIZE);
|
||||
VSync(0);
|
||||
|
||||
// Загрузить и выполнить MODULE2
|
||||
FntPrint("Loading MODULE2...\n");
|
||||
load_and_run_module(MODULE2_SECTOR, MODULE2_SIZE);
|
||||
VSync(0);
|
||||
|
||||
FntFlush(-1);
|
||||
VSync(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **4. Модуль 1 (MODULE1.C)**
|
||||
```c
|
||||
#include "SHARED.H"
|
||||
|
||||
void module_entry(SharedData *shared) {
|
||||
// Изменяем общие данные
|
||||
shared->counter++;
|
||||
sprintf(shared->message, "MODULE1 was here!");
|
||||
|
||||
// Выводим сообщение (в реальности используйте FntPrint из основной программы)
|
||||
// Здесь просто пример доступа к данным
|
||||
}
|
||||
// Важно: заголовок должен быть в конце файла!
|
||||
ModuleHeader __header__ __attribute__((section(".header"))) = {
|
||||
.magic = 0x55AA1234,
|
||||
.entry_point = module_entry,
|
||||
.size = 0 // Заполнит компоновщик
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **5. Модуль 2 (MODULE2.C)**
|
||||
```c
|
||||
#include "SHARED.H"
|
||||
|
||||
void module_entry(SharedData *shared) {
|
||||
// Читаем изменённые данные
|
||||
shared->counter += 10;
|
||||
sprintf(shared->message + 8, " + MODULE2!");
|
||||
|
||||
// Выводим сообщение
|
||||
}
|
||||
ModuleHeader __header__ __attribute__((section(".header"))) = {
|
||||
.magic = 0x55AA1234,
|
||||
.entry_point = module_entry,
|
||||
.size = 0
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **6. Компиляция и запись на диск**
|
||||
1. Скомпилируйте каждый модуль **отдельно**:
|
||||
```bash
|
||||
ccpsx MAIN.C -o MAIN.EXE
|
||||
ccpsx MODULE1.C -o MODULE1.BIN
|
||||
ccpsx MODULE2.C -o MODULE2.BIN
|
||||
```
|
||||
|
||||
2. Запишите на диск, указав **точные сектора**:
|
||||
```
|
||||
MAIN.EXE -> Сектор 0
|
||||
MODULE1.BIN -> Сектор 1000 (как указано в MAIN.C)
|
||||
MODULE2.BIN -> Сектор 1100
|
||||
```
|
||||
|
||||
3. В `SYSTEM.CNF` укажите:
|
||||
```
|
||||
BOOT = cdrom:\MAIN.EXE;1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### **7. Как это работает**
|
||||
1. **Основная программа**:
|
||||
- Загружает модули в `0x80030000` через `CdRead()`.
|
||||
- Проверяет магическое число в заголовке.
|
||||
- Вызывает `entry_point`, передавая указатель на общие данные.
|
||||
|
||||
2. **Модули**:
|
||||
- Компилируются с **заголовком** в начале.
|
||||
- Имеют доступ к `SharedData` через переданный указатель.
|
||||
- Разрешены **только операции с данными** (нельзя использовать PsyQ напрямую).
|
||||
|
||||
3. **Общие переменные**:
|
||||
- Расположены в основной программе.
|
||||
- Модули получают к ним доступ через указатель.
|
||||
|
||||
---
|
||||
|
||||
### **8. Ограничения безопасности**
|
||||
- Все модули **должны доверять** друг другу.
|
||||
- Нет защиты от **переполнения буфера** (адрес загрузки фиксирован).
|
||||
- Модули не должны **переопределять системные вызовы**.
|
||||
|
||||
---
|
||||
|
||||
### **9. Оптимизации**
|
||||
- Используйте **DMA** для ускорения загрузки.
|
||||
- Добавьте **CRC-проверку** модулей в заголовке.
|
||||
- Для сложных модулей применяйте **релокацию** (но это сложнее).
|
||||
|
||||
Этот подход используется в таких играх, как **Metal Gear Solid** (для загрузки скриптовых модулей).
|
||||
|
||||
________________
|
||||
|
||||
Reference in New Issue
Block a user