169 lines
6.2 KiB
Markdown
169 lines
6.2 KiB
Markdown
Вот модифицированная программа для **PlayStation 1**, которая загружает текстуру напрямую из указанного сектора CD-ROM в RAM, а затем выводит её на экран с эффектом плавного появления. Код адаптирован для работы с "сырыми" секторами диска.
|
||
|
||
---
|
||
|
||
### **1. Изменённый код (`MAIN.C`)**
|
||
```c
|
||
#include <sys/types.h>
|
||
#include <libetc.h>
|
||
#include <libgte.h>
|
||
#include <libgpu.h>
|
||
#include <libcd.h>
|
||
|
||
#define SCREEN_WIDTH 320
|
||
#define SCREEN_HEIGHT 240
|
||
|
||
// Параметры текстуры (256x256, 16-бит)
|
||
#define TEX_WIDTH 256
|
||
#define TEX_HEIGHT 256
|
||
#define TEX_SIZE (TEX_WIDTH * TEX_HEIGHT * 2) // 131072 байт (16-бит)
|
||
#define TEX_SECTORS (TEX_SIZE / 2048) // Размер в секторах CD (1 сектор = 2048 байт)
|
||
|
||
// Буфер для текстуры в RAM (выровнен для DMA)
|
||
uint16_t tex_buffer[TEX_WIDTH * TEX_HEIGHT] __attribute__((aligned(64)));
|
||
|
||
// Структура спрайта
|
||
typedef struct {
|
||
RECT img_rect; // Размеры текстуры
|
||
TIM_IMAGE tim; // Данные TIM-формата (не используется, но нужен для LoadImage)
|
||
int brightness; // Текущая яркость (0-128)
|
||
int fade_speed; // Скорость изменения яркости
|
||
} Sprite;
|
||
|
||
void init() {
|
||
ResetGraph(0);
|
||
InitPad(NULL, 0, NULL, 0);
|
||
CdInit();
|
||
SetVideoMode(MODE_NTSC);
|
||
FntLoad(960, 256);
|
||
FntOpen(16, 16, 256, 224, 0, 512);
|
||
}
|
||
|
||
void load_texture_from_sector(int start_sector) {
|
||
// Чтение текстуры из указанного сектора CD-ROM в RAM через DMA
|
||
CdRead(start_sector, (uint32_t*)tex_buffer, TEX_SECTORS);
|
||
CdReadSync(0); // Ожидание завершения DMA
|
||
}
|
||
|
||
void draw_sprite(Sprite* sprite) {
|
||
// Настройка полупрозрачности для эффекта яркости
|
||
float alpha = (float)sprite->brightness / 128.0f;
|
||
DR_MODE dr_mode;
|
||
SetDrawMode(&dr_mode, 0, 0, GetTPage(0, 0, 0, 0), 0);
|
||
SetSprt16(&sprite->img_rect);
|
||
SetSemiTrans(&sprite->img_rect, 1);
|
||
setRGB0(&sprite->img_rect, alpha * 255, alpha * 255, alpha * 255);
|
||
DrawPrim(&sprite->img_rect);
|
||
}
|
||
|
||
int main() {
|
||
init();
|
||
|
||
// Параметры загрузки (пример: текстура начинается с сектора 1000)
|
||
int texture_start_sector = 1000; // Замените на реальный сектор!
|
||
load_texture_from_sector(texture_start_sector);
|
||
|
||
// Настройка спрайта
|
||
Sprite sprite = {
|
||
.img_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0},
|
||
.brightness = 0,
|
||
.fade_speed = 1
|
||
};
|
||
|
||
// Загрузка текстуры в VRAM (адрес в RAM -> VRAM)
|
||
RECT vram_rect = {0, 0, TEX_WIDTH, TEX_HEIGHT}; // Куда загружать в VRAM
|
||
LoadImage(&vram_rect, (uint32_t*)tex_buffer);
|
||
|
||
// Главный цикл
|
||
while (1) {
|
||
FntPrint("Sector Load Demo\nBrightness: %d\nSector: %d",
|
||
sprite.brightness, texture_start_sector);
|
||
|
||
// Плавное изменение яркости
|
||
sprite.brightness += sprite.fade_speed;
|
||
if (sprite.brightness >= 128 || sprite.brightness <= 0)
|
||
sprite.fade_speed *= -1;
|
||
|
||
// Отрисовка
|
||
draw_sprite(&sprite);
|
||
FntFlush(-1);
|
||
VSync(0);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### **2. Ключевые изменения**
|
||
1. **Загрузка из сектора**:
|
||
- Вместо поиска файла (`CdSearchFile`) используется прямой доступ к сектору:
|
||
```c
|
||
CdRead(start_sector, (uint32_t*)tex_buffer, TEX_SECTORS);
|
||
```
|
||
- `start_sector` — начальный сектор текстуры на диске (например, `1000`).
|
||
|
||
2. **Размер текстуры**:
|
||
- Рассчитывается автоматически:
|
||
```c
|
||
#define TEX_SECTORS (TEX_SIZE / 2048) // 2048 байт = 1 сектор Mode 1
|
||
```
|
||
|
||
3. **Выравнивание в RAM**:
|
||
- Буфер `tex_buffer` выровнен по 64 байта для эффективного DMA:
|
||
```c
|
||
uint16_t tex_buffer[...] __attribute__((aligned(64)));
|
||
```
|
||
|
||
4. **Загрузка в VRAM**:
|
||
- `LoadImage` копирует данные из `tex_buffer` (RAM) в VRAM:
|
||
```c
|
||
LoadImage(&vram_rect, (uint32_t*)tex_buffer);
|
||
```
|
||
|
||
---
|
||
|
||
### **3. Как подготовить диск**
|
||
1. **Конвертируйте текстуру** в RAW 16-бит (например, через Photoshop или `ffmpeg`):
|
||
```bash
|
||
ffmpeg -i texture.png -f rawvideo -pix_fmt rgb565 texture.raw
|
||
```
|
||
|
||
2. **Запишите RAW-данные** на CD в нужный сектор (например, с помощью `mkpsxiso`):
|
||
```bash
|
||
mkpsxiso -y -o texture.cue -c "CDROM_DATA" texture.raw
|
||
```
|
||
- Узнайте начальный сектор через `cdrdao` или hex-редактор.
|
||
|
||
---
|
||
|
||
### **4. Важные нюансы**
|
||
- **Режим CD-ROM**: Данные должны быть записаны в **Mode 1** (2048 байт/сектор).
|
||
- **Размер текстуры**: Должен быть кратен размеру сектора (иначе чтение "сломает" данные).
|
||
- **Проверка сектора**: Убедитесь, что сектор не занят другими файлами.
|
||
|
||
---
|
||
|
||
### **5. Пример для сборки**
|
||
1. Скомпилируйте:
|
||
```bash
|
||
ccpsx MAIN.C -o CD_SECTOR_DEMO.EXE
|
||
```
|
||
2. Запишите на диск, указав в `SYSTEM.CNF`:
|
||
```
|
||
BOOT = cdrom:\CD_SECTOR_DEMO.EXE;1
|
||
```
|
||
|
||
---
|
||
|
||
### **6. Дополнительная оптимизация**
|
||
Для работы с **Mode 2 XA** (формат видео) измените:
|
||
```c
|
||
CdReadMode(CdMode_CD_XA); // Перед CdRead
|
||
```
|
||
и корректируйте размер сектора (2336 байт).
|
||
|
||
---
|
||
|
||
Этот код идеален для демо-сцен, где нужно напрямую читать графику с CD без файловой системы! 📀 |