Skip to content

Instantly share code, notes, and snippets.

@F0bes
Created March 13, 2022 01:45
Show Gist options
  • Save F0bes/4f62cc6ff224c2f4b9e6f4a732fa1be5 to your computer and use it in GitHub Desktop.
Save F0bes/4f62cc6ff224c2f4b9e6f4a732fa1be5 to your computer and use it in GitHub Desktop.
// 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 <string.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 "clut.c"
//#include "tex4_1.c"
//#include "tex4_2.c"
//#include "tex4_3.c"
//#include "tex4_4.c"
const u32 WIDTH = 640;
const u32 HEIGHT = 480;
const s32 FRAME_PSM = GS_PSM_32;
#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))
qword_t *draw_texture_transfer(qword_t *q, void *src, int width, int height, int psm, int dest, int dest_width, u32 dx, u32 dy);
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 (f == NULL)
{
printf("??? couldn't open file\n");
return 0;
}
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 clutAddress = graph_vram_allocate(16, 16, GS_PSM_32, GRAPH_ALIGN_BLOCK);
q = draw_texture_transfer(q, &clut[0], 16, 16, GS_PSM_32, clutAddress, 64);
q = draw_texture_flush(q);
dma_channel_send_chain(DMA_CHANNEL_GIF, packet->data, q - packet->data, 0, 0);
dma_wait_fast();
q = packet->data;
/*int texAddress32 = graph_vram_allocate(32, 32, GS_PSM_4, GRAPH_ALIGN_BLOCK);
int texAddress16 = graph_vram_allocate(16, 16, GS_PSM_4, GRAPH_ALIGN_BLOCK);
int texAddress8 = graph_vram_allocate(8, 8, GS_PSM_4, GRAPH_ALIGN_BLOCK);
int texAddress4 = graph_vram_allocate(4, 4, GS_PSM_4, GRAPH_ALIGN_BLOCK);*/
//int texAddress128 = graph_vram_allocate(128, 128, GS_PSM_8, GRAPH_ALIGN_BLOCK);
//int texAddress64 = graph_vram_allocate(64, 64, GS_PSM_8, GRAPH_ALIGN_BLOCK);
//int texAddress32 = graph_vram_allocate(32, 32, GS_PSM_8, GRAPH_ALIGN_BLOCK);
int texAddress128 = 0x96100;
int texAddress64 = 0x97100;
int texAddress32 = 0x97500;
int texAddress16 = 0x97600 ;
//int texAddress16 = graph_vram_allocate(16, 16, GS_PSM_8, GRAPH_ALIGN_BLOCK);
printf("%x,%x,%x,%x\n",texAddress128,texAddress64,texAddress32,texAddress16);
char tex8_1[128 * 128] ALIGNED(16);
char tex8_2[64 * 64] ALIGNED(16);
char tex8_3[32 * 32] ALIGNED(16);
char tex8_4[16 * 16] ALIGNED(16);
memset(tex8_1, 0x1, (128 * 128));
memset(tex8_2, 0x2, (64 * 64));
memset(tex8_3, 0x3, (32 * 32));
memset(tex8_4, 0x4, (16 * 16));
FlushCache(0);
q = draw_texture_transfer(q, (void *)tex8_1, 128, 128, GS_PSM_8, texAddress128, 128);
q = draw_texture_transfer(q, (void *)tex8_2, 64, 64, GS_PSM_8, texAddress64, 64);
q = draw_texture_transfer(q, (void *)tex8_3, 32, 32, GS_PSM_8, texAddress32, 64);
q = draw_texture_transfer(q, (void *)tex8_4, 16, 16, GS_PSM_8, texAddress16, 64);
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
*/
int frame = 0;
bool dumped = false;
while (1)
{
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, 3, 0, 2, 1, 0, 0); // MXL 0
q->dw[1] = GS_REG_TEX1;
q++;
q->dw[0] = GS_SET_MIPTBP1(texAddress64 / 64, 1, texAddress32 / 64, 1, texAddress16 / 64, 1);
q->dw[1] = GS_REG_NOP;
q++;
q->dw[0] = GS_SET_TEX0(texAddress128 / 64, 2, GS_PSM_8, 7, 7, 0, 1, clutAddress / 64, GS_PSM_32, 0, 0, 1);
q->dw[1] = GS_REG_TEX0;
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();
frame++;
if (frame == 100)
{
printf("100Frames\n");
frame = 0;
// 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();
if(!dumped)
{
download_from_gs(fb.address, GS_PSM_32, "framebuffer.raw", 32, WIDTH, HEIGHT);
dumped = true;
}
}
SleepThread();
}
qword_t *draw_texture_transfer(qword_t *q, void *src, int width, int height, int psm, int dest, int dest_width, u32 dx, u32 dy)
{
int i;
int remaining;
int qwords = 0;
switch (psm)
{
case GS_PSM_8:
{
qwords = (width * height) >> 4;
break;
}
case GS_PSM_32:
case GS_PSM_24:
{
qwords = (width * height) >> 2;
break;
}
case GS_PSM_4:
{
qwords = (width * height) >> 5;
break;
}
case GS_PSM_16:
case GS_PSM_16S:
{
qwords = (width * height) >> 3;
break;
}
default:
{
switch (psm)
{
case GS_PSM_8H:
{
qwords = (width * height) >> 4;
break;
}
case GS_PSMZ_32:
case GS_PSMZ_24:
{
qwords = (width * height) >> 2;
break;
}
case GS_PSMZ_16:
case GS_PSMZ_16S:
{
qwords = (width * height) >> 3;
break;
}
case GS_PSM_4HL:
case GS_PSM_4HH:
{
qwords = (width * height) >> 5;
break;
}
}
break;
}
}
// Determine number of iterations based on the number of qwords
// that can be handled per dmatag
i = qwords / GIF_BLOCK_SIZE;
// Now calculate the remaining image data left over
remaining = qwords % GIF_BLOCK_SIZE;
// Setup the transfer
DMATAG_CNT(q, 5, 0, 0, 0);
q++;
PACK_GIFTAG(q, GIF_SET_TAG(4, 0, 0, 0, GIF_FLG_PACKED, 1), GIF_REG_AD);
q++;
PACK_GIFTAG(q, GS_SET_BITBLTBUF(0, 0, 0, dest >> 6, dest_width >> 6, psm), GS_REG_BITBLTBUF);
q++;
PACK_GIFTAG(q, GS_SET_TRXPOS(0, 0, dx, dy, 0), GS_REG_TRXPOS);
q++;
PACK_GIFTAG(q, GS_SET_TRXREG(width, height), GS_REG_TRXREG);
q++;
PACK_GIFTAG(q, GS_SET_TRXDIR(0), GS_REG_TRXDIR);
q++;
while (i-- > 0)
{
// Setup image data dma chain
DMATAG_CNT(q, 1, 0, 0, 0);
q++;
PACK_GIFTAG(q, GIF_SET_TAG(GIF_BLOCK_SIZE, 0, 0, 0, 2, 0), 0);
q++;
DMATAG_REF(q, GIF_BLOCK_SIZE, (unsigned int)src, 0, 0, 0);
q++;
// Now increment the address by the number of qwords in bytes
src = (void *)src + (GIF_BLOCK_SIZE * 16);
}
if (remaining)
{
// Setup remaining image data dma chain
DMATAG_CNT(q, 1, 0, 0, 0);
q++;
PACK_GIFTAG(q, GIF_SET_TAG(remaining, 0, 0, 0, 2, 0), 0);
q++;
DMATAG_REF(q, remaining, (unsigned int)src, 0, 0, 0);
q++;
}
return q;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment