Skip to content

Commit 87a823f

Browse files
authoredDec 20, 2024··
Merge pull request #88 from fjtrujy/poc_CSM2
Adding basic`CSM2` CLUT Storage Mode Support
2 parents 2bc919a + 8add3e1 commit 87a823f

File tree

7 files changed

+235
-14
lines changed

7 files changed

+235
-14
lines changed
 

‎CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ add_object_library_macros(GS_CORE_OBJS ee/gs/src/gsCore.c
131131
gsKit_set_clamp
132132
gsKit_set_primalpha
133133
gsKit_set_texfilter
134+
gsKit_set_texclut
134135
gsKit_set_dither_matrix
135136
gsKit_set_dither
136137
gsKit_set_drawfield
@@ -351,6 +352,7 @@ if(NOT SKIP_BUILD_EXAMPLES)
351352
bigtex
352353
coverflow
353354
clut
355+
clutcsm
354356
cube
355357
fb
356358
fhdbg

‎ee/gs/include/gsCore.h

+8
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@
6868
/// Use bilinear filter on texture
6969
#define GS_FILTER_LINEAR 0x01
7070

71+
/// Use clut storage mode CSM1
72+
#define GS_CLUT_STORAGE_CSM1 0x00
73+
/// Use clut storage mode CSM2
74+
#define GS_CLUT_STORAGE_CSM2 0x01
75+
7176
/// Basic X/Y/Z Vertex Structure
7277
struct gsVertex
7378
{
@@ -209,6 +214,9 @@ void gsKit_set_primalpha(GSGLOBAL *gsGlobal, u64 AlphaMode, u8 PerPixel);
209214
/// Sets the Texture Filtering Parameters
210215
void gsKit_set_texfilter(GSGLOBAL *gsGlobal, u8 FilterMode);
211216

217+
/// Sets the CLUT position specfications
218+
void gsKit_set_texclut(GSGLOBAL *gsGlobal, gs_texclut texClut);
219+
212220
/// Sets the Dither Matrix Setting
213221
void gsKit_set_dither_matrix(GSGLOBAL *gsGlobal);
214222

‎ee/gs/include/gsInit.h

+20
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ struct gsTexture
959959
u32 Vram; ///< GS VRAM Memory Pointer
960960
u32 VramClut; ///< GS VRAM CLUT Memory Pointer
961961
u32 Filter; ///< NEAREST or LINEAR
962+
u8 ClutStorageMode; ///< CLUT Storage Mode
962963
u8 Delayed; ///< Delay Texture Upload To VRAM
963964
};
964965
typedef struct gsTexture GSTEXTURE;
@@ -1039,6 +1040,25 @@ typedef union {
10391040
};
10401041
} __attribute__((packed)) gs_stq;
10411042

1043+
typedef union {
1044+
u64 position;
1045+
struct {
1046+
u32 cbw : 6; // Bits 0-5 (6 bits)
1047+
u32 cou : 6; // Bits 6-11 (6 bits)
1048+
u32 cov : 10; // Bits 12-21 (10 bits)
1049+
u32 unused_bits: 10; // Bits 22-31 (10 bits)
1050+
u32 unused; // Remaining bits (64 - 22 = 42 bits)
1051+
} __attribute__((packed)); // Pack the structure to avoid padding
1052+
} __attribute__((packed)) gs_textclut_t;
1053+
1054+
typedef union {
1055+
u128 texclut;
1056+
struct {
1057+
gs_textclut_t specification;
1058+
u64 tag;
1059+
};
1060+
} __attribute__((packed)) gs_texclut;
1061+
10421062
/// gsKit Point Primitive Structure
10431063
/// This structure holds all relevant data for any
10441064
/// given point object, regardless of original format or type.

‎ee/gs/include/gsInline.h

+12
Original file line numberDiff line numberDiff line change
@@ -230,4 +230,16 @@ static inline gs_stq vertex_to_STQ(float s, float t)
230230
return res;
231231
}
232232

