vault backup: 2025-04-20 00:15:46
This commit is contained in:
10
.obsidian/workspace.json
vendored
10
.obsidian/workspace.json
vendored
@@ -41,12 +41,12 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"type": "markdown",
|
"type": "markdown",
|
||||||
"state": {
|
"state": {
|
||||||
"file": "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80012df4 RenderInterface.md",
|
"file": "PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80015674 Update Entity Stats.md",
|
||||||
"mode": "source",
|
"mode": "source",
|
||||||
"source": false
|
"source": false
|
||||||
},
|
},
|
||||||
"icon": "lucide-file",
|
"icon": "lucide-file",
|
||||||
"title": "FUN_80012df4 RenderInterface"
|
"title": "FUN_80015674 Update Entity Stats"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -207,8 +207,10 @@
|
|||||||
},
|
},
|
||||||
"active": "dd912cc876184c4f",
|
"active": "dd912cc876184c4f",
|
||||||
"lastOpenFiles": [
|
"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_80012df4 RenderInterface.md",
|
||||||
|
"PERSONAL PROJECTS/P2EP/pseudoCode/FUN_80011f2c InitInterfaceManager.md",
|
||||||
"PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md",
|
"PERSONAL PROJECTS/PS1 DOCS/PS1 IRQ.md",
|
||||||
"PERSONAL PROJECTS/P2EP/pseudoCode",
|
"PERSONAL PROJECTS/P2EP/pseudoCode",
|
||||||
"PERSONAL PROJECTS/PS1 DOCS/Untitled",
|
"PERSONAL PROJECTS/PS1 DOCS/Untitled",
|
||||||
@@ -241,9 +243,7 @@
|
|||||||
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud/Alfa cloud prod.canvas",
|
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud/Alfa cloud prod.canvas",
|
||||||
"WORK & PROJECTS/Mol/Планы и диаграммы/00001_Быстрый старт/Быстрый старт.canvas",
|
"WORK & PROJECTS/Mol/Планы и диаграммы/00001_Быстрый старт/Быстрый старт.canvas",
|
||||||
"My/Diet 1.md",
|
"My/Diet 1.md",
|
||||||
"My/Diet 2.md",
|
|
||||||
"My",
|
"My",
|
||||||
"WORK & PROJECTS/Mol/Планы и диаграммы/MOL _ План разработки.md",
|
|
||||||
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud",
|
"WORK & PROJECTS/Mol/Планы и диаграммы/Alfa Cloud",
|
||||||
"Структура объектов испытаний.png",
|
"Структура объектов испытаний.png",
|
||||||
"Схема связей юрлиц и адресов.png",
|
"Схема связей юрлиц и адресов.png",
|
||||||
|
|||||||
@@ -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: Рассчитанные значения
|
||||||
|
// ... другие поля ...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
Эта функция — критически важная часть игровой логики, отвечающая за корректное обновление всех динамических параметров объектов в игре.
|
||||||
121
PERSONAL PROJECTS/P2EP/pseudoCode/MakeSmallChar.md
Normal file
121
PERSONAL PROJECTS/P2EP/pseudoCode/MakeSmallChar.md
Normal 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
|
||||||
|
}
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user