Skip to content

Instantly share code, notes, and snippets.

@F0bes
Created March 12, 2022 05:53
Show Gist options
  • Save F0bes/70b2e8c7fc508e914121b257678f99fe to your computer and use it in GitHub Desktop.
Save F0bes/70b2e8c7fc508e914121b257678f99fe 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 <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 ((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 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 texAddress32 = graph_vram_allocate(32, 32, GS_PSM_4, GRAPH_ALIGN_BLOCK);
int texAddress16 = texAddress32 + 0x80;
int texAddress8 = texAddress16 + 0x40;
int texAddress4 =texAddress8 + 0x40;
printf("%x,%x,%x,%x\n", texAddress32, texAddress16, texAddress8, texAddress4);
q = draw_texture_transfer(q, (void *)tex4_1, 32, 32, GS_PSM_4, texAddress32, 64);
q = draw_texture_transfer(q, (void *)tex4_2, 16, 16, GS_PSM_4, texAddress16, 64);
q = draw_texture_transfer(q, (void *)tex4_3, 8, 8, GS_PSM_4, texAddress8, 64);
q = draw_texture_transfer(q, (void *)tex4_4, 4, 8, GS_PSM_4, texAddress4, 64);
//q = draw_texture_transfer(q, (void *)tex4_4, 4, 4, GS_PSM_4, texAddress32, 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;
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(texAddress16 / 64, 1, texAddress8 / 64, 1, texAddress4 / 64, 1); // MXL 3
q->dw[1] = GS_REG_NOP;
q++;
q->dw[0] = GS_SET_TEX0(texAddress32 / 64, 1, GS_PSM_4, 5, 5, 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 % 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_32, "framebuffer.raw", 32, WIDTH, HEIGHT);
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