Это старая версия документа!
Типы данных
Целочисленные типы
- long или int - 32-битное целочисленное со знаком;
- unsigned long или unsigned int (или просто unsigned) - 32-битное целочисленное без знака;
- short - 16-битное целочисленное со знаком. В документации иногда называется half-word;
- unsigned short - 16-битное целочисленное без знака.
Fixed-point типы
PlayStation не имеет FPU (только программная эмуляция), поэтому все вычисления с вещественными числами рекомендуется делать в fixed-point. Это также важно для совместимости с GTE.
Представление вещественного числа с фиксированной запятой по сути представляет собой целочисленное, которое неявно умножается на фиксированный коэффициент масштаба (scaling factor). Например, число 1.23 можно хранить в виде целого 1230, неявно умноженного на коэффициент масштаба 1/1000. Отсюда понятие фиксированной запятой - после запятой такое число всегда имеет одно и то же количество цифр.
На практике коэффициент масштаба зависит от количества бит, выделяемых под дробную часть, поэтому он кратен степени двойки. Например, если дробная часть занимает 12 бит, то коэффициент масштаба равен 1/2^12. Соответственно, число 1.0 в таком представлении соответствует целому 65536. На первый взгляд, неудобно, но если записывать в шестнадцатеричном виде, то все просто: 1.0 = 0x1000, 2.0 = 0x2000 и т.д.
Знак числа всегда записывается как старший бит. 1 = отрицательное число, 0 = положительное число. Затем всегда идут биты целой части, за ними - биты дробной части. Благодаря такому представлению fixed-point числа можно складывать и вычитать как обычные целые.
На PlayStation наиболее распространенные форматы чисел следующие:
- 16-битный Q3.12 - 1 бит знак, 3 бит целая часть, 12 бит дробная часть. Коэффициент масштаба 1/2^12 (1.0 = 2^12 = 0x1000). Предназначен для представления наиболее маленьких чисел. Например, в этом формате задаются элементы матриц GTE;
- 16-битный Q7.8 - 1 бит знак, 7 бит целая часть, 8 бит дробная часть. Коэффициент масштаба 1/2^8 (1.0 = 2^8 = 0x100);
- 32-битный Q15.16 - 1 бит знак, 15 бит целая часть, 16 бит дробная часть. Коэффициент масштаба 1/2^16 (1.0 = 2^16 = 0x10000). В этом формате чаще всего задаются координаты в экранном пространстве.
Сложение и вычитание
Как уже было отмечено, сложение и вычитание чисел с фиксированной запятой - это обычные целочисленные сложение и вычитание.
Умножение
Если форматы множителей совпадают, то умножение делается по следующему правилу:
(X/2^n) * (Y/2^n) = (X * Y)/(2^2n)
Как следует из формулы, при умножении формат числа меняется. Чтобы вернуться обратно в формат множителей, нужно результат сдвинуть вправо на число бит дробной части. Например:
X/2^16 * Y/2^16 = (X * Y)/2^32
Чтобы результат снова привести к масштабу 1/2^16, нужно домножить на 2^16, т.е. сдвинуть на 16 бит вправо:
R = (X * Y) » n
Программы для PlayStation в основном оперируют 16-битными числами. Это связано с тем, что за одну операцию можно загрузить в регистр только 16-битную константу. Поэтому наиболее эффективным является формат Q3.12.
Пример кода на C для умножения Q3.12:
short x = 0x0800; // 0.5 short y = 0x2000; // 2.0 short r = (short)(((int)x * (int)y) >> 12); // 0x1000 = 1.0
Деление
При делении fixed-point чисел коэффициенты масштаба сокращаются:
X/2^n / Y/2^n = X/Y
Но если мы просто вычислим целочисленное деление X/Y, то получим значение без дробной части. Чтобы сохранить дробную часть, нужно сначала сдвинуть делимое влево на число бит дробной части:
R = (X « n) / Y
Пример кода на C для деления Q3.12:
short a = 0x2000; // 2.0 short b = 0x4000; // 4.0 short r = (short)(((int)x << 12) / (int)y); // 0x0800 = 0.5
