Skip to content

Instantly share code, notes, and snippets.

@F0bes
Last active March 9, 2022 01:29
Show Gist options
  • Save F0bes/fd9a83655f18e689a4ad3cea274ea72b to your computer and use it in GitHub Desktop.
Save F0bes/fd9a83655f18e689a4ad3cea274ea72b to your computer and use it in GitHub Desktop.
mipmapping
// Tests MTBA with MXL 0 and MMIN 0
// (MTBA still works with these set to 0)
#include "defs.h"
#include <kernel.h>
#include <tamtypes.h>
#include <stdio.h>
#include <gif_tags.h>
#include <gs_gp.h>
#include <gs_psm.h>
#include <dma.h>
#include <dma_tags.h>
#include <draw.h>
#include <graph.h>
#include <packet.h>
#include <stdlib.h>
#include <fcntl.h>
#include "texture128.c"
//#include "grad.c"
#include "texture64.c"
#include "texture32.c"
#include "texture16.c"
const u32 WIDTH = 640;
const u32 HEIGHT = 480;
const s32 FRAME_PSM = GS_PSM_24;
#undef GS_SET_MIPTBP1
#define GS_SET_MIPTBP1(TBA1, TBW1, TBA2, TBW2, TBA3, TBW3) \
(u64)((TBA1)&0x00003FFF) << 0 | (u64)((TBW1)&0x0000003F) << 14 | \
(u64)((TBA2)&0x00003FFF) << 20 | (u64)((TBW2)&0x0000003F) << 34 | \
(u64)((TBA3)&0x00003FFF) << 40 | (u64)((TBW3)&0x0000003F) << 54
#define GS_SETREG_TEST(ate, atst, aref, afail, date, datm, zte, ztst) \
((u64)(ate) | ((u64)(atst) << 1) | \
((u64)(aref) << 4) | ((u64)(afail) << 12) | \
((u64)(date) << 14) | ((u64)(datm) << 15) | \
((u64)(zte) << 16) | ((u64)(ztst) << 17))
int download_from_gs(u32 address, u32 format, const char *fname, int psm_size, int width, int height)
{
u32 destBuffer[width * height];
static union
{
u32 value_u32[4];
u128 value;
} enable_path3 ALIGNED(16) = {
{VIF1_MSKPATH3(0), VIF1_NOP, VIF1_NOP, VIF1_NOP}};
u32 prev_imr;
u32 prev_chcr;
u32 dmaChain[20 * 2] ALIGNED(16);
u32 i = 0; // Used to index through the chain
u32 *pdma32 = (u32 *)&dmaChain;
u64 *pdma64 = (u64 *)(pdma32 + 4);
// Set up VIF packet
pdma32[i++] = VIF1_NOP;
pdma32[i++] = VIF1_MSKPATH3(0x8000);
pdma32[i++] = VIF1_FLUSHA;
pdma32[i++] = VIF1_DIRECT(6);
// Set up our GS packet
i = 0;
pdma64[i++] = GIFTAG(5, 1, 0, 0, 0, 1);
pdma64[i++] = GIF_AD;
// pdma64[i++] = GSBITBLTBUF_SET(address / 64, width / 64, format, 0, 0, 0);
pdma64[i++] = GSBITBLTBUF_SET(address / 64, width < 64 ? 1 : width / 64, format, 0, 0, 0);
pdma64[i++] = GSBITBLTBUF;
pdma64[i++] = GSTRXPOS_SET(0, 0, 0, 0, 0); // SSAX, SSAY, DSAX, DSAY, DIR
pdma64[i++] = GSTRXPOS;
pdma64[i++] = GSTRXREG_SET(width, height); // RRW, RRh
pdma64[i++] = GSTRXREG;
pdma64[i++] = 0;
pdma64[i++] = GSFINISH;
pdma64[i++] = GSTRXDIR_SET(1); // XDIR
pdma64[i++] = GSTRXDIR;
prev_imr = GsPutIMR(GsGetIMR() | 0x0200);
prev_chcr = *D1_CHCR;
if ((*D1_CHCR & 0x0100) != 0)
return 0;
// Finish event
*GS_CSR = CSR_FINISH;
// DMA crap
FlushCache(0);
printf("DMA stuff\n");
*D1_QWC = 0x7;
*D1_MADR = (u32)pdma32;
*D1_CHCR = 0x101;
asm __volatile__("sync.l\n");
// check if DMA is complete (STR=0)
printf("Waiting for DMA channel completion\n");
while (*D1_CHCR & 0x0100)
;
printf("Waiting for GS_CSR\n");
while ((*GS_CSR & CSR_FINISH) == 0)
;
printf("Waiting for the vif fifo to empty\n");
// Wait for viffifo to become empty
while ((*VIF1_STAT & (0x1f000000)))
;
// Reverse busdir and transfer image to host
*VIF1_STAT = VIF1_STAT_FDR;
*GS_BUSDIR = (u64)0x00000001;
FlushCache(0);
u32 trans_size = ((width * height * psm_size) / 0x100);
printf("Download the frame in 2 transfers of qwc 0x%x\n", trans_size);
*D1_QWC = trans_size;
*D1_MADR = (u32)destBuffer;
*D1_CHCR = 0x100;
asm __volatile__(" sync.l\n");
// check if DMA is complete (STR=0)
while (*D1_CHCR & 0x0100)
;
*D1_QWC = trans_size;
*D1_CHCR = 0x100;
asm __volatile__(" sync.l\n");
// Wait for viffifo to become empty
while ((*VIF1_STAT & (0x1f000000)))
;
// check if DMA is complete (STR=0)
while (*D1_CHCR & 0x0100)
;
*D1_CHCR = prev_chcr;
asm __volatile__(" sync.l\n");
*VIF1_STAT = 0;
*GS_BUSDIR = (u64)0;
// Put back prew imr and set finish event
GsPutIMR(prev_imr);
*GS_CSR = CSR_FINISH;
// Enable path3 again
*VIF1_FIFO = enable_path3.value;
/*
Write out to a file
*/
FILE *f = fopen(fname, "w+");
if ((u32)f < 0)
{
printf("??? couldn't open file, trying usb\n");
}
printf("File should be size %d\n", (psm_size / 8) * width * height);
fwrite(destBuffer, psm_size / 8, width * height, f);
fclose(f);
return 0;
}
int main(void)
{
(*(volatile u_int *)0x10003000) = 1;
/*
Initialize graph
*/
framebuffer_t fb;
fb.width = WIDTH;
fb.height = HEIGHT;
fb.psm = FRAME_PSM;
fb.mask = 0x00000000;
fb.address = graph_vram_allocate(fb.width, fb.height, fb.psm, GRAPH_ALIGN_PAGE);
zbuffer_t zb;
zb.enable = 1;
zb.zsm = GS_ZBUF_32;
zb.address = graph_vram_allocate(fb.width, fb.height, zb.zsm, GRAPH_ALIGN_PAGE);
zb.mask = 0;
zb.method = ZTEST_METHOD_ALLPASS;
graph_initialize(fb.address, fb.width, fb.height, fb.psm, 0, 0);
dma_channel_initialize(DMA_CHANNEL_GIF, NULL, 0);
dma_channel_fast_waits(DMA_CHANNEL_GIF);
/*
Init drawing stuff
*/
packet_t *packet = packet_init(100, PACKET_NORMAL);
qword_t *q = packet->data;
q = draw_setup_environment(q, 0, &fb, &zb);
q = draw_primitive_xyoffset(q, 0, 0, 0);
q = draw_enable_tests(q, 0, &zb);
q = draw_finish(q);
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
draw_wait_finish();
/*
Upload texture
*/
q = packet->data;
FlushCache(0);
int texAddress128 = graph_vram_allocate(128, 128, GS_PSM_24, GRAPH_ALIGN_BLOCK);
int texAddress64 = texAddress128 + (128 * 128);
int texAddress32 = texAddress64 + (64 * 64);
int texAddress16 = texAddress32 + (32 * 32);
// int texAddress64 = graph_vram_allocate(64, 64, GS_PSM_24, GRAPH_ALIGN_BLOCK);
// int texAddress32 = graph_vram_allocate(32, 32, GS_PSM_24, GRAPH_ALIGN_BLOCK);
// int texAddress16 = graph_vram_allocate(16, 16, GS_PSM_24, GRAPH_ALIGN_BLOCK);
// printf("%d\n%d\n%d\n%d\n",texAddress128,texAddress64,texAddress32,texAddress16);
// tb.address = texAddress;
q = draw_texture_transfer(q, textureBuffer128, 128, 128, GS_PSM_24, texAddress128, 128);
q = draw_texture_transfer(q, textureBuffer64, 64, 64, GS_PSM_24, texAddress64, 64);
q = draw_texture_transfer(q, textureBuffer32, 32, 32, GS_PSM_24, texAddress32, 32);
q = draw_texture_transfer(q, textureBuffer16, 16, 16, GS_PSM_24, texAddress16, 16);
q = draw_texture_flush(q);
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
dma_wait_fast();
/*
Now draw something
*/
q = packet->data;
// Draw a full screen sprite
PACK_GIFTAG(q, GIF_SET_TAG(1, 1, GIF_PRE_ENABLE, GIF_PRIM_SPRITE, GIF_FLG_PACKED, 7),
GIF_REG_AD | (GIF_REG_AD << 4) | (GIF_REG_AD << 8) | (GIF_REG_AD << 12) | (GIF_REG_RGBAQ << 16) | (GIF_REG_XYZ2 << 20) | (GIF_REG_XYZ2 << 24));
q++;
q->dw[0] = GS_SET_TEX1(1, 0, 0, 0, 1, 0, 0); // MXL 0
q->dw[1] = GS_REG_TEX1;
q++; //
q->dw[0] = GS_SET_TEX0(texAddress128 / 64, 2, GS_PSM_24, 7, 7, 0, 1, 0, 0, 0, 0, 0);
q->dw[1] = GS_REG_TEX0;
q++;
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 0); // MXL 3
q->dw[1] = GS_REG_TEX1;
q++;
q->dw[0] = GS_SET_TEST(0, 0, 0, 0, 0, 0, 1, 1);
q->dw[1] = GS_REG_TEST;
q++;
// RGBAQ
q->dw[0] = (u64)((0x33) | ((u64)0x33 << 32));
q->dw[1] = (u64)((0x33) | ((u64)0 << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((0 << 4)) | (((u64)(0 << 4)) << 32)));
q->dw[1] = (u64)(0);
q++;
// XYZ2
q->dw[0] = (u64)((((640 << 4)) | (((u64)(480 << 4)) << 32)));
q->dw[1] = (u64)(0);
q++;
q = draw_finish(q);
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
draw_wait_finish();
int frame = 0;
// while (1)
{
// frame++;
// if (!(frame % 1000))
// {
// printf("1000Frames\n");
// allows me to reset ps2link
// }
q = packet->data;
PACK_GIFTAG(q, GIF_SET_TAG(4, 1, GIF_PRE_ENABLE, GIF_SET_PRIM(GIF_PRIM_SPRITE, 0, 1, 0, 0, 0, 0, 0, 0), GIF_FLG_PACKED, 6),
GIF_REG_AD | (GIF_REG_ST << 4) | (GIF_REG_RGBAQ << 8) | (GIF_REG_XYZ2 << 12) | (GIF_REG_ST << 16) | (GIF_REG_XYZ2 << 20));
q++;
{ // 128X128
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 0);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((0 << 4)) | (((u64)(0 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((128 << 4)) | (((u64)(128 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
{ // 64X64
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 1 << 4);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((128 << 4)) | (((u64)(0 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((256 << 4)) | (((u64)(128 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
{ // 32X32
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 2 << 4);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((256 << 4)) | (((u64)(0 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((386 << 4)) | (((u64)(128 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
{ // 16X16
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 3 << 4);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((386 << 4)) | (((u64)(0 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((512 << 4)) | (((u64)(128 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
q = draw_finish(q);
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
// Wait until the drawing is finished.
draw_wait_finish();
{
/* q = packet->data;
PACK_GIFTAG(q, GIF_SET_TAG(1, 1, GIF_PRE_DISABLE, GIF_PRIM_SPRITE, GIF_FLG_PACKED, 3),
GIF_REG_AD | (GIF_REG_AD << 4) | (GIF_REG_AD << 8));
q++;
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 0);
q->dw[1] = GS_REG_TEX1;
q++;
q->dw[0] = GS_SET_MIPTBP1(0,1,0,1,0,1);
q->dw[1] = GS_REG_MIPTBP1;
q++;
q->dw[0] = GS_SET_TEX0(texAddress128 / 64, 2, GS_PSM_24, 7, 7, 0, 1, 0, 0, 0, 0, 0);
q->dw[1] = GS_REG_TEX0;
q++;
q = draw_finish(q);
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
draw_wait_finish();*/
}
q = packet->data;
PACK_GIFTAG(q, GIF_SET_TAG(4, 1, GIF_PRE_ENABLE, GIF_SET_PRIM(GIF_PRIM_SPRITE, 0, 1, 0, 0, 0, 0, 0, 0), GIF_FLG_PACKED, 6),
GIF_REG_AD | (GIF_REG_ST << 4) | (GIF_REG_RGBAQ << 8) | (GIF_REG_XYZ2 << 12) | (GIF_REG_ST << 16) | (GIF_REG_XYZ2 << 20));
q++;
{ // 128X128
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 0);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((0 << 4)) | (((u64)(128 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((128 << 4)) | (((u64)(256 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
{ // 64X64
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 1 << 4);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((128 << 4)) | (((u64)(128 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((256 << 4)) | (((u64)(256 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
{ // 32X32
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 2 << 4);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((256 << 4)) | (((u64)(128 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((386 << 4)) | (((u64)(256 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
{ // 16X16
// TEST1
q->dw[0] = GS_SET_TEX1(1, 3, 0, 2, 1, 0, 3 << 4);
q->dw[1] = GS_REG_TEX1;
q++;
// UV
q->dw[0] = GIF_SET_ST(0 << 4, 0 << 4);
q->dw[1] = 0x3f800000;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((386 << 4)) | (((u64)(128 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// UV
q->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
q->dw[1] = 0x3f800000;
q++;
// XYZ2
q->dw[0] = (u64)(((512 << 4)) | (((u64)(256 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
}
q = draw_finish(q);
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
// Wait until the drawing is finished.
draw_wait_finish();
/* Flat shaded triangle, for testing
q = packet->data;
PACK_GIFTAG(q, GIF_SET_TAG(1, 1, GIF_PRE_ENABLE, GIF_PRIM_TRIANGLE, GIF_FLG_PACKED, 5),
GIF_REG_AD | (GIF_REG_RGBAQ << 4) | (GIF_REG_XYZ2 << 8) | (GIF_REG_XYZ2 << 12) | (GIF_REG_XYZ2 << 16));
q++;
// TEST1
q->dw[0] = GS_SET_TEST(0, 0, 0, 0, 0, 0, 1, 1);
q->dw[1] = GS_REG_TEST;
q++;
// RGBAQ (Q will default to 1.0f on new tag)
q->dw[0] = (u64)((0) | ((u64)0xcc << 32));
q->dw[1] = (u64)((0xcc) | ((u64)0xFF << 32));
q++;
// XYZ2
q->dw[0] = (u64)((((200 << 4)) | (((u64)(100 << 4)) << 32)));
q->dw[1] = (u64)(0x1000);
q++;
// XYZ2
q->dw[0] = (u64)(((100 << 4)) | (((u64)(200 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
// XYZ2
q->dw[0] = (u64)(((200 << 4)) | (((u64)(200 << 4)) << 32));
q->dw[1] = (u64)(0x1000);
q++;
q = draw_finish(q);
dma_channel_send_normal(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
// Wait until the drawing is finished.
draw_wait_finish();
*/
// Now initiate vsync.
graph_wait_vsync();
}
download_from_gs(fb.address, GS_PSM_24, "framebuffer.raw", 24, WIDTH, HEIGHT);
SleepThread();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment