Latest compatible version of Classicube from the original GitHub repository (https://github.com/ClassiCube/ClassiCube) that can be compiled on Classicube for PowerMac PPC running Mac OS X 10.4.
This commit is contained in:
25
third_party/gldc/LICENSE
vendored
Normal file
25
third_party/gldc/LICENSE
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2018, Luke Benstead
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
26
third_party/gldc/gldc.h
vendored
Normal file
26
third_party/gldc/gldc.h
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef PRIVATE_H
|
||||
#define PRIVATE_H
|
||||
#include <stdint.h>
|
||||
|
||||
#define GLDC_FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#define GLDC_NO_INLINE __attribute__((noinline))
|
||||
|
||||
typedef struct {
|
||||
/* Same 32 byte layout as pvr_vertex_t */
|
||||
uint32_t flags;
|
||||
float x, y, w;
|
||||
uint32_t u, v; // really floats, but stored as uint for better load/store codegen
|
||||
uint32_t bgra;
|
||||
float z; // actually oargb, but repurposed since unused
|
||||
} __attribute__ ((aligned (32))) Vertex;
|
||||
|
||||
typedef struct {
|
||||
uint32_t format;
|
||||
void *data;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
} TextureObject;
|
||||
|
||||
void GLDC_NO_INLINE SubmitCommands(Vertex* v3, int n);
|
||||
|
||||
#endif // PRIVATE_H
|
||||
258
third_party/gldc/sh4.c
vendored
Normal file
258
third_party/gldc/sh4.c
vendored
Normal file
@@ -0,0 +1,258 @@
|
||||
#include <kos.h>
|
||||
#include <dc/pvr.h>
|
||||
#include "gldc.h"
|
||||
|
||||
#define PushVertex(src, dst) __asm__ volatile ( \
|
||||
"fmov.d @%1+, dr0 ! LS, FX = *src, src += 8\n" \
|
||||
"fmov.d @%1+, dr2 ! LS, YW = *src, src += 8\n" \
|
||||
"add #64, %0 ! EX, dst += 64\n" \
|
||||
"fmul fr3, fr3 ! FE, W = W * W\n" \
|
||||
"fmov.d @%1+, dr4 ! LS, UV = *src, src += 8\n" \
|
||||
"fmov.d @%1+, dr6 ! LS, C? = *src, src += 8\n" \
|
||||
"fsrra fr3 ! FE, W = 1/sqrt(W*W) ~ 1/W\n" \
|
||||
"fmov.d dr6, @-%0 ! LS, dst -= 8, *dst = C?\n" \
|
||||
"fmov.d dr4, @-%0 ! LS, dst -= 8, *dst = UV\n" \
|
||||
"fmul fr3, fr2 ! FE, Y = W * Y\n" \
|
||||
"add #-32, %1 ! EX, src -= 32\n" \
|
||||
"fmov.d dr2, @-%0 ! LS, dst -= 8, *dst = YW\n" \
|
||||
"fmul fr3, fr1 ! FE, Y = X * X\n" \
|
||||
"fmov.d dr0, @-%0 ! LS, dst -= 8, *dst = FX\n" \
|
||||
"pref @%0 ! LS, flush store queue\n" \
|
||||
: "+r" (dst) \
|
||||
: "r" (src) \
|
||||
: "memory", "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7" \
|
||||
);
|
||||
|
||||
#define PushCommand(src, dst) __asm__ volatile ( \
|
||||
"fmov.d @%1+, dr0 ! LS, D01 = *src, src += 8\n" \
|
||||
"fmov.d @%1+, dr2 ! LS, D23 = *src, src += 8\n" \
|
||||
"fmov.d @%1+, dr4 ! LS, D45 = *src, src += 8\n" \
|
||||
"fmov.d @%1+, dr6 ! LS, D67 = *src, src += 8\n" \
|
||||
"add #64, %0 ! EX, dst += 64\n" \
|
||||
"fmov.d dr6, @-%0 ! LS, dst -= 8, *dst = D67\n" \
|
||||
"fmov.d dr4, @-%0 ! LS, dst -= 8, *dst = D45\n" \
|
||||
"fmov.d dr2, @-%0 ! LS, dst -= 8, *dst = D23\n" \
|
||||
"fmov.d dr0, @-%0 ! LS, dst -= 8, *dst = D01\n" \
|
||||
"pref @%0 ! LS, flush store queue\n" \
|
||||
"add #-32, %1 ! EX, src -= 32\n" \
|
||||
: "+r" (dst) \
|
||||
: "r" (src) \
|
||||
: "memory", "fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7" \
|
||||
);
|
||||
|
||||
extern void ClipEdge(Vertex* const v1, Vertex* const v2, volatile Vertex* vout, char type);
|
||||
|
||||
#define V0_VIS (1 << 0)
|
||||
#define V1_VIS (1 << 1)
|
||||
#define V2_VIS (1 << 2)
|
||||
#define V3_VIS (1 << 3)
|
||||
|
||||
#define TYPE_VTX 0xE0 // PVR vertex, data
|
||||
#define TYPE_EOS 0xF0 // PVR vertex, end of strip
|
||||
|
||||
extern void ProcessVertexList(Vertex* v3, int n, void* sq_addr);
|
||||
|
||||
void SubmitCommands(Vertex* v3, int n) {
|
||||
volatile Vertex* dst = (volatile Vertex*)MEM_AREA_SQ_BASE;
|
||||
Vertex* vEnd = v3 + n;
|
||||
asm volatile ("fschg"); // swap to 64 bit loads/stores
|
||||
|
||||
for (; v3 < vEnd; v3++)
|
||||
{
|
||||
// Preload next vertex into memory
|
||||
__builtin_prefetch(v3 + 1);
|
||||
|
||||
switch(v3->flags & 0xFF000000) {
|
||||
case PVR_CMD_VERTEX_EOL:
|
||||
break;
|
||||
case PVR_CMD_VERTEX:
|
||||
continue;
|
||||
default:
|
||||
PushCommand(v3, dst);
|
||||
continue;
|
||||
};
|
||||
|
||||
// Quads [0, 1, 2, 3] -> Triangles [{0, 1, 2} {2, 3, 0}]
|
||||
Vertex* const v0 = v3 - 3;
|
||||
Vertex* const v1 = v3 - 2;
|
||||
Vertex* const v2 = v3 - 1;
|
||||
uint8_t mask = v3->flags & 0xFF;
|
||||
|
||||
// Check if all vertices visible
|
||||
if (__builtin_expect(mask == (V0_VIS | V1_VIS | V2_VIS | V3_VIS), 1)) {
|
||||
// Triangle strip: {1,2,0} {2,0,3}
|
||||
PushVertex(v1, dst);
|
||||
PushVertex(v2, dst);
|
||||
PushVertex(v0, dst);
|
||||
PushVertex(v3, dst);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Only some vertices visible
|
||||
// https://casual-effects.com/research/McGuire2011Clipping/clip.glsl
|
||||
switch(mask) {
|
||||
case V0_VIS:
|
||||
// v0
|
||||
// / |
|
||||
// / |
|
||||
// .....A....B...
|
||||
// / |
|
||||
// v3--v2---v1
|
||||
PushVertex(v0, dst); // v0
|
||||
ClipEdge(v0, v1, dst++, TYPE_VTX); // B
|
||||
ClipEdge(v3, v0, dst++, TYPE_EOS); // A
|
||||
break;
|
||||
|
||||
case V1_VIS:
|
||||
// v1
|
||||
// / |
|
||||
// / |
|
||||
// ....A.....B...
|
||||
// / |
|
||||
// v0--v3---v2
|
||||
ClipEdge(v0, v1, dst++, TYPE_VTX); // A
|
||||
PushVertex(v1, dst); // v1
|
||||
ClipEdge(v1, v2, dst++, TYPE_EOS); // B
|
||||
break;
|
||||
|
||||
case V2_VIS:
|
||||
// v2
|
||||
// / |
|
||||
// / |
|
||||
// ....A.....B...
|
||||
// / |
|
||||
// v1--v0---v3
|
||||
ClipEdge(v1, v2, dst++, TYPE_VTX); // A
|
||||
PushVertex(v2, dst); // v2
|
||||
ClipEdge(v2, v3, dst++, TYPE_EOS); // B
|
||||
break;
|
||||
|
||||
case V3_VIS:
|
||||
// v3
|
||||
// / |
|
||||
// / |
|
||||
// ....A.....B...
|
||||
// / |
|
||||
// v2--v1---v0
|
||||
ClipEdge(v3, v0, dst++, TYPE_VTX); // B
|
||||
ClipEdge(v2, v3, dst++, TYPE_VTX); // A
|
||||
PushVertex(v3, dst); // v3
|
||||
break;
|
||||
|
||||
case V0_VIS | V1_VIS:
|
||||
// v0-----------v1
|
||||
// \ |
|
||||
// ....B..........A...
|
||||
// \ |
|
||||
// v3-----v2
|
||||
PushVertex(v1, dst); // v1
|
||||
ClipEdge(v1, v2, dst++, TYPE_VTX); // A
|
||||
PushVertex(v0, dst); // v0
|
||||
ClipEdge(v3, v0, dst++, TYPE_EOS); // B
|
||||
break;
|
||||
|
||||
// case V0_VIS | V2_VIS: degenerate case that should never happen
|
||||
case V0_VIS | V3_VIS:
|
||||
// v3-----------v0
|
||||
// \ |
|
||||
// ....B..........A...
|
||||
// \ |
|
||||
// v2-----v1
|
||||
ClipEdge(v0, v1, dst++, TYPE_VTX); // A
|
||||
ClipEdge(v2, v3, dst++, TYPE_VTX); // B
|
||||
PushVertex(v0, dst); // v0
|
||||
PushVertex(v3, dst); // v3
|
||||
break;
|
||||
|
||||
case V1_VIS | V2_VIS:
|
||||
// v1-----------v2
|
||||
// \ |
|
||||
// ....B..........A...
|
||||
// \ |
|
||||
// v0-----v3
|
||||
PushVertex(v1, dst); // v1
|
||||
PushVertex(v2, dst); // v2
|
||||
ClipEdge(v0, v1, dst++, TYPE_VTX); // B
|
||||
ClipEdge(v2, v3, dst++, TYPE_EOS); // A
|
||||
break;
|
||||
|
||||
// case V1_VIS | V3_VIS: degenerate case that should never happen
|
||||
case V2_VIS | V3_VIS:
|
||||
// v2-----------v3
|
||||
// \ |
|
||||
// ....B..........A...
|
||||
// \ |
|
||||
// v1-----v0
|
||||
ClipEdge(v1, v2, dst++, TYPE_VTX); // B
|
||||
PushVertex(v2, dst); // v2
|
||||
ClipEdge(v3, v0, dst++, TYPE_VTX); // A
|
||||
PushVertex(v3, dst); // v3
|
||||
break;
|
||||
|
||||
case V0_VIS | V1_VIS | V2_VIS:
|
||||
// --v1--
|
||||
// v0-- --v2
|
||||
// \ |
|
||||
// .....B.....A...
|
||||
// \ |
|
||||
// v3
|
||||
// v1,v2,v0 v2,v0,A v0,A,B
|
||||
PushVertex(v1, dst); // v1
|
||||
PushVertex(v2, dst); // v2
|
||||
PushVertex(v0, dst); // v0
|
||||
ClipEdge(v2, v3, dst++, TYPE_VTX); // A
|
||||
ClipEdge(v3, v0, dst++, TYPE_EOS); // B
|
||||
break;
|
||||
|
||||
case V0_VIS | V1_VIS | V3_VIS:
|
||||
// --v0--
|
||||
// v3-- --v1
|
||||
// \ |
|
||||
// .....B.....A...
|
||||
// \ |
|
||||
// v2
|
||||
// v0,v1,v3 v1,v3,A v3,A,B
|
||||
v3->flags = PVR_CMD_VERTEX;
|
||||
PushVertex(v0, dst); // v0
|
||||
PushVertex(v1, dst); // v1
|
||||
PushVertex(v3, dst); // v3
|
||||
ClipEdge(v1, v2, dst++, TYPE_VTX); // A
|
||||
ClipEdge(v2, v3, dst++, TYPE_EOS); // B
|
||||
break;
|
||||
|
||||
case V0_VIS | V2_VIS | V3_VIS:
|
||||
// --v3--
|
||||
// v2-- --v0
|
||||
// \ |
|
||||
// .....B.....A...
|
||||
// \ |
|
||||
// v1
|
||||
// v3,v0,v2 v0,v2,A v2,A,B
|
||||
v3->flags = PVR_CMD_VERTEX;
|
||||
PushVertex(v3, dst); // v3
|
||||
PushVertex(v0, dst); // v0
|
||||
PushVertex(v2, dst); // v2
|
||||
ClipEdge(v0, v1, dst++, TYPE_VTX); // A
|
||||
ClipEdge(v1, v2, dst++, TYPE_EOS); // B
|
||||
break;
|
||||
|
||||
case V1_VIS | V2_VIS | V3_VIS:
|
||||
// --v2--
|
||||
// v1-- --v3
|
||||
// \ |
|
||||
// .....B.....A...
|
||||
// \ |
|
||||
// v0
|
||||
// v2,v3,v1 v3,v1,A v1,A,B
|
||||
v3->flags = PVR_CMD_VERTEX;
|
||||
PushVertex(v2, dst); // v2
|
||||
PushVertex(v3, dst); // v3
|
||||
PushVertex(v1, dst); // v1
|
||||
ClipEdge(v3, v0, dst++, TYPE_VTX); // A
|
||||
ClipEdge(v0, v1, dst++, TYPE_EOS); // B
|
||||
break;
|
||||
}
|
||||
}
|
||||
asm volatile ("fschg"); // swap back to 32 bit loads/stores
|
||||
}
|
||||
110
third_party/gldc/state.c
vendored
Normal file
110
third_party/gldc/state.c
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
#include <dc/pvr.h>
|
||||
#include "gldc.h"
|
||||
|
||||
static TextureObject* TEXTURE_ACTIVE;
|
||||
|
||||
static uint8_t DEPTH_TEST_ENABLED;
|
||||
static uint8_t DEPTH_MASK_ENABLED;
|
||||
|
||||
static uint8_t CULLING_ENABLED;
|
||||
|
||||
static uint8_t FOG_ENABLED;
|
||||
static uint8_t ALPHA_TEST_ENABLED;
|
||||
|
||||
static uint8_t SCISSOR_TEST_ENABLED;
|
||||
static uint32_t SHADE_MODEL = PVR_SHADE_GOURAUD;
|
||||
|
||||
static uint8_t BLEND_ENABLED;
|
||||
|
||||
static uint8_t TEXTURES_ENABLED;
|
||||
static uint8_t AUTOSORT_ENABLED;
|
||||
|
||||
static inline int DimensionFlag(int w) {
|
||||
switch(w) {
|
||||
case 16: return 1;
|
||||
case 32: return 2;
|
||||
case 64: return 3;
|
||||
case 128: return 4;
|
||||
case 256: return 5;
|
||||
case 512: return 6;
|
||||
case 1024: return 7;
|
||||
case 8:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static GLDC_NO_INLINE void apply_poly_header(pvr_poly_hdr_t* dst, int list_type) {
|
||||
TextureObject* tx1 = TEXTURE_ACTIVE;
|
||||
|
||||
int gen_culling = CULLING_ENABLED ? PVR_CULLING_CW : PVR_CULLING_SMALL;
|
||||
int depth_comp = DEPTH_TEST_ENABLED ? PVR_DEPTHCMP_GEQUAL : PVR_DEPTHCMP_ALWAYS;
|
||||
int depth_write = DEPTH_MASK_ENABLED ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
|
||||
|
||||
int clip_mode = SCISSOR_TEST_ENABLED ? PVR_USERCLIP_INSIDE : PVR_USERCLIP_DISABLE;
|
||||
int fog_type = FOG_ENABLED ? PVR_FOG_TABLE : PVR_FOG_DISABLE;
|
||||
|
||||
int gen_alpha = (BLEND_ENABLED || ALPHA_TEST_ENABLED) ? PVR_ALPHA_ENABLE : PVR_ALPHA_DISABLE;
|
||||
int blend_src = PVR_BLEND_SRCALPHA;
|
||||
int blend_dst = PVR_BLEND_INVSRCALPHA;
|
||||
|
||||
if (list_type == PVR_LIST_OP_POLY) {
|
||||
/* Opaque polys are always one/zero */
|
||||
blend_src = PVR_BLEND_ONE;
|
||||
blend_dst = PVR_BLEND_ZERO;
|
||||
} else if (list_type == PVR_LIST_PT_POLY) {
|
||||
/* Punch-through polys require fixed blending and depth modes */
|
||||
depth_comp = PVR_DEPTHCMP_LEQUAL;
|
||||
} else if (list_type == PVR_LIST_TR_POLY && AUTOSORT_ENABLED) {
|
||||
/* Autosort mode requires this mode for transparent polys */
|
||||
depth_comp = PVR_DEPTHCMP_GEQUAL;
|
||||
}
|
||||
|
||||
int txr_enable, txr_alpha;
|
||||
if (!TEXTURES_ENABLED || !tx1) {
|
||||
/* Disable all texturing to start with */
|
||||
txr_enable = PVR_TEXTURE_DISABLE;
|
||||
} else {
|
||||
txr_alpha = (BLEND_ENABLED || ALPHA_TEST_ENABLED) ? PVR_TXRALPHA_ENABLE : PVR_TXRALPHA_DISABLE;
|
||||
txr_enable = PVR_TEXTURE_ENABLE;
|
||||
}
|
||||
|
||||
/* The base values for CMD */
|
||||
dst->cmd = PVR_CMD_POLYHDR;
|
||||
dst->cmd |= txr_enable << 3;
|
||||
/* Force bits 18 and 19 on to switch to 6 triangle strips */
|
||||
dst->cmd |= 0xC0000;
|
||||
|
||||
/* Or in the list type, shading type, color and UV formats */
|
||||
dst->cmd |= (list_type << PVR_TA_CMD_TYPE_SHIFT) & PVR_TA_CMD_TYPE_MASK;
|
||||
dst->cmd |= (PVR_CLRFMT_ARGBPACKED << PVR_TA_CMD_CLRFMT_SHIFT) & PVR_TA_CMD_CLRFMT_MASK;
|
||||
dst->cmd |= (SHADE_MODEL << PVR_TA_CMD_SHADE_SHIFT) & PVR_TA_CMD_SHADE_MASK;
|
||||
dst->cmd |= (PVR_UVFMT_32BIT << PVR_TA_CMD_UVFMT_SHIFT) & PVR_TA_CMD_UVFMT_MASK;
|
||||
dst->cmd |= (clip_mode << PVR_TA_CMD_USERCLIP_SHIFT) & PVR_TA_CMD_USERCLIP_MASK;
|
||||
|
||||
dst->mode1 = (depth_comp << PVR_TA_PM1_DEPTHCMP_SHIFT) & PVR_TA_PM1_DEPTHCMP_MASK;
|
||||
dst->mode1 |= (gen_culling << PVR_TA_PM1_CULLING_SHIFT) & PVR_TA_PM1_CULLING_MASK;
|
||||
dst->mode1 |= (depth_write << PVR_TA_PM1_DEPTHWRITE_SHIFT) & PVR_TA_PM1_DEPTHWRITE_MASK;
|
||||
dst->mode1 |= (txr_enable << PVR_TA_PM1_TXRENABLE_SHIFT) & PVR_TA_PM1_TXRENABLE_MASK;
|
||||
|
||||
dst->mode2 = (blend_src << PVR_TA_PM2_SRCBLEND_SHIFT) & PVR_TA_PM2_SRCBLEND_MASK;
|
||||
dst->mode2 |= (blend_dst << PVR_TA_PM2_DSTBLEND_SHIFT) & PVR_TA_PM2_DSTBLEND_MASK;
|
||||
dst->mode2 |= (fog_type << PVR_TA_PM2_FOG_SHIFT) & PVR_TA_PM2_FOG_MASK;
|
||||
dst->mode2 |= (gen_alpha << PVR_TA_PM2_ALPHA_SHIFT) & PVR_TA_PM2_ALPHA_MASK;
|
||||
|
||||
if (txr_enable == PVR_TEXTURE_DISABLE) {
|
||||
dst->mode3 = 0;
|
||||
} else {
|
||||
dst->mode2 |= (txr_alpha << PVR_TA_PM2_TXRALPHA_SHIFT) & PVR_TA_PM2_TXRALPHA_MASK;
|
||||
dst->mode2 |= (PVR_FILTER_NEAREST << PVR_TA_PM2_FILTER_SHIFT) & PVR_TA_PM2_FILTER_MASK;
|
||||
dst->mode2 |= (PVR_MIPBIAS_NORMAL << PVR_TA_PM2_MIPBIAS_SHIFT) & PVR_TA_PM2_MIPBIAS_MASK;
|
||||
dst->mode2 |= (PVR_TXRENV_MODULATEALPHA << PVR_TA_PM2_TXRENV_SHIFT) & PVR_TA_PM2_TXRENV_MASK;
|
||||
|
||||
dst->mode2 |= (DimensionFlag(tx1->width) << PVR_TA_PM2_USIZE_SHIFT) & PVR_TA_PM2_USIZE_MASK;
|
||||
dst->mode2 |= (DimensionFlag(tx1->height) << PVR_TA_PM2_VSIZE_SHIFT) & PVR_TA_PM2_VSIZE_MASK;
|
||||
|
||||
dst->mode3 = (0 << PVR_TA_PM3_MIPMAP_SHIFT) & PVR_TA_PM3_MIPMAP_MASK;
|
||||
dst->mode3 |= (tx1->format << PVR_TA_PM3_TXRFMT_SHIFT) & PVR_TA_PM3_TXRFMT_MASK;
|
||||
dst->mode3 |= ((uint32_t)tx1->data & 0x00fffff8) >> 3;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user