171 lines
5.9 KiB
Markdown
171 lines
5.9 KiB
Markdown
Вот готовая программа для **PlayStation 1**, которая загружает текстуру с CD-ROM, передаёт её в VRAM и плавно выводит на экран с анимацией яркости (от 0 до 128). Код использует **PsyQ SDK** и разбит на логические блоки.
|
||
|
||
---
|
||
|
||
### **1. Структура проекта**
|
||
```
|
||
texture_demo/
|
||
├── MAIN.C # Основной код
|
||
├── TEXTURE.BIN # RAW-текстура 256x256 (16-бит RGB)
|
||
└── SYSTEM.CNF # Конфигурационный файл
|
||
```
|
||
|
||
---
|
||
|
||
### **2. Код программы (`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_SIZE (256 * 256 * 2) // 131072 байт
|
||
uint16_t tex_buffer[256 * 256] __attribute__((aligned(64))); // Выравнивание для DMA
|
||
|
||
// Параметры спрайта
|
||
typedef struct {
|
||
RECT img_rect; // Размеры текстуры
|
||
TIM_IMAGE tim; // Данные TIM-файла
|
||
int brightness; // Текущая яркость (0-128)
|
||
int fade_speed; // Скорость изменения яркости
|
||
} Sprite;
|
||
|
||
void init() {
|
||
// Инициализация системных библиотек
|
||
ResetGraph(0);
|
||
InitPad(NULL, 0, NULL, 0);
|
||
CdInit();
|
||
|
||
// Настройка видеорежима (NTSC)
|
||
SetVideoMode(MODE_NTSC);
|
||
FntLoad(960, 256);
|
||
FntOpen(16, 16, 256, 224, 0, 512);
|
||
}
|
||
|
||
void load_texture(const char* filename) {
|
||
CdlFILE file;
|
||
uint8_t sector_buffer[2048]; // Буфер для сектора CD
|
||
|
||
// Поиск файла на диске
|
||
if (CdSearchFile(&file, filename) == 0) {
|
||
FntPrint("Error: File not found!\n");
|
||
return;
|
||
}
|
||
|
||
// Чтение текстуры в буфер через DMA
|
||
CdRead(file.pos, (uint32_t*)tex_buffer, TEX_SIZE / 2048);
|
||
CdReadSync(0); // Ожидание завершения
|
||
}
|
||
|
||
void draw_sprite(Sprite* sprite) {
|
||
// Установка яркости (0-128 → 0.0-1.0)
|
||
float alpha = (float)sprite->brightness / 128.0f;
|
||
|
||
// Рисуем полноэкранный спрайт с альфа-смешением
|
||
DR_MODE dr_mode;
|
||
SetDrawMode(&dr_mode, 0, 0, GetTPage(0, 0, sprite->tim.prect->x, sprite->tim.prect->y), 0);
|
||
SetSprt16(&sprite->img_rect); // 16-битный спрайт
|
||
|
||
// Применяем яркость через полупрозрачность
|
||
SetSemiTrans(&sprite->img_rect, 1);
|
||
setRGB0(&sprite->img_rect, alpha * 255, alpha * 255, alpha * 255);
|
||
|
||
// Вывод спрайта
|
||
DrawPrim(&sprite->img_rect);
|
||
}
|
||
|
||
int main() {
|
||
init(); // Инициализация
|
||
|
||
// Загрузка текстуры
|
||
load_texture("\\TEXTURE.BIN"); // Путь на CD
|
||
|
||
// Настройка спрайта
|
||
Sprite sprite = {
|
||
.img_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT},
|
||
.brightness = 0,
|
||
.fade_speed = 1
|
||
};
|
||
|
||
// Загрузка текстуры в VRAM
|
||
sprite.tim.mode = 0;
|
||
sprite.tim.prect = (RECT*)tex_buffer;
|
||
LoadImage(&sprite.tim.prect[0], &sprite.tim.pdata[0]);
|
||
|
||
// Главный цикл
|
||
while (1) {
|
||
FntPrint("Fade Demo: Brightness = %d\n", sprite.brightness);
|
||
|
||
// Плавное увеличение яркости
|
||
sprite.brightness += sprite.fade_speed;
|
||
if (sprite.brightness >= 128 || sprite.brightness <= 0)
|
||
sprite.fade_speed *= -1; // Меняем направление
|
||
|
||
// Отрисовка
|
||
draw_sprite(&sprite);
|
||
FntFlush(-1);
|
||
|
||
// Синхронизация с VBlank
|
||
VSync(0);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### **3. Как это работает?**
|
||
1. **Инициализация**:
|
||
- Настраивается видеорежим (NTSC 320x240).
|
||
- Инициализируются CD-ROM и геймпад.
|
||
|
||
2. **Загрузка текстуры**:
|
||
- Файл `TEXTURE.BIN` (RAW 256x256, 16-бит) читается с диска через DMA.
|
||
- Данные копируются в буфер `tex_buffer`.
|
||
|
||
3. **Передача в VRAM**:
|
||
- `LoadImage()` загружает текстуру в VRAM (адрес автоматически выбирается GPU).
|
||
|
||
4. **Плавное затемнение**:
|
||
- В главном цикле меняется параметр `brightness` (0 → 128 → 0).
|
||
- Яркость применяется через **полупрозрачность** (`SetSemiTrans`).
|
||
|
||
5. **Вывод**:
|
||
- Спрайт рисуется на весь экран с текущей яркостью.
|
||
|
||
---
|
||
|
||
### **4. Требования к текстуре**
|
||
- Формат: **RAW 16-бит RGB** (без заголовков).
|
||
- Размер: **256x256** (можно изменить в коде).
|
||
- Размещение: корень CD (`TEXTURE.BIN`).
|
||
|
||
---
|
||
|
||
### **5. Сборка**
|
||
1. Скомпилируйте через **PsyQ SDK**:
|
||
```bash
|
||
ccpsx MAIN.C -o TEXTURE_DEMO.EXE
|
||
```
|
||
2. Запишите на диск вместе с `TEXTURE.BIN` и `SYSTEM.CNF`.
|
||
|
||
---
|
||
|
||
### **6. Демонстрация эффекта**
|
||
- Текстура плавно "проявляется" (от чёрного к нормальной яркости) и затем исчезает.
|
||
- Скорость регулируется `fade_speed`.
|
||
|
||
---
|
||
|
||
### **7. Оптимизации**
|
||
- Для плавности используется **VSync(0)**.
|
||
- DMA ускоряет загрузку текстуры.
|
||
- Полупрозрачность GPU имитирует изменение яркости.
|
||
|
||
Этот код можно расширить для загрузки анимаций или сложных эффектов! 🎮 |