vault backup: 2025-04-20 00:15:46

This commit is contained in:
sShemet
2025-04-20 00:15:46 +05:00
parent af241b4e09
commit 703f40a528
3 changed files with 261 additions and 5 deletions

View File

@@ -41,12 +41,12 @@
"state": {
"type": "markdown",
"state": {
"file": "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80012df4 RenderInterface.md",
"file": "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80015674 Update Entity Stats.md",
"mode": "source",
"source": false
},
"icon": "lucide-file",
"title": "FUN_80012df4 RenderInterface"
"title": "FUN_80015674 Update Entity Stats"
}
}
],
@@ -207,8 +207,10 @@
},
"active": "dd912cc876184c4f",
"lastOpenFiles": [
"PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80011f2c InitInterfaceManager.md",
"PERSONAL PROJECTS/P2EP/pseudoCode/MakeSmallChar.md",
"PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80015674 Update Entity Stats.md",
"PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80012df4 RenderInterface.md",
"PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80011f2c InitInterfaceManager.md",
"PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md",
"PERSONAL PROJECTS/P2EP/pseudoCode",
"PERSONAL PROJECTS/PS1 DOCS/Untitled",
@@ -241,9 +243,7 @@
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud/Alfa cloud prod.canvas",
"WORK & PROJECTS/Mol/Планы и диаграммы/00001_Быстрый старт/Быстрый старт.canvas",
"My/Diet 1.md",
"My/Diet 2.md",
"My",
"WORK & PROJECTS/Mol/Планы и диаграммы/MOL _ План разработки.md",
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud",
"Структура объектов испытаний.png",
"Схема связей юрлиц и адресов.png",

View File

@@ -0,0 +1,135 @@
Эта функция представляет собой **систему управления игровыми объектами или характеристиками персонажа** в игре на PS1. Вот детальный анализ:
### 🔍 Основное назначение
Функция выполняет:
1. **Обновление параметров объекта** (персонажа, предмета или системы)
2. **Расчет характеристик** на основе базовых значений и модификаторов
3. **Обработку двух режимов работы** (нормальный и специальный через флаг 0x8000)
### 📌 Полная реконструкция на C
```c
// Структура объекта игры (реконструкция)
typedef struct {
uint32_t id; // ID объекта + флаги (param_1)
uint16_t type; // Тип объекта
uint16_t subtype; // Подтип
uint8_t base_stats[10]; // Базовые характеристики
uint8_t modifiers[10]; // Модификаторы
uint16_t calculated[8]; // Рассчитанные значения
// ... другие поля ...
} GameEntity;
// Глобальные данные (реконструкция)
extern uint16_t DWORD_8006eb8c[]; // Таблицы характеристик
extern uint16_t DWORD_800830d0[]; // Базовая статистика
void UpdateEntityStats(GameEntity* target, GameEntity* source, int offset, bool apply_modifiers)
{
// Проверка специального флага
if ((source->id & 0x8000) == 0) {
// Нормальный режим -------------------------------------------------
// 1. Поиск нужного объекта в массиве
int entity_index = 0;
GameEntity* current = source;
while(entity_index < 7) {
if (current->type == (source->id & 0x7FFF)) break;
entity_index++;
current = (GameEntity*)((char*)current + 0x54); // Следующий объект
}
// 2. Копирование базовых параметров
if (!apply_modifiers) {
memcpy(target, current, sizeof(GameEntity)); // Частичное копирование
}
// 3. Расчет комбинированных характеристик
for (int i = 0; i < 5; i++) {
// Среднее значение между базой и модификатором
uint8_t combined = (current->base_stats[i] +
(current->modifiers[i] + source->modifiers[i]) / 2) / 2;
// Ограничение значений (макс 99)
target->modifiers[i] = (combined > 99) ? 99 : combined;
}
// 4. Сложные расчеты характеристик
int calculated_value =
(current->base_stats[9] * DWORD_8006eb8c[(current->type-1)*4] +
current->modifiers[9] * DWORD_8006eb8c[(current->type-1)*4+1]) / 1000;
// 5. Применение ограничений
calculated_value += DWORD_800830d0[entity_index*0x54 + 2];
target->calculated[0] = (calculated_value > 999) ? 999 : calculated_value;
// 6. Обновление связанных объектов
if (!apply_modifiers) {
current->calculated[0] = target->calculated[0];
}
// ... аналогичные расчеты для других характеристик ...
} else {
// Специальный режим (по ID) ---------------------------------------
uint16_t special_id = source->id & 0xFFF;
// 1. Загрузка данных из специальной таблицы
uint8_t* special_data = (uint8_t*)(0x80062b04 + special_id * 0x20);
// 2. Инициализация объекта
target->id = 9; // Специальный тип
target->type = source->id | 0x8000; // Сохраняем флаг
// 3. Копирование характеристик
memcpy(target->modifiers, special_data + 1, 5);
// 4. Расчет производных значений
target->calculated[0] = *(uint16_t*)(0x80062b00 + special_id * 0x20 + 2);
target->calculated[4] = special_data[0] + special_data[1] * 3;
// ... дополнительные расчеты ...
}
}
```
### 🔧 Технические особенности
1. **Два режима работы**:
- Нормальный (поиск по типу объекта)
- Специальный (прямой доступ по ID с флагом 0x8000)
2. **Система характеристик**:
- Базовые значения
- Модификаторы
- Рассчитанные итоговые значения с ограничениями (например, макс. 999)
3. **Оптимизации PS1**:
- Фиксированные смещения (0x54, 0x20)
- Работа с префиксом 0x80000000 (адресация KSEG0)
### 🌟 Что делает на практике?
1. **Для персонажей**:
- Пересчитывает HP/MP/статы на основе уровня и экипировки
- Применяет временные модификаторы (баффы/дебаффы)
2. **Для предметов**:
- Обновляет параметры при экипировке
- Рассчитывает комбинированные эффекты
3. **Для системных объектов**:
- Управляет специальными объектами через ID
### 📊 Структура данных
```c
// Пример структуры объекта (0x54 байта)
struct {
uint32_t id_flags; // 0x00: ID + флаги
uint16_t type; // 0x04: Тип объекта
uint16_t subtype; // 0x06: Подтип
uint8_t stats[10]; // 0x08: Основные характеристики
uint16_t calculated[8]; // 0x12: Рассчитанные значения
// ... другие поля ...
};
```
Эта функция — критически важная часть игровой логики, отвечающая за корректное обновление всех динамических параметров объектов в игре.

View File

@@ -0,0 +1,121 @@
``` 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
}
```