Files
SergObsidian/PERSONAL PROJECTS/PS1 DOCS/PSX code texture load unpack show and fade.md
2025-04-18 23:10:56 +05:00

183 lines
5.9 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.

Вот готовая программа для **PlayStation 1**, которая загружает текстуру, плавно проявляет её, ждёт нажатия кнопки (✅ **CROSS** или **CIRCLE**), а затем плавно исчезает. Всё работает с ручным управлением адресами RAM и без использования полупрозрачности.
---
### **Код (`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
#define TEX_WIDTH 256
#define TEX_HEIGHT 256
#define RAW_SECTOR_SIZE 2048
#define TEX_SECTORS ((TEX_WIDTH * TEX_HEIGHT * 2) / RAW_SECTOR_SIZE)
// Адреса в RAM
#define RAW_DATA_ADDR 0x80010000 // Сырые данные с CD
#define UNPACKED_ADDR 0x80030000 // Распакованная текстура
// Состояния анимации
typedef enum {
FADE_IN, // Появление текстуры
WAIT_FOR_BUTTON, // Ожидание нажатия кнопки
FADE_OUT // Исчезновение
} State;
// Структура спрайта
typedef struct {
RECT img_rect;
uint16_t *texture;
int brightness; // 0-128 (0 = чёрный, 128 = оригинал)
State state;
} Sprite;
// Заглушка распаковки (замените на реальный алгоритм)
void unpack_texture(uint8_t *src, uint16_t *dst, int width, int height) {
for (int i = 0; i < width * height; i++) {
dst[i] = ((uint16_t*)src)[i]; // Простое копирование (данные уже в RGB565)
}
}
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_and_unpack_texture(int start_sector) {
// Чтение данных с CD в RAW_DATA_ADDR через DMA
CdRead(start_sector, (uint32_t*)RAW_DATA_ADDR, TEX_SECTORS);
CdReadSync(0);
// Распаковка в UNPACKED_ADDR
unpack_texture((uint8_t*)RAW_DATA_ADDR, (uint16_t*)UNPACKED_ADDR, TEX_WIDTH, TEX_HEIGHT);
}
void draw_sprite(Sprite *sprite) {
// Применение яркости через RGB
int r, g, b;
if (sprite->brightness <= 0) {
r = g = b = 0; // Полная темнота
} else {
float mult = (float)sprite->brightness / 128.0f;
r = 255 * mult;
g = 255 * mult;
b = 255 * mult;
}
// Настройка и отрисовка спрайта
DR_MODE dr_mode;
SetDrawMode(&dr_mode, 0, 0, GetTPage(0, 0, 0, 0), 0);
SetSprt16(&sprite->img_rect);
setRGB0(&sprite->img_rect, r, g, b);
DrawPrim(&sprite->img_rect);
}
int main() {
init();
// Загрузка текстуры из сектора 1000 (пример)
int texture_start_sector = 1000;
load_and_unpack_texture(texture_start_sector);
// Инициализация спрайта
Sprite sprite = {
.img_rect = {0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, 0},
.texture = (uint16_t*)UNPACKED_ADDR,
.brightness = 0,
.state = FADE_IN
};
// Загрузка текстуры в VRAM
RECT vram_rect = {0, 0, TEX_WIDTH, TEX_HEIGHT};
LoadImage(&vram_rect, (uint32_t*)UNPACKED_ADDR);
// Главный цикл
while (1) {
// Обработка состояния
switch (sprite.state) {
case FADE_IN:
sprite.brightness += 2;
if (sprite.brightness >= 128) {
sprite.brightness = 128;
sprite.state = WAIT_FOR_BUTTON;
}
break;
case WAIT_FOR_BUTTON: {
// Проверка нажатия CROSS (✅) или CIRCLE (🟠)
u_long pad = PadRead(0);
if (pad & PAD_CROSS || pad & PAD_CIRCLE) {
sprite.state = FADE_OUT;
}
break;
}
case FADE_OUT:
sprite.brightness -= 2;
if (sprite.brightness <= 0) {
sprite.brightness = 0;
// Здесь можно перейти к следующей сцене
}
break;
}
// Отрисовка
draw_sprite(&sprite);
FntPrint("Press X or O to fade out\nBrightness: %d", sprite.brightness);
FntFlush(-1);
VSync(0);
}
return 0;
}
```
---
### **Как это работает?**
1. **FADE_IN**:
- Текстура плавно проявляется (яркость увеличивается от 0 до 128).
2. **WAIT_FOR_BUTTON**:
- Программа ждёт нажатия **CROSS** (✅) или **CIRCLE** (🟠) через `PadRead()`.
3. **FADE_OUT**:
- После нажатия текстура исчезает (яркость уменьшается до 0).
---
### **Ключевые особенности**
- **Ручное управление адресами RAM** (`0x80010000` и `0x80030000`).
- **Яркость через RGB**, а не полупрозрачность.
- **Проверка кнопок** через битовые маски:
- `PAD_CROSS` — кнопка ✅.
- `PAD_CIRCLE` — кнопка 🟠.
---
### **Сборка**
1. Скомпилируйте:
```bash
ccpsx MAIN.C -o FADE_DEMO.EXE
```
2. Запишите на диск, указав в `SYSTEM.CNF`:
```
BOOT = cdrom:\FADE_DEMO.EXE;1
```
---
### **Демонстрация**
1. Текстура плавно появляется.
2. Нажмите **X** или **O** на геймпаде.
3. Текстура исчезает в темноту.
Теперь вы можете интегрировать это в свою игру для cinematic-сцен! 🎮