REDRIVER2/src_rebuild/EMULATOR/LIBGPU.C
Ilya Shurumov 6c14702b24 - [EMU] make GPU DR_* commands properly parsed
- [EMU] use ptag length instead of primitive_size
- [EMU] drawing area offset support
2020-06-06 13:51:27 +06:00

1512 lines
39 KiB
C

#include "LIBGPU.H"
#include "EMULATOR.H"
#include "EMULATOR_GLOBALS.H"
#include "EMULATOR_PRIVATE.H"
#include <stdint.h>
#include <LIBETC.H>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
DISPENV activeDispEnv;
DRAWENV activeDrawEnv; // word_33BC
int g_GPUDisabledState = 0;
#if 0
char fontDebugTexture[] =
{
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x10,0x00,0x00,0x00,0x10,0x01,0x00,
0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,
0x00,0x01,0x01,0x01,0x00,0x11,0x00,0x01,0x00,0x01,0x01,0x00,0x00,0x11,0x00,0x00,
0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x01,
0x00,0x01,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,
0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,
0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,
0x00,0x00,0x01,0x01,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x11,0x01,
0x00,0x01,0x01,0x01,0x00,0x01,0x10,0x01,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,
0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,
0x00,0x10,0x11,0x00,0x00,0x01,0x10,0x01,0x00,0x10,0x01,0x01,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,
0x00,0x00,0x10,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x11,0x00,0x00,0x11,0x11,0x01,
0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x11,0x00,
0x00,0x01,0x00,0x01,0x00,0x10,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x00,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x01,
0x00,0x01,0x10,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,
0x00,0x10,0x10,0x00,0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x10,0x00,
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,
0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,
0x00,0x01,0x01,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x11,0x00,
0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x00,0x10,0x00,
0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x01,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,
0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,
0x00,0x11,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,
0x00,0x11,0x11,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,
0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,
0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x01,
0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,
0x00,0x01,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,
0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x10,0x11,0x00,
0x00,0x00,0x10,0x00,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,
0x00,0x10,0x11,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,0x00,0x10,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00,
0x00,0x11,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x11,0x11,0x01,0x00,0x10,0x11,0x00,
0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00,
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x10,0x00,
0x00,0x01,0x00,0x00,0x00,0x11,0x10,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,
0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x01,0x00,
0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x11,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x01,0x01,0x00,0x11,0x11,0x01,0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x00,
0x00,0x10,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x00,
0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x11,0x00,0x00,
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x01,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,
0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x01,0x00,
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x10,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x10,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x10,0x00,
0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00,
0x00,0x11,0x11,0x00,0x00,0x11,0x11,0x01,0x00,0x01,0x00,0x00,0x00,0x10,0x11,0x00,
0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x01,0x00,0x01,
0x00,0x11,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00,
0x00,0x11,0x11,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,
0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,
0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x11,0x11,0x00,0x00,0x01,0x00,0x01,0x00,0x11,0x11,0x00,0x00,0x10,0x11,0x00,
0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x01,
0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x10,0x10,0x00,0x00,0x01,0x01,0x01,
0x00,0x10,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x10,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x01,0x10,0x00,0x00,0x01,0x00,0x01,
0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,0x00,0x10,0x10,0x00,0x00,0x11,0x10,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x00,0x00,0x00,0x10,0x01,0x01,0x00,0x01,0x00,0x01,0x00,0x10,0x11,0x00,
0x00,0x00,0x01,0x00,0x00,0x10,0x11,0x00,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x01,
0x00,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x11,0x11,0x01,0x00,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x01,
0x00,0x00,0x00,0x00,0x00,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
#endif
//unk_E88
unsigned char fontDebugClut[] = { 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
struct VertexBufferSplit
{
TextureID textureId;
unsigned short vIndex;
unsigned short vCount;
BlendMode blendMode;
TexFormat texFormat;
RECT16 clipRect;
};
//#define DEBUG_POLY_COUNT
#if defined(DEBUG_POLY_COUNT)
static int polygon_count = 0;
#endif
struct Vertex g_vertexBuffer[MAX_NUM_POLY_BUFFER_VERTICES];
struct VertexBufferSplit g_splits[MAX_NUM_INDEX_BUFFERS];
int g_vertexIndex;
int g_splitIndex;
void ClearVBO()
{
g_vertexIndex = 0;
g_splitIndex = 0;
g_splits[0].texFormat = (TexFormat)0xFFFF;
}
u_short s_lastSemiTrans = 0xFFFF;
u_short s_lastPolyType = 0xFFFF;
void ResetPolyState()
{
s_lastSemiTrans = 0xFFFF;
s_lastPolyType = 0xFFFF;
}
//#define WIREFRAME_MODE
#if defined(USE_32_BIT_ADDR)
unsigned long terminator[2] = { -1, 0 };
#else
unsigned long terminator = -1;
#endif
void(*drawsync_callback)(void) = NULL;
void* off_3348[] =
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
int ClearImage(RECT16* rect, u_char r, u_char g, u_char b)
{
Emulator_Clear(rect->x, rect->y, rect->w, rect->h, r, g, b);
return 0;
}
int ClearImage2(RECT16* rect, u_char r, u_char g, u_char b)
{
Emulator_Clear(rect->x, rect->y, rect->w, rect->h, r, g, b);
return 0;
}
void DrawAggregatedSplits();
int DrawSync(int mode)
{
// Update VRAM seems needed to be here
//Emulator_UpdateVRAM();
if (g_splitIndex > 0) // don't do flips if nothing to draw.
{
DrawAggregatedSplits();
Emulator_EndScene();
}
if (drawsync_callback != NULL)
{
drawsync_callback();
}
return 0;
}
int LoadImagePSX(RECT16* rect, u_long* p)
{
Emulator_CopyVRAM((unsigned short*)p, 0, 0, rect->w, rect->h, rect->x, rect->y);
return 0;
}
int MargePrim(void* p0, void* p1)
{
int v0 = ((unsigned char*)p0)[3];
int v1 = ((unsigned char*)p1)[3];
v0 += v1;
v1 = v0 + 1;
if (v1 < 0x11)
{
((char*)p0)[3] = v1;
((int*)p1)[0] = 0;
return 0;
}
return -1;
}
int MoveImage(RECT16* rect, int x, int y)
{
Emulator_CopyVRAM(NULL, rect->x, rect->y, rect->w, rect->h, x, y);
return 0;
}
int ResetGraph(int mode)
{
UNIMPLEMENTED();
return 0;
}
int SetGraphDebug(int level)
{
UNIMPLEMENTED();
return 0;
}
int StoreImage(RECT16* rect, u_long* p)
{
Emulator_ReadVRAM((unsigned short*)p, rect->x, rect->y, rect->w, rect->h);
return 0;
}
int StoreImage2(RECT16 *RECT16, u_long *p)
{
int result = StoreImage(RECT16, p);
// GPU reset?
return result;
}
u_long* ClearOTag(u_long* ot, int n)
{
//Nothing to do here.
if (n == 0)
return NULL;
//last is special terminator
ot[n - 1] = (unsigned long)&terminator;
for (int i = n - 2; i > -1; i--)
{
ot[i] = (unsigned long)&ot[i + 1];
}
return NULL;
}
u_long* ClearOTagR(u_long* ot, int n)
{
//Nothing to do here.
if (n == 0)
return NULL;
//First is special terminator
setaddr(ot, &terminator);
setlen(ot, 0);
#if defined(USE_32_BIT_ADDR)
for (int i = 2; i < n * 2; i += 2)
#else
for (int i = 1; i < n; i++)
#endif
{
#if defined(USE_32_BIT_ADDR)
setaddr(&ot[i], (unsigned long)&ot[i - 2]);
#else
setaddr(&ot[i], (unsigned long)&ot[i - 1]);
#endif
setlen(&ot[i], 0);
}
return NULL;
}
void SetDispMask(int mask)
{
g_GPUDisabledState = (mask == 0);
}
int FntPrint(char* text, ...)
{
UNIMPLEMENTED();
return 0;
}
DISPENV* GetDispEnv(DISPENV* env)//(F)
{
memcpy(env, &activeDispEnv, sizeof(DISPENV));
return env;
}
DISPENV* PutDispEnv(DISPENV* env)//To Finish
{
memcpy((char*)&activeDispEnv, env, sizeof(DISPENV));
return 0;
}
DISPENV* SetDefDispEnv(DISPENV* env, int x, int y, int w, int h)//(F)
{
env->disp.x = x;
env->disp.y = y;
env->disp.w = w;
env->disp.h = h;
env->screen.x = 0;
env->screen.y = 0;
env->screen.w = 0;
env->screen.h = 0;
env->isrgb24 = 0;
env->isinter = 0;
env->pad1 = 0;
env->pad0 = 0;
return 0;
}
DRAWENV* GetDrawEnv(DRAWENV* env)
{
UNIMPLEMENTED();
return NULL;
}
DRAWENV* PutDrawEnv(DRAWENV* env)//Guessed
{
memcpy((char*)&activeDrawEnv, env, sizeof(DRAWENV));
return 0;
}
DRAWENV* SetDefDrawEnv(DRAWENV* env, int x, int y, int w, int h)//(F)
{
env->clip.x = x;
env->clip.y = y;
env->clip.w = w;
env->tw.x = 0;
env->tw.y = 0;
env->tw.w = 0;
env->tw.h = 0;
env->r0 = 0;
env->g0 = 0;
env->b0 = 0;
env->dtd = 1;
env->clip.h = h;
if (GetVideoMode() == 0)
{
env->dfe = h < 0x121 ? 1 : 0;
}
else
{
env->dfe = h < 0x101 ? 1 : 0;
}
env->ofs[0] = x;
env->ofs[1] = y;
env->tpage = 10;
env->isbg = 0;
return env;
}
void SetDrawEnv(DR_ENV* dr_env, DRAWENV* env)
{
dr_env->code[0] = ((env->clip.y & 0x3FF) << 10) | env->clip.x & 0x3FF | 0xE3000000;
dr_env->code[1] = (((env->clip.y + env->clip.h - 1) & 0x3FF) << 10) | (env->clip.x + env->clip.w - 1) & 0x3FF | 0xE4000000;
dr_env->code[2] = ((env->ofs[1] & 0x3FF) << 11) | env->ofs[0] & 0x7FF | 0xE5000000;
dr_env->code[3] = 32 * (((256 - env->tw.h) >> 3) & 0x1F) | ((256 - env->tw.w) >> 3) & 0x1F | (((env->tw.y >> 3) & 0x1F) << 15) | (((env->tw.x >> 3) & 0x1F) << 10) | 0xE2000000;
dr_env->code[4] = ((env->dtd != 0) << 9) | ((env->dfe != 0) << 10) | env->tpage & 0x1FF | 0xE1000000;
dr_env->len = 5;
dr_env->tag = dr_env->tag & 0xFFFFFF | 0x5000000;
}
void SetDrawMode(DR_MODE* p, int dfe, int dtd, int tpage, RECT16* tw)
{
setDrawMode(p, dfe, dtd, tpage, tw);
}
void SetDrawArea(DR_AREA *p, RECT16 *r)
{
p->code[0] = (r->x & 0x3FF | ((r->y & 0x3FF) << 10)) | 0xE3000000;
p->code[1] = (((r->x + r->w) & 0x3FF) | (((r->y + r->h) & 0x3FF) << 10)) | 0xE4000000;
p->len = 2;
p->tag = p->tag & 0xFFFFFF | 0x2000000;
}
void SetDrawMove(DR_MOVE* p, RECT16* rect, int x, int y)
{
char len;
len = 5;
if (rect->w == 0 || rect->h == 0)
len = 0;
p->code[0] = 0x1000000;
p->code[1] = 0x80000000;
p->code[2] = *(ulong*)&rect->x;
p->code[3] = y << 0x10 | x & 0xffffU;
p->code[4] = *(ulong *)&rect->w;
p->len = len;
p->tag = p->tag & 0xFFFFFF | 0x1000000;
}
u_long DrawSyncCallback(void(*func)(void))
{
drawsync_callback = func;
return 0;
}
u_short GetClut(int x, int y)
{
return getClut(x, y);
}
void AddSplit(bool semiTrans, int page, TextureID textureId)
{
VertexBufferSplit& curSplit = g_splits[g_splitIndex];
BlendMode blendMode = semiTrans ? GET_TPAGE_BLEND(page) : BM_NONE;
TexFormat texFormat = GET_TPAGE_FORMAT(page);
RECT16& clipRect = activeDrawEnv.clip;
if (curSplit.blendMode == blendMode &&
curSplit.texFormat == texFormat &&
curSplit.textureId == textureId &&
curSplit.clipRect.x == clipRect.x &&
curSplit.clipRect.y == clipRect.y &&
curSplit.clipRect.w == clipRect.w &&
curSplit.clipRect.h == clipRect.h)
{
return;
}
curSplit.vCount = g_vertexIndex - curSplit.vIndex;
VertexBufferSplit& split = g_splits[++g_splitIndex];
split.textureId = textureId;
split.vIndex = g_vertexIndex;
split.vCount = 0;
split.blendMode = blendMode;
split.texFormat = texFormat;
split.clipRect = clipRect;
}
void TriangulateQuad()
{
/*
Triangulate like this:
v0--v1
| / |
| / |
v2--v3
NOTE: v2 swapped with v3 during primitive parsing but it not shown here
*/
g_vertexBuffer[g_vertexIndex + 4] = g_vertexBuffer[g_vertexIndex + 3];
g_vertexBuffer[g_vertexIndex + 5] = g_vertexBuffer[g_vertexIndex + 2];
g_vertexBuffer[g_vertexIndex + 2] = g_vertexBuffer[g_vertexIndex + 3];
g_vertexBuffer[g_vertexIndex + 3] = g_vertexBuffer[g_vertexIndex + 1];
}
void DrawSplit(const VertexBufferSplit& split)
{
Emulator_SetupClipMode(split.clipRect);
Emulator_SetTexture(split.textureId, split.texFormat);
Emulator_SetBlendMode(split.blendMode);
Emulator_DrawTriangles(split.vIndex, split.vCount / 3);
}
//
// Draws all polygons after AggregatePTAG
//
void DrawAggregatedSplits()
{
if (g_emulatorPaused)
{
for (int i = 0; i < 3; i++)
{
struct Vertex* vert = &g_vertexBuffer[g_polygonSelected + i];
vert->r = 255;
vert->g = 0;
vert->b = 0;
eprintf("==========================================\n");
eprintf("POLYGON: %d\n", i);
eprintf("X: %d Y: %d\n", vert->x, vert->y);
eprintf("U: %d V: %d\n", vert->u, vert->v);
eprintf("TP: %d CLT: %d\n", vert->page, vert->clut);
eprintf("==========================================\n");
}
Emulator_UpdateInput();
}
// next code ideally should be called before EndScene
Emulator_UpdateVertexBuffer(g_vertexBuffer, g_vertexIndex);
for (int i = 1; i <= g_splitIndex; i++)
DrawSplit(g_splits[i]);
ClearVBO();
#ifdef PGXP
PGXP_ClearCache();
#endif
}
// forward declarations
int ParsePrimitive(uintptr_t primPtr);
int ParseLinkedPrimitiveList(uintptr_t packetStart, uintptr_t packetEnd);
void AggregatePTAGsToSplits(u_long* p, bool singlePrimitive)
{
if (!p)
return;
if (singlePrimitive)
{
#ifdef PGXP
P_TAG* pTag = (P_TAG*)p;
pTag->pgxp_index = 0xFFFF; // force
#endif
// single primitive
ParsePrimitive((uintptr_t)p);
g_splits[g_splitIndex].vCount = g_vertexIndex - g_splits[g_splitIndex].vIndex;
}
else
{
P_TAG* pTag = (P_TAG*)p;
// P_TAG as primitive list
//do
while ((uintptr_t)pTag != (uintptr_t)&terminator)
{
if (pTag->len > 0)
{
int lastSize = ParseLinkedPrimitiveList((uintptr_t)pTag, (uintptr_t)pTag + (uintptr_t)(pTag->len * 4) + 4 + LEN_OFFSET);
if (lastSize == -1)
break; // safe bailout
}
pTag = (P_TAG*)pTag->addr;
}
}
}
//------------------------------------------------------------------
void DrawOTagEnv(u_long* p, DRAWENV* env)
{
do
{
PutDrawEnv(env);
DrawOTag(p);
} while (g_emulatorPaused);
}
void DrawOTag(u_long* p)
{
if (g_GPUDisabledState)
return;
if (Emulator_BeginScene())
{
ClearVBO();
ResetPolyState();
}
#if defined(DEBUG_POLY_COUNT)
polygon_count = 0;
#endif
if (activeDrawEnv.isbg)
{
ClearImage(&activeDrawEnv.clip, activeDrawEnv.r0, activeDrawEnv.g0, activeDrawEnv.b0);
}
else
{
Emulator_BlitVRAM();
}
AggregatePTAGsToSplits(p, false);
DrawAggregatedSplits();
}
void DrawPrim(void* p)
{
if (g_GPUDisabledState)
return;
if (Emulator_BeginScene())
{
ClearVBO();
ResetPolyState();
}
#if defined(DEBUG_POLY_COUNT)
polygon_count = 0;
#endif
if (activeDrawEnv.isbg)
{
ClearImage(&activeDrawEnv.clip, activeDrawEnv.r0, activeDrawEnv.g0, activeDrawEnv.b0);
}
else
{
Emulator_BlitVRAM();
}
Emulator_SetPolygonOffset(-0.5f);
AggregatePTAGsToSplits((u_long*)p, true);
DrawAggregatedSplits();
Emulator_SetPolygonOffset(0.0f);
}
// parses primitive and pushes it to VBO
// returns primitive size
// -1 means invalid primitive
int ParsePrimitive(uintptr_t primPtr)
{
P_TAG* pTag = (P_TAG*)primPtr;
int textured = (pTag->code & 0x4) != 0;
int blend_mode = 0;
if (textured)
{
if ((pTag->code & 0x1) != 0)
{
blend_mode = 2;
}
else
{
blend_mode = 1;
}
}
else
{
blend_mode = 0;
}
bool semi_transparent = (pTag->code & 2) != 0;
#ifdef PGXP
unsigned short gte_index = pTag->pgxp_index;
#else
unsigned short gte_index = 0xFFFF;
#endif
switch (pTag->code & ~3)
{
case 0x0:
{
switch (pTag->code)
{
case 0x01:
{
DR_MOVE* drmove = (DR_MOVE*)pTag;
#if 0 // [A] this was disabled because Emulator_StoreFrameBuffer slow
int x, y;
y = drmove->code[3] >> 0x10 & 0xFFFF;
x = drmove->code[3] & 0xFFFF;
RECT16 rect;
*(ulong*)&rect.x = *(ulong*)&drmove->code[2];
*(ulong*)&rect.w = *(ulong*)&drmove->code[4];
// FIXME:
// this is only proof of concept
// Also I don't know yet why it is not working
Emulator_StoreFrameBuffer(activeDispEnv.disp.x, activeDispEnv.disp.y, activeDispEnv.disp.w, activeDispEnv.disp.h);
Emulator_UpdateVRAM();
MoveImage(&rect, x, y);
#endif
break;
}
default:
{
eprinterr("Unknown command %02X!\n", pTag->code);
}
}
break;
}
case 0x20:
{
POLY_F3* poly = (POLY_F3*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayTriangleZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0);
g_vertexIndex += 3;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x24:
{
POLY_FT3* poly = (POLY_FT3*)pTag;
activeDrawEnv.tpage = poly->tpage;
AddSplit(semi_transparent, poly->tpage, vramTexture);
Emulator_GenerateVertexArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u2, poly->tpage, poly->clut, GET_TPAGE_DITHER(lastTpage));
Emulator_GenerateColourArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0);
g_vertexIndex += 3;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x28:
{
POLY_F4* poly = (POLY_F4*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayQuadZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x2C:
{
POLY_FT4* poly = (POLY_FT4*)pTag;
activeDrawEnv.tpage = poly->tpage;
AddSplit(semi_transparent, poly->tpage, vramTexture);
Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u3, &poly->u2, poly->tpage, poly->clut, GET_TPAGE_DITHER(lastTpage));
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x30:
{
POLY_G3* poly = (POLY_G3*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayTriangleZero(&g_vertexBuffer[g_vertexIndex], 1);
Emulator_GenerateColourArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r2);
g_vertexIndex += 3;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x34:
{
POLY_GT3* poly = (POLY_GT3*)pTag;
activeDrawEnv.tpage = poly->tpage;
AddSplit(semi_transparent, poly->tpage, vramTexture);
Emulator_GenerateVertexArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u2, poly->tpage, poly->clut, GET_TPAGE_DITHER(lastTpage));
Emulator_GenerateColourArrayTriangle(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r2);
g_vertexIndex += 3;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x38:
{
POLY_G4* poly = (POLY_G4*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayQuadZero(&g_vertexBuffer[g_vertexIndex], 1);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r3, &poly->r2);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x3C:
{
POLY_GT4* poly = (POLY_GT4*)pTag;
activeDrawEnv.tpage = poly->tpage;
AddSplit(semi_transparent, poly->tpage, vramTexture);
Emulator_GenerateVertexArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, &poly->x3, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->u0, &poly->u1, &poly->u3, &poly->u2, poly->tpage, poly->clut, GET_TPAGE_DITHER(lastTpage));
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1, &poly->r3, &poly->r2);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x40:
{
LINE_F2* poly = (LINE_F2*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, gte_index);
Emulator_GenerateTexcoordArrayLineZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayLine(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x48: // TODO (unused)
{
LINE_F3* poly = (LINE_F3*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
{
Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, gte_index);
Emulator_GenerateTexcoordArrayLineZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayLine(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
}
{
Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x1, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayLineZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayLine(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
}
break;
}
case 0x4c:
{
LINE_F4* poly = (LINE_F4*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
{
Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, gte_index);
Emulator_GenerateTexcoordArrayLineZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayLine(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
}
{
Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x1, &poly->x2, gte_index);
Emulator_GenerateTexcoordArrayLineZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayLine(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
}
{
Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x2, &poly->x3, gte_index);
Emulator_GenerateTexcoordArrayLineZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayLine(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
}
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
// TODO: unsupported
break;
}
case 0x50:
{
LINE_G2* poly = (LINE_G2*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateLineArray(&g_vertexBuffer[g_vertexIndex], &poly->x0, &poly->x1, gte_index);
Emulator_GenerateTexcoordArrayLineZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayLine(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r1);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x60:
{
TILE* poly = (TILE*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->x0, poly->w, poly->h, gte_index);
Emulator_GenerateTexcoordArrayQuadZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x64:
{
SPRT* poly = (SPRT*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, vramTexture);
Emulator_GenerateVertexArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->x0, poly->w, poly->h, gte_index);
Emulator_GenerateTexcoordArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->u0, activeDrawEnv.tpage, poly->clut, poly->w, poly->h);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x68:
{
TILE_1* poly = (TILE_1*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->x0, 1, 1, gte_index);
Emulator_GenerateTexcoordArrayQuadZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x70:
{
TILE_8* poly = (TILE_8*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->x0, 8, 8, gte_index);
Emulator_GenerateTexcoordArrayQuadZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x74:
{
SPRT_8* poly = (SPRT_8*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, vramTexture);
Emulator_GenerateVertexArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->x0, 8, 8, gte_index);
Emulator_GenerateTexcoordArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->u0, activeDrawEnv.tpage, poly->clut, 8, 8);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x78:
{
TILE_16* poly = (TILE_16*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, whiteTexture);
Emulator_GenerateVertexArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->x0, 16, 16, gte_index);
Emulator_GenerateTexcoordArrayQuadZero(&g_vertexBuffer[g_vertexIndex], 0);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0x7C:
{
SPRT_16* poly = (SPRT_16*)pTag;
AddSplit(semi_transparent, activeDrawEnv.tpage, vramTexture);
Emulator_GenerateVertexArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->x0, 16, 16, gte_index);
Emulator_GenerateTexcoordArrayRect(&g_vertexBuffer[g_vertexIndex], &poly->u0, activeDrawEnv.tpage, poly->clut, 16, 16);
Emulator_GenerateColourArrayQuad(&g_vertexBuffer[g_vertexIndex], &poly->r0, &poly->r0, &poly->r0, &poly->r0);
TriangulateQuad();
g_vertexIndex += 6;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0xE0: // DR_ENV commands
{
DR_ENV* drenv = (DR_ENV*)pTag;
// parse each code of the command
for (int i = 0; i < pTag->len; i++)
{
u_long code = drenv->code[i];
u_char drcode = code >> 24 & 0xFF;
switch (drcode)
{
case 0xE1:
{
activeDrawEnv.tpage = (code & 0x1FF);
activeDrawEnv.dtd = (code >> 9) & 1;
activeDrawEnv.dfe = (code >> 10) & 1;
break;
}
case 0xE2:
{
activeDrawEnv.tw.w = (code & 0x1F);
activeDrawEnv.tw.h = ((code >> 5) & 0x1F);
activeDrawEnv.tw.x = ((code >> 10) & 0x1F);
activeDrawEnv.tw.y = ((code >> 15) & 0x1F);
break;
}
case 0xE3:
{
activeDrawEnv.clip.x = code & 1023;
activeDrawEnv.clip.y = (code >> 10) & 1023;
break;
}
case 0xE4:
{
activeDrawEnv.clip.w = code & 1023;
activeDrawEnv.clip.h = (code >> 10) & 1023;
activeDrawEnv.clip.w -= activeDrawEnv.clip.x;
activeDrawEnv.clip.h -= activeDrawEnv.clip.y;
break;
}
case 0xE5:
{
activeDrawEnv.ofs[0] = code & 2047;//sign_x_to_s32(11, (*cb & 2047));
activeDrawEnv.ofs[1] = (code >> 11) & 2047; //sign_x_to_s32(11, ((*cb >> 11) & 2047));
break;
}
case 0xE6:
{
eprintf("Mask setting: %08x\n", code);
//MaskSetOR = (*cb & 1) ? 0x8000 : 0x0000;
//MaskEvalAND = (*cb & 2) ? 0x8000 : 0x0000;
break;
}
}
}
#if 0
switch (pTag->code)
{
case 0xE1:
{
#if defined(USE_32_BIT_ADDR)
unsigned short tpage = ((unsigned short*)pTag)[4];
#else
unsigned short tpage = ((unsigned short*)pTag)[2];
#endif
//if (tpage != 0)
{
activeDrawEnv.tpage = tpage;
//activeDrawEnv.dtd =
//activeDrawEnv.dfe
}
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
case 0xE3:
{
// FIXME: this is ugly
DR_AREA* drarea = (DR_AREA*)pTag;
RECT16 rect;
rect.x = drarea->code[0] & 0x3FF;
rect.y = ((drarea->code[0] >> 10) & 0x3FF);
// not W/H but x2 y2
rect.w = (drarea->code[1] & 0x3FF) - rect.x;
rect.h = ((drarea->code[1] >> 10) & 0x3FF) - rect.y;
activeDrawEnv.clip = rect;
#if defined(DEBUG_POLY_COUNT)
polygon_count++;
#endif
break;
}
// FIXME: there is multiple codes in single DR_* primitive
default:
{
eprinterr("Primitive type error: %x", pTag->code);
assert(FALSE);
break;
}
}
#endif
break;
}
default:
{
//Unhandled poly type
eprinterr("Unhandled primitive type: %02X type2:%02X\n", pTag->code, pTag->code & ~3);
break;
}
}
#ifdef USE_32_BIT_ADDR
return (pTag->len + 2) * sizeof(long);
#else
return (pTag->len + 1) * sizeof(long);
#endif
}
int ParseLinkedPrimitiveList(uintptr_t packetStart, uintptr_t packetEnd)
{
uintptr_t currentAddress = packetStart;
int lastSize = -1;
while (currentAddress != packetEnd)
{
lastSize = ParsePrimitive(currentAddress);
if (lastSize == -1) // not valid packets submitted
break;
currentAddress += lastSize;
}
g_splits[g_splitIndex].vCount = g_vertexIndex - g_splits[g_splitIndex].vIndex;
return lastSize;
}
void SetSprt16(SPRT_16* p)
{
setSprt16(p);
}
void SetSprt8(SPRT_8* p)
{
setSprt8(p);
}
void SetTile(TILE* p)
{
setTile(p);
}
void SetPolyGT4(POLY_GT4* p)
{
setPolyGT4(p);
}
void SetSemiTrans(void* p, int abe)
{
setSemiTrans(p, abe);
}
void SetShadeTex(void* p, int tge)
{
setShadeTex(p, tge);
}
void SetSprt(SPRT* p)
{
setSprt(p);
}
void SetDumpFnt(int id)
{
UNIMPLEMENTED();
}
void SetLineF3(LINE_F3* p)
{
setLineF3(p);
}
void FntLoad(int tx, int ty)
{
UNIMPLEMENTED();
}
void AddPrim(void* ot, void* p)
{
addPrim(ot, p);
}
void AddPrims(void* ot, void* p0, void* p1)
{
addPrims(ot, p0, p1);
}
void CatPrim(void* p0, void* p1)
{
catPrim(p0, p1);
}
u_short LoadTPage(u_long* pix, int tp, int abr, int x, int y, int w, int h)
{
RECT16 imageArea;
imageArea.x = x;
imageArea.y = y;
imageArea.h = h;
enum
{
TP_4BIT,
TP_8BIT,
TP_16BIT
};
switch (tp)
{
case TP_4BIT:
{
//loc_278
if (w >= 0)
{
imageArea.w = w >> 2;
}
else
{
imageArea.w = (w + 3) >> 2;
}
break;
}
case TP_8BIT:
{
//loc_290
imageArea.w = (w + (w >> 31)) >> 1;
break;
}
case TP_16BIT:
{
//loc_2A4
imageArea.w = w;
break;
}
}
//loc_2AC
LoadImagePSX(&imageArea, pix);
return GetTPage(tp, abr, x, y) & 0xFFFF;
}
u_short GetTPage(int tp, int abr, int x, int y)
{
return getTPage(tp, abr, x, y);
}
u_short LoadClut(u_long* clut, int x, int y)
{
RECT16 rect;//&var_18
setRECT16(&rect, x, y, 256, 1);
LoadImagePSX(&rect, clut);
return GetClut(x, y) & 0xFFFF;
}
u_short LoadClut2(u_long* clut, int x, int y)
{
RECT16 drawArea;
drawArea.x = x;
drawArea.y = y;
drawArea.w = 16;
drawArea.h = 1;
LoadImagePSX(&drawArea, clut);
return getClut(x, y);
}
u_long* KanjiFntFlush(int id)
{
UNIMPLEMENTED();
return 0;
}
u_long* FntFlush(int id)
{
UNIMPLEMENTED();
return 0;
}
int KanjiFntOpen(int x, int y, int w, int h, int dx, int dy, int cx, int cy, int isbg, int n)
{
UNIMPLEMENTED();
return 0;
}
int FntOpen(int x, int y, int w, int h, int isbg, int n)
{
UNIMPLEMENTED();
return 0;
}
void SetPolyF4(POLY_F4* p)
{
setPolyF4(p);
}
void SetPolyFT4(POLY_FT4* p)
{
setPolyFT4(p);
}
void SetPolyG4(POLY_G4* p)
{
setPolyG4(p);
}
void TermPrim(void* p)
{
termPrim(p);
}