Skip to content

Commit 8add3e1

Browse files
committedDec 20, 2024·
Adding an example with CLUT CSM1/2 variants
1 parent ffd089d commit 8add3e1

File tree

2 files changed

+164
-0
lines changed

2 files changed

+164
-0
lines changed
 

‎CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ if(NOT SKIP_BUILD_EXAMPLES)
352352
bigtex
353353
coverflow
354354
clut
355+
clutcsm
355356
cube
356357
fb
357358
fhdbg

‎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.