Files
SergObsidian/PERSONAL PROJECTS/P2EP/pseudoCode/MakeSmallChar.md
2025-04-20 00:15:46 +05:00

121 lines
4.6 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.

``` c
#include <libgte.h>
#include <libgpu.h>
#include <libgs.h>
/* Структуры данных */
typedef struct {
uint* next_block; // Следующий блок DMA (младшие 24 бита)
uint control; // Контрольные биты DMA
uint data_addr; // Адрес данных
uint tpage_params; // Параметры текстуры (TPage)
} DMAControlBlock;
typedef struct {
short x, y; // Позиция символа
short char_width; // Ширина символа
ushort flags; // Флаги рендеринга
uint* dma_head; // Голова DMA-цепочки
uint* dma_tail; // Хвост DMA-цепочки
} TextRenderState;
/* Константы */
#define SCRAM_BASE 0x1F800000 // Быстрая память PS1
#define DMA_MAGIC 0x80000000 // Флаг DMA-блока
#define CHAR_OFFSET 0x20 // Смещение ASCII-кодов
/* Глобальные переменные (аналоги оригинальных) */
static uint* gDmaNextFree = (uint*)0x8007CE68;
static uint* gDmaCounter = (uint*)0x8007CE6C;
static uint gActiveTpage = 0x8007CA0C;
/* Основная функция рендеринга текста */
DMAControlBlock* RenderTextSystem(
const char* text,
short base_x,
short base_y,
uint color_flags,
uint tpage_config
) {
/* Инициализация состояния */
TextRenderState state;
state.x = base_x;
state.y = base_y;
state.flags = color_flags;
/* Получаем начальный DMA-блок из SCRAM */
DMAControlBlock* dma_blocks = (DMAControlBlock*)(*gDmaNextFree | DMA_MAGIC);
state.dma_head = state.dma_tail = (uint*)dma_blocks;
/* Настройка параметров рендеринга */
StoreColorToAddr(color_flags, tpage_config);
InitDMAtextChain(dma_blocks, base_x, base_y);
/* Основной цикл обработки текста */
while (*text) {
char current_char = *text++;
ushort char_code = current_char - CHAR_OFFSET;
/* Особые обработки для специфичных символов */
switch (current_char) {
case 'g': case 'j': case 'p': case 'q': case 'y':
base_y += 2; // Смещение для символов с хвостами
break;
}
/* Позиционирование символа */
short render_x, render_y;
if (state.flags & 0x10) {
/* Альтернативный режим позиционирования */
render_x = base_x - GetCharLeftOffset(char_code);
render_y = base_y + GetCharBaseline(char_code);
} else {
/* Стандартный режим */
render_x = base_x + dma_blocks->char_width * 8;
render_y = base_y;
}
/* Генерация DMA-команд для символа */
DMAControlBlock* new_block = AllocDMABlock();
SetupCharRender(new_block, char_code, render_x, render_y);
/* Добавление в цепочку */
state.dma_tail->next_block = (uint)new_block & 0xFFFFFF;
state.dma_tail = new_block;
/* Обновление позиции */
if (dma_blocks->char_width == 0) {
state.dma_head = new_block;
dma_blocks->char_width = 1;
}
}
/* Финализация текстурных страниц */
for (int i = 0; i < 2; i++) {
DMAControlBlock* tpage_block = AllocDMABlock();
SetDrawTPage(tpage_block, 0, 1, gActiveTpage);
state.dma_tail->next_block = (uint)tpage_block & 0xFFFFFF;
state.dma_tail = tpage_block;
}
return dma_blocks;
}
/* Вспомогательные функции */
static DMAControlBlock* AllocDMABlock() {
DMAControlBlock* block = (DMAControlBlock*)(*gDmaNextFree | DMA_MAGIC);
(*gDmaCounter)--;
*gDmaNextFree = (*gDmaNextFree & 0xFF000000) | (*block & 0xFFFFFF);
return block;
}
static void SetupCharRender(DMAControlBlock* block, ushort char_code, short x, short y) {
/* Настройка параметров символа */
block->control = 0x1000000; // Базовые флаги DMA
block->data_addr = GetCharDataAddr(char_code);
block->tpage_params = (y << 16) | x; // Позиция
/* Дополнительные настройки из оригинального кода */
block->control |= 0x64808080; // Специфичные флаги PS1
}
```