233+
static inline gs_texclut postion_to_TEXCLUT(u8 cbw, u8 cou, u8 cov)
234+
{
235+
gs_texclut res;
236+
237+
res.specification.cbw = cbw;
238+
res.specification.cou = cou;
239+
res.specification.cov = cov;
240+
res.tag = GS_TEXCLUT;
241+
242+
return res;
243+
}
244+
233245
#endif /* __GSINLINE_H__ */

‎ee/gs/src/gsCore.c

+16
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,22 @@ void gsKit_set_texfilter(GSGLOBAL *gsGlobal, u8 FilterMode)
411411
}
412412
#endif
413413

414+
#if F_gsKit_set_texclut
415+
void gsKit_set_texclut(GSGLOBAL *gsGlobal, gs_texclut texClut)
416+
{
417+
u64 *p_data;
418+
u64 *p_store;
419+
420+
p_data = p_store = gsKit_heap_alloc(gsGlobal, 1, 16, GIF_AD);
421+
422+
*p_data++ = GIF_TAG_AD(1);
423+
*p_data++ = GIF_AD;
424+
425+
memcpy(p_data, &texClut, sizeof(gs_texclut));
426+
p_data += 2; // Advance 2 u64, which is 16 bytes the gs_texclut struct size
427+
}
428+
#endif
429+
414430
#if F_gsKit_set_dither_matrix
415431
void gsKit_set_dither_matrix(GSGLOBAL *gsGlobal)
416432
{

‎ee/gs/src/gsTexture.c

+14-14
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ void gsKit_prim_sprite_texture_3d(GSGLOBAL *gsGlobal, const GSTEXTURE *Texture,
505505
{
506506
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
507507
tw, th, gsGlobal->PrimAlphaEnable, 0,
508-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
508+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
509509
}
510510

511511
*p_data++ = GS_SETREG_PRIM( GS_PRIM_PRIM_SPRITE, 0, 1, gsGlobal->PrimFogEnable,
@@ -720,7 +720,7 @@ void gskit_prim_list_sprite_texture_uv_3d(GSGLOBAL *gsGlobal, const GSTEXTURE *T
720720
{
721721
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
722722
tw, th, gsGlobal->PrimAlphaEnable, 0,
723-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
723+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
724724
}
725725
*p_data++ = GS_TEX0_1 + gsGlobal->PrimContext;
726726

@@ -765,7 +765,7 @@ void gskit_prim_list_sprite_texture_uv_flat(GSGLOBAL *gsGlobal, const GSTEXTURE
765765
{
766766
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
767767
tw, th, gsGlobal->PrimAlphaEnable, 0,
768-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
768+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
769769
}
770770
*p_data++ = GS_TEX0_1 + gsGlobal->PrimContext;
771771

@@ -810,7 +810,7 @@ void gskit_prim_list_sprite_texture_uv_flat_color(GSGLOBAL *gsGlobal, const GSTE
810810
{
811811
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
812812
tw, th, gsGlobal->PrimAlphaEnable, 0,
813-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
813+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
814814
}
815815
*p_data++ = GS_TEX0_1 + gsGlobal->PrimContext;
816816

@@ -891,7 +891,7 @@ void gsKit_prim_triangle_texture_3d(GSGLOBAL *gsGlobal, GSTEXTURE *Texture,
891891
{
892892
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
893893
tw, th, gsGlobal->PrimAlphaEnable, 0,
894-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
894+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
895895
}
896896

897897
*p_data++ = GS_SETREG_PRIM( GS_PRIM_PRIM_TRIANGLE, 0, 1, gsGlobal->PrimFogEnable,
@@ -975,7 +975,7 @@ void gsKit_prim_triangle_goraud_texture_3d(GSGLOBAL *gsGlobal, GSTEXTURE *Textur
975975
{
976976
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
977977
tw, th, gsGlobal->PrimAlphaEnable, 0,
978-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
978+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
979979
}
980980

981981
*p_data++ = GS_SETREG_PRIM( GS_PRIM_PRIM_TRIANGLE, 1, 1, gsGlobal->PrimFogEnable,
@@ -1028,7 +1028,7 @@ void gsKit_prim_list_triangle_goraud_texture_uv_3d(GSGLOBAL *gsGlobal, GSTEXTURE
10281028
{
10291029
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
10301030
tw, th, gsGlobal->PrimAlphaEnable, 0,
1031-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1031+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
10321032
}
10331033
*p_data++ = GS_TEX0_1 + gsGlobal->PrimContext;
10341034

@@ -1073,7 +1073,7 @@ void gsKit_prim_list_triangle_goraud_texture_stq_3d(GSGLOBAL *gsGlobal, GSTEXTUR
10731073
{
10741074
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
10751075
tw, th, gsGlobal->PrimAlphaEnable, 0,
1076-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1076+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
10771077
}
10781078
*p_data++ = GS_TEX0_1 + gsGlobal->PrimContext;
10791079

@@ -1127,7 +1127,7 @@ void gsKit_prim_triangle_strip_texture(GSGLOBAL *gsGlobal, GSTEXTURE *Texture,
11271127
{
11281128
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
11291129
tw, th, gsGlobal->PrimAlphaEnable, 0,
1130-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1130+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
11311131
}
11321132
*p_data++ = GS_TEX0_1+gsGlobal->PrimContext;
11331133

@@ -1192,7 +1192,7 @@ void gsKit_prim_triangle_strip_texture_3d(GSGLOBAL *gsGlobal, GSTEXTURE *Texture
11921192
{
11931193
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
11941194
tw, th, gsGlobal->PrimAlphaEnable, 0,
1195-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1195+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
11961196
}
11971197
*p_data++ = GS_TEX0_1+gsGlobal->PrimContext;
11981198

@@ -1256,7 +1256,7 @@ void gsKit_prim_triangle_fan_texture(GSGLOBAL *gsGlobal, GSTEXTURE *Texture,
12561256
{
12571257
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
12581258
tw, th, gsGlobal->PrimAlphaEnable, 0,
1259-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1259+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
12601260
}
12611261
*p_data++ = GS_TEX0_1+gsGlobal->PrimContext;
12621262

@@ -1320,7 +1320,7 @@ void gsKit_prim_triangle_fan_texture_3d(GSGLOBAL *gsGlobal, GSTEXTURE *Texture,
13201320
{
13211321
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
13221322
tw, th, gsGlobal->PrimAlphaEnable, 0,
1323-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1323+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
13241324
}
13251325
*p_data++ = GS_TEX0_1+gsGlobal->PrimContext;
13261326

@@ -1416,7 +1416,7 @@ void gsKit_prim_quad_texture_3d(GSGLOBAL *gsGlobal, GSTEXTURE *Texture,
14161416
{
14171417
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
14181418
tw, th, gsGlobal->PrimAlphaEnable, 0,
1419-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1419+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
14201420
}
14211421

14221422
*p_data++ = GS_SETREG_PRIM( GS_PRIM_PRIM_TRISTRIP, 0, 1, gsGlobal->PrimFogEnable,
@@ -1511,7 +1511,7 @@ void gsKit_prim_quad_goraud_texture_3d(GSGLOBAL *gsGlobal, GSTEXTURE *Texture,
15111511
{
15121512
*p_data++ = GS_SETREG_TEX0(Texture->Vram/256, Texture->TBW, Texture->PSM,
15131513
tw, th, gsGlobal->PrimAlphaEnable, 0,
1514-
Texture->VramClut/256, Texture->ClutPSM, 0, 0, GS_CLUT_STOREMODE_LOAD);
1514+
Texture->VramClut/256, Texture->ClutPSM, Texture->ClutStorageMode, 0, GS_CLUT_STOREMODE_LOAD);
15151515
}
15161516

15171517
*p_data++ = GS_SETREG_PRIM( GS_PRIM_PRIM_TRISTRIP, 1, 1, gsGlobal->PrimFogEnable,

‎examples/clutcsm/clutcsm.c

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// ____ ___ | / _____ _____
2+
// | __ | |___/ | |
3+
// |___| ___| | \ __|__ | gsKit Open Source Project.
4+
// ----------------------------------------------------------------------
5+
// Copyright 2004 - Chris "Neovanglist" Gilbert <Neovanglist@LainOS.org>
6+
// Licenced under Academic Free License version 2.0
7+
// Review gsKit README & LICENSE files for further details.
8+
//
9+
// textures.c - Example demonstrating how the 2 different CLUT storage modes work.
10+
// CSMT1 and CSM1 are the two different CLUT storage modes. CSM1 is the default
11+
// mode, and is the mode that is used which requires to have the content swizzled
12+
// before uploading it to the GS. However, CSM2 is a mode that allows you to
13+
// upload the CLUT data directly to the GS, without having to swizzle it first.
14+
// Additionally it allows you to upload a list of CLUTs, and then switch between
15+
// them using the GS_SETCLUT command.
16+
//
17+
//
18+
19+
#include <stdio.h>
20+
#include <malloc.h>
21+
22+
#include <gsKit.h>
23+
#include <dmaKit.h>
24+
#include <gsToolkit.h>
25+
#include <gsInline.h>
26+
#include <gsTexture.h>
27+
28+
#define CLUT_SIZE 256
29+
#define TEXTURE_WIDTH 320
30+
#define TEXTURE_HEIGHT 240
31+
32+
#define USING_CSM1 0
33+
34+
#if USING_CSM1
35+
#define TEXTURE_CLUT_WIDTH 16
36+
#define TEXTURE_CLUT_HEIGHT 16
37+
#else
38+
#define TEXTURE_CLUT_WIDTH 256
39+
#define TEXTURE_CLUT_HEIGHT 1
40+
#endif
41+
42+
int main(int argc, char *argv[])
43+
{
44+
GSGLOBAL *gsGlobal;
45+
GSTEXTURE tex;
46+
uint32_t i, j, offset;
47+
uint32_t totalVertices = 2;
48+
uint64_t White = GS_SETREG_RGBAQ(0xFF, 0xFF, 0xFF, 0x00, 0x00);
49+
gs_rgbaq color = color_to_RGBAQ(0x80, 0x80, 0x80, 0x80, 0);
50+
51+
gsGlobal = gsKit_init_global();
52+
53+
gsGlobal->PSM = GS_PSM_CT24;
54+
gsGlobal->PSMZ = GS_PSMZ_16S;
55+
56+
dmaKit_init(D_CTRL_RELE_OFF, D_CTRL_MFD_OFF, D_CTRL_STS_UNSPEC,
57+
D_CTRL_STD_OFF, D_CTRL_RCYC_8, 1 << DMA_CHANNEL_GIF);
58+
59+
// Initialize the DMAC
60+
dmaKit_chan_init(DMA_CHANNEL_GIF);
61+
62+
gsKit_init_screen(gsGlobal);
63+
gsKit_mode_switch(gsGlobal, GS_ONESHOT);
64+
65+
tex.Width = TEXTURE_WIDTH;
66+
tex.Height = TEXTURE_HEIGHT;
67+
tex.PSM = GS_PSM_T8;
68+
tex.ClutPSM = GS_PSM_CT16;
69+
tex.Clut = memalign(128, gsKit_texture_size_ee(CLUT_SIZE, 1, tex.ClutPSM));
70+
tex.Mem = memalign(128, gsKit_texture_size_ee(tex.Width, tex.Height, tex.PSM));
71+
tex.Vram = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(tex.Width, tex.Height, GS_PSM_T8), GSKIT_ALLOC_USERBUFFER);
72+
tex.VramClut = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(TEXTURE_CLUT_WIDTH, TEXTURE_CLUT_HEIGHT, GS_PSM_CT16), GSKIT_ALLOC_USERBUFFER);
73+
#if USING_CSM1
74+
tex.ClutStorageMode = GS_CLUT_STORAGE_CSM1;
75+
#else
76+
tex.ClutStorageMode = GS_CLUT_STORAGE_CSM2;
77+
#endif
78+
79+
printf("Tex VRAM Range = 0x%X - 0x%X\n", tex.Vram, tex.Vram + gsKit_texture_size(tex.Width, tex.Height, tex.PSM) - 1);
80+
81+
gsKit_set_clamp(gsGlobal, GS_CMODE_CLAMP);
82+
83+
uint16_t colors[4] = {
84+
0xEFFF,
85+
0x001F,
86+
0x03E0,
87+
0x7C00,
88+
};
89+
90+
// fill the clut, each 16 positions are the same color
91+
uint16_t *clut = (uint16_t *)tex.Clut;
92+
for (i = 0; i < CLUT_SIZE; i += 16)
93+
{
94+
for (j = 0; j < 16; ++j)
95+
{
96+
clut[i + j] = colors[(i / 16) & 0x3];
97+
}
98+
}
99+
#if USING_CSM1
100+
// Swap the texture to have the CSM1 requirements
101+
for (i = 0; i < CLUT_SIZE; i++)
102+
{
103+
if ((i & 0x18) == 8)
104+
{
105+
uint16_t tmp = clut[i];
106+
clut[i] = clut[i + 8];
107+
clut[i + 8] = tmp;
108+
}
109+
}
110+
#endif
111+
112+
// print the clut, 16 colors per line
113+
for (i = 0; i < CLUT_SIZE; i += 16)
114+
{
115+
for (j = 0; j < 16; ++j)
116+
{
117+
printf("%04X ", clut[i + j]);
118+
}
119+
printf("\n");
120+
}
121+
122+
// initialize texture, each 16 horizontal pixels are the same color, so let's point to the right color
123+
uint8_t *tex256 = (uint8_t *)tex.Mem;
124+
for (i = 0; i < TEXTURE_HEIGHT; ++i)
125+
{
126+
for (j = 0; j < TEXTURE_WIDTH; ++j)
127+
{
128+
tex256[i * TEXTURE_WIDTH + j] = j & 0xFF;
129+
}
130+
}
131+
132+
gsKit_texture_send((u32 *)tex.Mem, tex.Width, tex.Height, tex.Vram, tex.PSM, 1, GS_CLUT_TEXTURE);
133+
gsKit_texture_send((u32 *)tex.Clut, TEXTURE_CLUT_WIDTH, TEXTURE_CLUT_HEIGHT, tex.VramClut, tex.ClutPSM, 1, GS_CLUT_PALLETE);
134+
135+
GSPRIMUVPOINTFLAT *verts = (GSPRIMUVPOINTFLAT *)malloc(sizeof(GSPRIMUVPOINTFLAT) * totalVertices);
136+
verts[0].xyz2 = vertex_to_XYZ2(gsGlobal, 0, 0, 0);
137+
verts[0].uv = vertex_to_UV(&tex, 0, 0);
138+
139+
verts[1].xyz2 = vertex_to_XYZ2(gsGlobal, gsGlobal->Width, gsGlobal->Height, 0);
140+
verts[1].uv = vertex_to_UV(&tex, tex.Width, tex.Height);
141+
142+
offset = 0;
143+
144+
gs_texclut texclut = postion_to_TEXCLUT(4, 0, 0);
145+
146+
while (1)
147+
{
148+
gsKit_clear(gsGlobal, White);
149+
#if !USING_CSM1
150+
gsKit_set_texclut(gsGlobal, texclut);
151+
#endif
152+
gskit_prim_list_sprite_texture_uv_flat_color(gsGlobal, &tex, color, totalVertices, verts);
153+
154+
gsKit_queue_exec(gsGlobal);
155+
gsKit_sync_flip(gsGlobal);
156+
157+
offset++;
158+
}
159+
160+
free(verts);
161+
162+
return 0;
163+
}

0 commit comments

Comments
 (0)
Please sign in to comment.