/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.Allegrex.compiler.nativeCode.graphics;
import jpcsp.Memory;
import jpcsp.Allegrex.compiler.nativeCode.AbstractNativeCodeSequence;
import jpcsp.graphics.GeCommands;
import jpcsp.memory.IMemoryReader;
import jpcsp.memory.IMemoryWriter;
import jpcsp.memory.MemoryReader;
import jpcsp.memory.MemoryWriter;
/**
* @author gid15
*
*/
public class BoneSequence extends AbstractNativeCodeSequence {
static public void call(int baseAddressReg, int offset1, int offset2, int offset3, int destAddressReg) {
Memory mem = getMemory();
int baseAddress = getRegisterValue(baseAddressReg);
int paramAddr = mem.read32(baseAddress + offset1);
int count = mem.read16(paramAddr + offset2);
if (count <= 0) {
return;
}
int destAddr = getRegisterValue(destAddressReg);
int srcBaseAddr = mem.read32(baseAddress + offset3);
final float[] src1 = new float[16];
final float[] src2 = new float[16];
final float[] dst = new float[16];
int length = count * 304;
IMemoryReader src1Reader = MemoryReader.getMemoryReader(srcBaseAddr + 64, length, 4);
IMemoryReader src2Reader = MemoryReader.getMemoryReader(srcBaseAddr + 128, length, 4);
IMemoryReader src3Reader = MemoryReader.getMemoryReader(srcBaseAddr + 296, length, 4);
IMemoryWriter boneWriter = MemoryWriter.getMemoryWriter(srcBaseAddr + 192, length, 4);
final int cmdBONE = GeCommands.BONE << 24;
for (int i = 0; i < count; i++) {
if ((src3Reader.readNext() & 1) != 0) {
for (int j = 0; j < 12; j++) {
boneWriter.writeNext(cmdBONE);
}
src1Reader.skip(76);
src2Reader.skip(76);
} else {
for (int j = 0; j < 16; j++) {
src1[j] = Float.intBitsToFloat(src1Reader.readNext());
src2[j] = Float.intBitsToFloat(src2Reader.readNext());
}
// VMMUL
for (int n1 = 0, j = 0, k = 0; n1 < 4; n1++, k += 4) {
// We only need a 4x3 dst matrix because the BONE matrix is only 4x3
for (int n2 = 0; n2 < 3; n2++, j++) {
float dot = src1[n2] * src2[k];
dot += src1[n2 + 4] * src2[k + 1];
dot += src1[n2 + 8] * src2[k + 2];
dst[j] = dot + src1[n2 + 12] * src2[k + 3];
}
j++;
}
for (int n1 = 0, j = 0; n1 < 4; n1++) {
// The BONE matrix is only 4x3
for (int n2 = 0; n2 < 3; n2++, j++) {
int intBits = Float.floatToRawIntBits(dst[j]);
boneWriter.writeNext(cmdBONE | (intBits >>> 8));
}
j++; // Skip one column
}
src1Reader.skip(60);
src2Reader.skip(60);
}
src3Reader.skip(75);
boneWriter.skip(64);
}
boneWriter.flush();
// This is probably not used by the application as it is overwritten
// at each loop and only the last loop result is left...
for (int n1 = 0, k = 0; n1 < 4; n1++, k += 4) {
final int n2 = 3;
float dot = src1[n2] * src2[k];
dot += src1[n2 + 4] * src2[k + 1];
dot += src1[n2 + 8] * src2[k + 2];
dst[(n1 << 2) + n2] = dot + src1[n2 + 12] * src2[k + 3];
}
IMemoryWriter dstWriter = MemoryWriter.getMemoryWriter(destAddr, 64, 4);
for (int n1 = 0; n1 < 4; n1++) {
for (int n2 = 0; n2 < 4; n2++) {
int intBits = Float.floatToRawIntBits(dst[(n2 << 2) + n1]);
dstWriter.writeNext(intBits);
}
}
dstWriter.flush();
}
static public void call(int matrix1Reg, int matrix2Reg, int destReg, int countReg) {
int matrix1Addr = getRegisterValue(matrix1Reg);
int matrix2Addr = getRegisterValue(matrix2Reg);
int dest = getRegisterValue(destReg);
int count = getRegisterValue(countReg);
if (count <= 0) {
return;
}
IMemoryReader matrix1Reader = MemoryReader.getMemoryReader(matrix1Addr, 48 * count, 4);
IMemoryReader matrix2Reader = MemoryReader.getMemoryReader(matrix2Addr, 48 * count, 4);
IMemoryWriter destWriter = MemoryWriter.getMemoryWriter(dest, 64 * count, 4);
final float[] matrix2 = new float[12];
int cmdBONE = GeCommands.BONE << 24;
int cmdRET = GeCommands.RET << 24;
float dot, m1a, m1b, m1c;
for (int i = 0; i < count; i++) {
for (int j = 0; j < 12; j++) {
matrix2[j] = Float.intBitsToFloat(matrix2Reader.readNext());
}
for (int n1 = 0; n1 < 3; n1++) {
m1a = Float.intBitsToFloat(matrix1Reader.readNext());
m1b = Float.intBitsToFloat(matrix1Reader.readNext());
m1c = Float.intBitsToFloat(matrix1Reader.readNext());
for (int n2 = 0; n2 < 3; n2++) {
dot = m1a * matrix2[n2];
dot += m1b * matrix2[n2 + 3];
dot += m1c * matrix2[n2 + 6];
destWriter.writeNext((Float.floatToRawIntBits(dot) >>> 8) | cmdBONE);
}
}
m1a = Float.intBitsToFloat(matrix1Reader.readNext());
m1b = Float.intBitsToFloat(matrix1Reader.readNext());
m1c = Float.intBitsToFloat(matrix1Reader.readNext());
for (int n2 = 0; n2 < 3; n2++) {
dot = m1a * matrix2[n2];
dot += m1b * matrix2[n2 + 3];
dot += m1c * matrix2[n2 + 6];
dot += matrix2[n2 + 9];
destWriter.writeNext((Float.floatToRawIntBits(dot) >>> 8) | cmdBONE);
}
destWriter.writeNext(cmdRET);
destWriter.skip(3);
}
destWriter.flush();
}
}