Skip to content

Commit

Permalink
feat(bongocat): add fancy graphic to play while dumping
Browse files Browse the repository at this point in the history
Uses VU1, every 5th VSYNC_S interrupt continues a VU1 microprogram that'll take care of drawing, incrementing, handling frames, etc. For your speedy dumping needs.
  • Loading branch information
F0bes committed Jul 29, 2022
1 parent 72b4e59 commit 4179930
Show file tree
Hide file tree
Showing 10 changed files with 262 additions and 20 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
.vscode/*

biosdrain_tex.c
*tex_*.c
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
EE_BIN ?= biosdrain.elf
EE_OBJS = biosdrain.o biosdrain_tex.o OSDInit.o sysman_rpc.o ui/menu.o dump.o modelname.o
EE_OBJS += ui/graphic.o ui/graphic_vu.o ui/tex/bongo_tex_1.o ui/tex/bongo_tex_2.o
IRX_OBJS = irx/usbmass_bd_irx.o irx/usbd_irx.o irx/bdm_irx.o irx/bdmfs_vfat_irx.o irx/sysman_irx.o
# Bin2c objects that will be linked in
EE_OBJS += $(IRX_OBJS)
EE_LIBS = -lkernel -lpatches -ldebug -lgraph -ldma -ldraw

EE_DVP = dvp-as

# Git version
GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)"

Expand Down Expand Up @@ -36,6 +39,15 @@ irx/bdmfs_vfat_irx.c: $(PS2SDK)/iop/irx/bdmfs_vfat.irx
biosdrain_tex.c: biosdrain_tex.tex
bin2c $< biosdrain_tex.c biosdrain_tex

ui/tex/bongo_tex_1.c: ui/tex/bongo_tex_1.tex
bin2c $< ui/tex/bongo_tex_1.c bongo_tex_1

ui/tex/bongo_tex_2.c: ui/tex/bongo_tex_2.tex
bin2c $< ui/tex/bongo_tex_2.c bongo_tex_2

%.o: %.vsm
$(EE_DVP) $< -o $@

clean:
$(MAKE) -C sysman clean
rm -f $(EE_BIN_RESET) $(EE_BIN_NORESET) $(EE_OBJS) $(IRX_C_FILES)
Expand Down
4 changes: 3 additions & 1 deletion biosdrain.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "dump.h"

#include <kernel.h>
#include <stdio.h>
#include <dirent.h> // mkdir()
#include <unistd.h> // rmdir()
#include <graph.h> // graph_wait_vsync()
Expand Down Expand Up @@ -188,8 +189,9 @@ void load_irx_sysman()
int main(void)
{
printf("main()\n");
menu_init();

graphic_init();
menu_init();
menu_logo_fadein();

menu_status("Determining target device.\n");
Expand Down
3 changes: 2 additions & 1 deletion dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

#include "ui/menu.h"

#include <libcdvd.h>
#include <kernel.h>
#include <libcdvd.h>
#include <stdlib.h>
#include <stdio.h>

#include "modelname.h"
#include "sysman/sysinfo.h" // t_SysmanHardwareInfo
Expand Down
165 changes: 165 additions & 0 deletions ui/graphic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include "menu.h"

#include <kernel.h>
#include <graph.h>
#include <draw.h>
#include <gif_tags.h>
#include <gif_registers.h>
#include <gs_gp.h>
#include <dma.h>
#include <stdio.h>
#include <stdlib.h> // aligned_alloc

extern u64 graphic_vu_start __attribute__((section(".vudata")));
extern u64 graphic_vu_end __attribute__((section(".vudata")));

// VIF stuff
#define VIFMPG(size, pos) ((0x4A000000) | (size << 16) | pos)
#define VIFFLUSHE 0x10000000
#define VIFFLUSH 0x11000000
#define VIFFLUSHA 0x13000000
#define VIFMSCAL(execaddr) (0x14000000 | execaddr)
#define VIFMSCNT 0x17000000
#define VIFFMSCALF(execaddr) (0x15000000 | execaddr)
#define VIF1CHCR (*(volatile u32 *)0x10009000)
#define VIF1MADR (*(volatile u32 *)0x10009010)
#define VIF1QWC (*(volatile u32 *)0x10009020)

// Texture stuff
extern unsigned int size_bongo_tex_1;
extern unsigned char bongo_tex_1[];

extern unsigned int size_bongo_tex_2;
extern unsigned char bongo_tex_2[];

u32 TEX1ADDR = 0xB0000;
u32 TEX2ADDR = 0xC0000;
void graphic_init_load_textures(void)
{

qword_t *texBuffer = (qword_t *)aligned_alloc(64, sizeof(qword_t) * 270);
qword_t *q = texBuffer;
q = draw_texture_transfer(q, &bongo_tex_1[0], 256, 256, 0, TEX1ADDR, 256);
q = draw_texture_flush(q);

dma_channel_send_chain(DMA_CHANNEL_GIF, texBuffer, q - texBuffer, 0, 0);
dma_channel_wait(DMA_CHANNEL_GIF, 0);

q = texBuffer;
q = draw_texture_transfer(q, &bongo_tex_2[0], 256, 256, 0, TEX2ADDR, 256);
q = draw_texture_flush(q);

dma_channel_send_chain(DMA_CHANNEL_GIF, texBuffer, q - texBuffer, 0, 0);
dma_channel_wait(DMA_CHANNEL_GIF, 0);

free(texBuffer);
}

void graphic_init(void)
{
graphic_init_load_textures();
u64 *VU1_DATA_PTR = (u64 *)0x1100C000;
VU1_DATA_PTR[0] = GS_SET_TEX0(TEX1ADDR / 64, 4, 0, 8, 8, 0, 1, 0, 0, 0, 0, 0); // Set texture #1 here
VU1_DATA_PTR[1] = GS_REG_TEX0; // Set texture #2 here

VU1_DATA_PTR[2] = GS_SET_TEX0(TEX2ADDR / 64, 4, 0, 8, 8, 0, 1, 0, 0, 0, 0, 0); // Set texture #1 here
VU1_DATA_PTR[3] = GS_REG_TEX0; // Set texture #2 here

// addr(2)
qword_t *VU1_QW = (qword_t *)&VU1_DATA_PTR[4];

PACK_GIFTAG(VU1_QW, GIF_SET_TAG(1, 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));
VU1_QW++;
// TEX0 (To be copied by VU1)
VU1_QW->dw[0] = 0xb000b;
VU1_QW->dw[1] = 0;
VU1_QW++;
// ST
VU1_QW->dw[0] = GIF_SET_ST(0, 0);
VU1_QW->dw[1] = 0x3f800000;
VU1_QW++;
// RGBAQ
VU1_QW->dw[0] = (u64)((0) | ((u64)0xFC << 32));
VU1_QW->dw[1] = (u64)((0xFE) | ((u64)0x1 << 32));
VU1_QW++;
// XYZ2
// DUE TO LACK OF Z BUFFER CURRENTLY, WE CANNOT HAVE THE CAT
// BONGOING THE LOGO. IT CAUSES Z FIGHTING LIKE ISSUES :(.
// WHEN WE HAVE A PROPER UI, THIS CAN BE FIXED :).
VU1_QW->dw[0] = (u64)((((400 << 4)) | (((u64)(45 << 4)) << 32)));
VU1_QW->dw[1] = (u64)(0);
VU1_QW++;
// ST
VU1_QW->dw[0] = GIF_SET_ST(0x3f800000, 0x3f800000);
VU1_QW->dw[1] = 0x3f800000;
VU1_QW++;
// XYZ2
VU1_QW->dw[0] = (u64)(((510 << 4)) | (((u64)(105 << 4)) << 32));
VU1_QW->dw[1] = (u64)(0);
VU1_QW++;

// addr(9)
FlushCache(0);

u64 microInstructioncnt = (&graphic_vu_end - &graphic_vu_start);
if (microInstructioncnt > 255)
{
printf("WARNING, THE MICRO PROGRAM IS > THAN 255 INSTRUCTIONS!\n");
}

u32 vif_packet[2000] __attribute__((aligned(64)));
u32 vif_index = 0;

// Wait for any possible micro programs
vif_packet[vif_index++] = VIFFLUSHE;

// Upload the micro program to address 0
vif_packet[vif_index++] = VIFMPG(microInstructioncnt, 0);

// Embed the micro program into the VIF packet
for (u32 instr = 0; instr < microInstructioncnt; instr++)
{
vif_packet[vif_index++] = (&graphic_vu_start)[instr];
vif_packet[vif_index++] = (&graphic_vu_start)[instr] >> 32;
}

// Execute the micro program at address 0
vif_packet[vif_index++] = VIFMSCAL(0);

while (vif_index % 4) // Align the packet
vif_packet[vif_index++] = 0x00; // VIFNOP

VIF1MADR = (u32)vif_packet;
VIF1QWC = vif_index / 4;

FlushCache(0);

VIF1CHCR = 0x101;

while (VIF1CHCR & 0x100)
{
};
}

void graphic_draw_fast(void)
{
// Reset the GIF every vsync? But it works so whatever...
// Could probably remove once the dependency on debug draw is gone.
// My suspicion is that scr_printf is causing the GIF to wait for PATH3?
(*(volatile u_int *)0x10003000) = 1;

asm volatile(
"vu1_active_%=:\n"
"bc2t vu1_active_%=\n"
"nop\n"
:);
// continue the micro program
asm volatile(
"li $t0, 0x43A\n"
"CTC2 $t0, $vi1\n"
"VILWR.x $vi2, ($vi1)\n"
"CFC2 $t0, $vi2\n"
"CTC2 $t0, $31\n" ::
: "$t0");
}
39 changes: 39 additions & 0 deletions ui/graphic_vu.vsm
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.vu
.align 4
.global graphic_vu_start
.global graphic_vu_end

# VI1 is the current tex0 index
graphic_vu_start:

# VI04 is where we xgkick
NOP IADDIU VI04, VI00, 2
# VI02 is the max texture frames (The point where VI01 resets)
NOP IADDI VI03, VI00, 2
# VI02 is where TEX0 is in our kicked GIF packet
NOP IADDI VI02, VI00, 3
# VI01 is used as an index
NOP IADDI VI01, VI01, 0

graphic_vu_cont:

# Copy our desired TEX0 to the one in our packet
NOP LQ.xyzw VF03, 0(VI01)
NOP SQ.xyzw VF03, 0(VI02)
# Increment out index
NOP IADDIU VI01, VI01, 1
NOP NOP
# Reset the index to 0 if we are beyond the last texture index
NOP IBNE VI01, VI03, index_dont_reset
NOP NOP
NOP IADDI VI01, VI00, 0
index_dont_reset:
# Kick off our packet
NOP xgkick VI04
NOP NOP
# Halt here, and wait for the EE to let us continue
NOP[e] NOP
NOP NOP
NOP B graphic_vu_cont
NOP NOP
graphic_vu_end:
53 changes: 37 additions & 16 deletions ui/menu.c
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
#include "config.h"
#include "menu.h"

#include <stdlib.h> // aligned_alloc
#include <stdarg.h>

#include <kernel.h>
#include <debug.h>
#include <graph.h>
#include <draw.h>
#include <dma.h>
#include <gs_gp.h>

#include <stdio.h>
#include <stdlib.h> // aligned_alloc
#include <stdarg.h>

// Simple menu system using debug, just for now

extern unsigned int size_biosdrain_tex;
extern unsigned char biosdrain_tex[];

// Unfix this and allocate properly when
// a proper menu is developed.
u32 g_logo_texaddress = 0x96000;
static u32 g_logo_texaddress = 0x96000;

qword_t g_draw_packet[10] __attribute__((aligned(64)));
static qword_t g_draw_packet[10] __attribute__((aligned(64)));

void menu_load_logo()
{
Expand All @@ -37,8 +39,8 @@ void menu_load_logo()
q = texBuffer;
// Set registers that only need to be set once
{
PACK_GIFTAG(q, GIF_SET_TAG(1, 1, GIF_PRE_DISABLE, 0, GIF_FLG_PACKED, 4),
GIF_REG_AD | (GIF_REG_AD << 4) | (GIF_REG_AD << 8) | (GIF_REG_TEX0 << 12));
PACK_GIFTAG(q, GIF_SET_TAG(1, 1, GIF_PRE_DISABLE, 0, GIF_FLG_PACKED, 3),
GIF_REG_AD | (GIF_REG_AD << 4) | (GIF_REG_AD << 8));
q++;
// ALPHA
q->dw[0] = GS_SET_ALPHA(0, 2, 0, 2, 0);
Expand All @@ -52,10 +54,6 @@ void menu_load_logo()
q->dw[0] = GS_SET_TEST(0, 0, 0, 0, 0, 0, 1, 1);
q->dw[1] = GS_REG_TEST;
q++;
// TEX0
q->dw[0] = GS_SET_TEX0(g_logo_texaddress / 64, 4, 0, 8, 8, 0, 1, 0, 0, 0, 0, 0);
q->dw[1] = GS_REG_TEX0;
q++;

dma_channel_send_normal(DMA_CHANNEL_GIF, texBuffer, q - texBuffer, 0, 0);
dma_channel_wait(DMA_CHANNEL_GIF, 0);
Expand All @@ -65,8 +63,12 @@ void menu_load_logo()
// Craft our packet to draw the logo
q = g_draw_packet;
{
PACK_GIFTAG(q, GIF_SET_TAG(1, 1, GIF_PRE_ENABLE, GS_SET_PRIM(GS_PRIM_SPRITE, 0, 1, 0, 1, 0, 1, 0, 0), GIF_FLG_PACKED, 5),
(GIF_REG_RGBAQ) | (GIF_REG_UV << 4) | (GIF_REG_XYZ2 << 8) | (GIF_REG_UV << 12) | (GIF_REG_XYZ2 << 16));
PACK_GIFTAG(q, GIF_SET_TAG(1, 1, GIF_PRE_ENABLE, GS_SET_PRIM(GS_PRIM_SPRITE, 0, 1, 0, 1, 0, 1, 0, 0), GIF_FLG_PACKED, 6),
(GIF_REG_AD) | (GIF_REG_RGBAQ << 4) | (GIF_REG_UV << 8) | (GIF_REG_XYZ2 << 12) | (GIF_REG_UV << 16) | (GIF_REG_XYZ2 << 20));
q++;
// TEX0
q->dw[0] = GS_SET_TEX0(g_logo_texaddress / 64, 4, 0, 8, 8, 0, 1, 0, 0, 0, 0, 0);
q->dw[1] = GS_REG_TEX0;
q++;
// RGBAQ
q->dw[0] = (u64)((0xFF) | ((u64)0xFF << 32));
Expand All @@ -93,14 +95,14 @@ void menu_load_logo()

void menu_logo_draw()
{
dma_channel_send_normal(DMA_CHANNEL_GIF, g_draw_packet, 7, 0, 0);
dma_channel_send_normal(DMA_CHANNEL_GIF, g_draw_packet, 8, 0, 0);
dma_channel_wait(DMA_CHANNEL_GIF, 0);
}

void menu_logo_alpha(u16 alpha)
{
g_draw_packet[1].dw[0] = (u64)((0xFF) | ((u64)0xFF << 32));
g_draw_packet[1].dw[1] = (u64)((0xFF) | ((u64)alpha << 32));
g_draw_packet[2].dw[0] = (u64)((0xFF) | ((u64)0xFF << 32));
g_draw_packet[2].dw[1] = (u64)((0xFF) | ((u64)alpha << 32));
menu_logo_draw();
}

Expand All @@ -115,6 +117,18 @@ void menu_logo_fadein()
}
}

static const s32 graphic_vsync_max = 5;
static s32 graphic_vsync_current = 0;
static void intc_vsync_handler(s32 alarm_id, u16 time, void *common)
{
if(graphic_vsync_current++ == graphic_vsync_max)
{
graphic_vsync_current = 0;
graphic_draw_fast();
}
ExitHandler();
}

void menu_init(void)
{
init_scr();
Expand All @@ -128,6 +142,13 @@ void menu_init(void)
scr_setXY(0, 1);

scr_printf("BiosDrain Starting. rev %s\n", GIT_VERSION);

DIntr();
AddIntcHandler(INTC_VBLANK_S, (void*)intc_vsync_handler, 0);
EnableIntc(INTC_VBLANK_S);
EIntr();

graphic_init();
}

void menu_status(const char *fmt, ...)
Expand Down
Loading

0 comments on commit 4179930

Please sign in to comment.