add on-screen frame-budget usage, rework graphics

* enable anti-aliasing

* increase teapot resolution

* rework teapot display list offset to 0 for convenience

* add font for frame-budget and debug text

* add on-screen ascii text to cache test to get a feel for fonts

* reduce cache test resolution to VI-padded 576x432

* rework other rendering settings (maybe no real difference)

* tweak task pushing (maybe no real difference)
This commit is contained in:
Connor Olding 2018-10-23 16:29:25 +02:00
parent fab37799e2
commit 2dda303281
13 changed files with 374 additions and 158 deletions

View File

@ -44,8 +44,8 @@ constant MAIN_FROM(0x0000)
constant MAIN_TO(0x0080)
constant MAIN_FONT(0x4000)
constant WIDTH(640)
constant HEIGHT(480)
constant WIDTH(576) // 640 * 0.9
constant HEIGHT(432) // 480 * 0.9
constant DEPTH(2)
constant VIDEO_BUFFER(0x80400000 - WIDTH * HEIGHT * DEPTH)
constant VIDEO_MODE(BPP16 | INTERLACE | AA_MODE_2 | DIVOT_EN | PIXEL_ADV_3 | DITHER_FILTER_EN)
@ -89,7 +89,7 @@ Start:
li t1, 0xDEADBEEF
li t2, 0xCAFEBABE
li t3, 0xABAD1DEA
li t4, 0x12345678
li t4, 0xADD0BEE5
lui a0, MAIN_BASE
// spaced out a bit just to see what happens.
@ -137,8 +137,8 @@ if 0 {
ori a0, MAIN_FONT
// show our results on-screen.
lli s0, 64 // s0: X
lli s1, 48 // s1: Y
lli s0, 16 // s0: X
lli s1, 12 // s1: Y
lli s2, 0x20 / 4 // s2: number of words to draw
lui s3, MAIN_BASE
ori s3, MAIN_TO // s3: start of data to dump
@ -148,12 +148,12 @@ MainHexDumpLoop:
lw s4, 0(s3) // s4: current word being drawn
addiu s0, 8 * 8
addiu s0, 8 * FONT_WIDTH
lli s5, 8 // s5: inner loop iteration count
MainHexDumpInnerLoop:
andi t0, s4, 0x0F
subiu s0, 8
subiu s0, FONT_WIDTH
lui a0, MAIN_BASE
ori a0, MAIN_FONT
@ -169,10 +169,40 @@ MainHexDumpInnerLoop:
srl s4, 4
subiu s2, 1
addiu s1, 12
addiu s1, FONT_HEIGHT
bnez s2, MainHexDumpLoop
addiu s3, 4
la s3, TEXT
DrawTextLoop:
lbu a1, 0(s3)
addiu s3, 1
beqz a1, DrawTextDone
lli t0, 0x0D // delay slot
beq a1, t0, DrawTextLoop
lli t1, 0x0A // delay slot
bne a1, t1,+
nop
addiu s1, FONT_HEIGHT // next line
b DrawTextLoop
lli s0, 16 // return to base X offset
+
lui a0, MAIN_BASE // delay slot
ori a0, MAIN_FONT
sll a2, s1, 16
or a2, s0
la a3, VIDEO_BUFFER
jal DrawChar16
addiu s0, FONT_WIDTH // delay slot
b DrawTextLoop
nop
DrawTextDone:
// use our old cache-poking utility for now.
jal PokeDataCache
nop
@ -180,50 +210,57 @@ MainHexDumpInnerLoop:
lui a0, VI_BASE
li t1, VIDEO_MODE
li t2, VIDEO_BUFFER & ADDR_MASK
li t3, 640 // width in pixels (for the buffer)
li t4, 0 // interrupt on line
li t3, WIDTH // width of the buffer in pixels
li t4, 0 // interrupt on line, 0 to disable (i think?)
li t5, 0 // current line; any write clears VI interrupt
li t6, 0x03E52239 // timings (split into 4)
li t7, 525 - 1 // lines. subtracting by one enables interlacing.
sw t1, 4 * 0(a0)
sw t2, 4 * 1(a0)
sw t3, 4 * 2(a0)
sw t4, 4 * 3(a0)
sw t5, 4 * 4(a0)
sw t6, 4 * 5(a0)
sw t7, 4 * 6(a0)
li t7, 525 - 1 // lines; subtracting by one enables interlacing
sw t1, VI_STATUS(a0) // offset 0x00
sw t2, VI_ORIGIN(a0) // offset 0x04
sw t3, VI_WIDTH(a0) // offset 0x08
sw t4, VI_V_INTR(a0) // offset 0x0C
sw t5, VI_V_CURRENT_LINE(a0) // offset 0x10
sw t6, VI_TIMING(a0) // offset 0x14
sw t7, VI_V_SYNC(a0) // offset 0x18
li t1, 0x00000C15 // divide VI clock to get proper NTSC rate
li t2, 0x0C150C15 // likewise (this is only different on PAL)
li t3, 0x006C02EC // 640 pixels per row, starting at 108 units
li t4, 0x00230203 // 480 pixels per column, starting at 35 units
li t3, 0x008C02CC // 576 pixels per row, starting at ... units
li t4, 0x003B01EB // 432 pixels per column, starting at ... units
li t5, 0x000E0204 // video burst starts at 14 and lasts for 502 units
li t6, 0x00000400 // x offset and x step size (inverse scaling)
li t7, 0x00000800 // y offset and y step size (inverse scaling)
sw t1, 4 * 7(a0)
sw t2, 4 * 8(a0)
sw t3, 4 * 9(a0)
sw t4, 4 * 10(a0)
sw t5, 4 * 11(a0)
sw t6, 4 * 12(a0)
sw t7, 4 * 13(a0)
li t7, 0x02000800 // y offset and y step size (inverse scaling)
// setting y offset to 0.5 (it's Q10 fixed point)
// reduces interlacing jitter at the cost of a little image sharpness.
sw t1, VI_H_SYNC(a0) // offset 0x1C
sw t2, VI_H_SYNC_LEAP(a0) // offset 0x20
sw t3, VI_H_VIDEO(a0) // offset 0x24
sw t4, VI_V_VIDEO(a0) // offset 0x28
sw t5, VI_V_BURST(a0) // offset 0x2C
sw t6, VI_X_SCALE(a0) // offset 0x30
sw t7, VI_Y_SCALE(a0) // offset 0x34
VideoLoop:
lui a0, VI_BASE
li t1, VIDEO_BUFFER & ADDR_MASK
-
// wait until we're done displaying the frame.
lw t0, VI_V_CURRENT_LINE(a0)
sltiu at, t0, 2 + 1
beqz at,-
nop
andi t0, 1
bnez t0,+
andi t0, 1 // check if we're on an odd field.
li t2, 0x003B01EB
bnez t0,+ // if we're not, branch.
nop
addiu t1, WIDTH * DEPTH
addiu t1, WIDTH * DEPTH // odd field, so offset the image by one row.
li t2, 0x003B01E9 // slightly shorter image so that
// the y offset doesn't cause sampling out of bounds
+
sw t1, VI_ORIGIN(a0)
sw t2, VI_V_VIDEO(a0)
j VideoLoop
nop
@ -250,4 +287,9 @@ PokeDataCache:
jr ra
nop
include "font.asm"
align(16)
insert TEXT, "text.txt"
db 0
align(4)
include "font.8x16.asm"

View File

@ -174,14 +174,25 @@ if HIRES {
gMatrix(view_mat1, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION)
gPipeSync()
gSetCombine(15,15,31,4,7,7,7,4, 15,15,31,4,7,7,7,4)
gSetOtherMode(G_PM_NPRIMITIVE | G_CYC_1CYCLE | G_TP_NONE | G_TD_CLAMP | G_TL_TILE | G_TT_NONE | G_TF_AVERAGE | G_TC_FILT | G_CK_NONE | G_CD_MAGICSQ | G_AD_PATTERN, G_AC_NONE | G_ZS_PIXEL | Z_CMP | Z_UPD)
gSetCombine(0,0,0,4,0,0,0,4, 0,0,0,4,0,0,0,4)
variable upper(G_PM_NPRIMITIVE | G_CYC_1CYCLE | G_TP_NONE | G_TD_CLAMP | G_TL_TILE | G_TT_NONE | G_TF_AVERAGE | G_TC_FILT | G_CK_NONE | G_CD_MAGICSQ | G_AD_PATTERN)
variable lower(AA_EN | Z_CMP | Z_UPD | IM_RD | CVG_DST_CLAMP | ZMODE_OPA | ALPHA_CVG_SEL | G_BL_CLR_IN << 30 | G_BL_A_IN << 26 | G_BL_CLR_MEM << 22 | G_BL_A_MEM << 18)
gSetOtherMode(upper, lower)
gGeometryMode(0, G_ZBUFFER | G_SHADE | G_CULL_FRONT | G_SHADING_SMOOTH)
gSetSegment6(model)
gMatrix(model_mat, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW)
gDisplayList((6 << 24) | MODEL_START)
if 0 {
// debug: display coverage values onscreen.
gPipeSync()
gSetOtherMode(G_CYC_1CYCLE, G_ZS_PRIM | IM_RD | FORCE_BL | G_BL_CLR_IN << 30 | G_BL_0 << 26 | G_BL_CLR_BL << 22 | G_BL_A_MEM << 18)
gSetBlendColor(0xFF,0xFF,0xFF,0xFF)
gSetPrimDepth(0xFFFF, 0xFFFF)
gFillRect(0, 0, WIDTH - 1, HEIGHT - 1)
}
// finish.
gFullSync()
gEndList()
@ -204,8 +215,8 @@ align(8)
viewport:
// note that the third parameters here affect the range of Z-buffering.
dh WIDTH/2*4, HEIGHT/2*4, 0x3FF, 0 // scale
dh WIDTH/2*4, HEIGHT/2*4, 0x000, 0 // translation
dh WIDTH/2*4, HEIGHT/2*4, 0x1FF, 0 // scale
dh WIDTH/2*4, HEIGHT/2*4, 0x1FF, 0 // translation
view_mat0:
if FOV90 {
@ -215,10 +226,10 @@ if FOV90 {
Mat.X($0001'4C8D, $0000'0000, $0000'0000, $0000'0000)
Mat.Y($0000'0000, $0001'BB67, $0000'0000, $0000'0000)
}
Mat.Z($0000'0000, $0000'0000, $FFFE'FF00, $FFFF'0000)
Mat.W($0000'0000, $0000'0000, $FFFD'FF00, $0000'0000)
Mat.Z($0000'0000, $0000'0000, $FFFE'FF9A, $FFFF'0000)
Mat.W($0000'0000, $0000'0000, $FFEB'FC00, $0000'0000)
Mat.rix()
constant PERSPECTIVE_NORMALIZATION($00FF)
constant PERSPECTIVE_NORMALIZATION($000A)
view_mat1:
Mat.X($0001'0000, $0000'0000, $0000'0000, $0000'0000)
@ -265,6 +276,6 @@ constant MODEL_START(pc() - model)
gQuadTri(2, 3, 7, 6)
gEndList()
} else {
constant MODEL_START(0x32B0)
constant MODEL_START(0)
insert model, "res/teapot.F3D"
}

144
font.8x16.asm Normal file
View File

@ -0,0 +1,144 @@
constant FONT_WIDTH(8)
constant FONT_HEIGHT(16)
constant FONT_SIZE16(FONT_WIDTH * FONT_HEIGHT * 2 * 95) // 0x5F00
LoadFont16:
// loads a 95-character, 8x16 font
// as an RGB5A1 (16-bpp) image to the specified address.
// a0: address to load font to (size: 0x5F00)
li t9, FONT_SIZE16
addu a1, a0, t9 // a1: end of output (exclusive)
la a2, FONT // a2: start of input
la a3, FONT + FONT.size // a3: end of input (exclusive)
LoadFont16Loop:
lhu t9, 0(a2)
addiu a2, 2
srl t1, t9, 12
srl t2, t9, 8
srl t3, t9, 4
andi t4, t9, 0x0F
andi t2, 0x0F
andi t3, 0x0F
if 0 {
sll t1, 2
sll t2, 2
sll t3, 2
sll t4, 2
} else {
// copy lsb to get the full 5-bit range of values.
sll t5, t1, 1
sll t6, t2, 1
sll t7, t3, 1
sll t8, t4, 1
andi t1, 1
andi t2, 1
andi t3, 1
andi t4, 1
or t1, t5
or t2, t6
or t3, t7
or t4, t8
sll t1, 1
sll t2, 1
sll t3, 1
sll t4, 1
}
sll t5, t1, 5
sll t6, t2, 5
sll t7, t3, 5
sll t8, t4, 5
or t1, t5
or t2, t6
or t3, t7
or t4, t8
sll t5, t1, 5
sll t6, t2, 5
sll t7, t3, 5
sll t8, t4, 5
or t1, t5
or t2, t6
or t3, t7
or t4, t8
ori t1, 1
ori t2, 1
ori t3, 1
ori t4, 1
sh t1, 0x0(a0)
sh t2, 0x2(a0)
sh t3, 0x4(a0)
sh t4, 0x6(a0)
bne a2, a3, LoadFont16Loop
addiu a0, 0x8
jr ra
nop
DrawChar16:
// draws a 16-bpp character on-screen at the specified coordinates.
// a0: font data address (same argument as LoadFont16)
// a1: character (range: 32 to 126 inclusive)
// a2: X, Y coordinate in pixels: X | Y << 16
// a3: output image address
// exit early if character is outside of valid range.
subiu a1, 0x20
bltz a1, DrawCharDone
sltiu at, a1, 0x80 - 0x20
beqz at, DrawCharDone
lli t9, FONT_WIDTH * FONT_HEIGHT * 2 // delay slot
multu a1, t9
mflo t9
addu a0, t9 // a0: character data address
andi a1, a2, 0xFFFF // a1: X
srl a2, 16 // a2: Y
sll t0, a1, 1
lli t9, WIDTH * 2
multu a2, t9
mflo t9
addu a3, t0 // offset output by X
addu a3, t9 // offset output by Y
lli t9, FONT_HEIGHT // t9: rows remaining
DrawChar16Loop:
// character width hardcoded for 8.
lhu t1, 0x0(a0)
lhu t2, 0x2(a0)
lhu t3, 0x4(a0)
lhu t4, 0x6(a0)
lhu t5, 0x8(a0)
lhu t6, 0xA(a0)
lhu t7, 0xC(a0)
lhu t8, 0xE(a0)
sh t1, 0x0(a3)
sh t2, 0x2(a3)
sh t3, 0x4(a3)
sh t4, 0x6(a3)
sh t5, 0x8(a3)
sh t6, 0xA(a3)
sh t7, 0xC(a3)
sh t8, 0xE(a3)
addiu a0, 0x10
subiu t9, 1
bnez t9, DrawChar16Loop
addiu a3, WIDTH * 2
DrawCharDone:
jr ra
nop
insert FONT, "res/fonts/NotoSansMono-SemiCondensedMedium.16.i4"

103
font.asm
View File

@ -1,103 +0,0 @@
constant FONT_SIZE16(8 * 12 * 2 * 256) // 0xC000
LoadFont16:
// loads a 256-character, 8x12 font
// as an RGB5A1 (16-bpp) image to the specified address.
// a0: address to load font to (size: 0xC000)
li t9, FONT_SIZE16
addu a1, a0, t9 // a1: end of output (exclusive)
la a2, FONT // a2: start of input
la a3, FONT + FONT.size // a3: end of input (exclusive)
LoadFont16Loop:
lbu t9, 0(a2)
addiu a2, 1
// sign-extend every pixel to get our blacks and whites.
sll t1, t9, 24
sll t2, t9, 25
sll t3, t9, 26
sll t4, t9, 27
sll t5, t9, 28
sll t6, t9, 29
sll t7, t9, 30
sll t8, t9, 31
//
sra t1, 31
sra t2, 31
sra t3, 31
sra t4, 31
sra t5, 31
sra t6, 31
sra t7, 31
sra t8, 31
sh t1, 0x0(a0)
sh t2, 0x2(a0)
sh t3, 0x4(a0)
sh t4, 0x6(a0)
sh t5, 0x8(a0)
sh t6, 0xA(a0)
sh t7, 0xC(a0)
sh t8, 0xE(a0)
bne a2, a3, LoadFont16Loop
addiu a0, 0x10
jr ra
nop
DrawChar16:
// draws a 16-bpp character on-screen at the specified coordinates.
// a0: font data address (same argument as LoadFont16)
// a1: character (range: 0 to 255 inclusive)
// a2: X, Y coordinate in pixels: X | Y << 16
// a3: output image address
lli t9, 8 * 12 * 2
multu a1, t9
mflo t9
addu a0, t9 // a0: character data address
andi a1, a2, 0xFFFF // a1: X
srl a2, 16 // a2: Y
sll t0, a1, 1
lli t9, WIDTH * 2
multu a2, t9
mflo t9
addu a3, t0 // offset output by X
addu a3, t9 // offset output by Y
lli t9, 12 // t9: rows remaining (character height)
DrawChar16Loop:
// character width hardcoded for 8.
lhu t1, 0x0(a0)
lhu t2, 0x2(a0)
lhu t3, 0x4(a0)
lhu t4, 0x6(a0)
lhu t5, 0x8(a0)
lhu t6, 0xA(a0)
lhu t7, 0xC(a0)
lhu t8, 0xE(a0)
sh t1, 0x0(a3)
sh t2, 0x2(a3)
sh t3, 0x4(a3)
sh t4, 0x6(a3)
sh t5, 0x8(a3)
sh t6, 0xA(a3)
sh t7, 0xC(a3)
sh t8, 0xE(a3)
addiu a0, 0x10
subiu t9, 1
bnez t9, DrawChar16Loop
addiu a3, WIDTH * 2
jr ra
nop
align(16); insert FONT, "res/dwarf.1bpp"

View File

@ -159,16 +159,29 @@ constant CVG_DST_WRAP(0x100)
constant CVG_DST_FULL(0x200)
constant CVG_DST_SAVE(0x300)
// more Z stuff
constant ZMODE_OPA(0)
constant ZMODE_INTER(0x400)
constant ZMODE_XLU(0x800)
constant ZMODE_DEC(0xC00)
constant ZMODE_OPA(0) // opaque
constant ZMODE_INTER(0x400) // interpenetrating
constant ZMODE_XLU(0x800) // translucent
constant ZMODE_DEC(0xC00) // decal
// more coverage stuff
constant CVG_X_ALPHA(0x1000)
constant ALPHA_CVG_SEL(0x2000)
// blending
constant FORCE_BL(0x4000) // no effect?
// blending modes
constant G_BL_CLR_IN(0)
constant G_BL_CLR_MEM(1)
constant G_BL_CLR_BL(2)
constant G_BL_CLR_FOG(3)
constant G_BL_1MA(0)
constant G_BL_A_MEM(1)
constant G_BL_A_IN(0)
constant G_BL_A_FOG(1)
constant G_BL_A_SHADE(2)
constant G_BL_1(2)
constant G_BL_0(3)
macro gNoOp() {
// stalls the RDP (and not the RSP?)
_g(0x00, 0, 0)
@ -489,7 +502,7 @@ macro gSetPrimDepth(variable z, variable dz) {
// fixes the Z value to a constant for the following primitives.
// useful for 2.5D effects, maybe?
// TODO: what are the ranges?
_g(0xEE, 0, (z << 16) | d)
_g(0xEE, 0, (z << 16) | dz)
}
macro gRdpSetOtherMode(variable omodeH, variable omodeL) {

View File

@ -5,7 +5,7 @@ constant HICOLOR(0)
constant MAIN_DECOMP_IMAGE(HIRES & HICOLOR)
constant MAIN_BASE(0x800E)
constant MAIN_BASE(0x8004)
constant MAIN_COUNTS(0x0010)
constant MAIN_SP_TASK(0x0040)
constant MAIN_XXD(0x0080)
@ -13,6 +13,8 @@ constant MAIN_DLIST(0x1000)
constant MAIN_DLIST_SIZE(0xF000)
constant MAIN_DLIST_JUMPER(MAIN_DLIST - 0xA8)
constant FONT_BASE(0x8005)
if HIRES {
constant WIDTH(640)
constant HEIGHT(480)
@ -21,6 +23,12 @@ if HIRES {
constant HEIGHT(240)
}
if HICOLOR {
constant DEPTH(4)
} else {
constant DEPTH(2)
}
if HIRES {
if HICOLOR {
// 640x480, 32-bit
@ -44,7 +52,7 @@ constant TASK_DP_WAIT(0x0002)
constant TASK_LOADABLE(0x0004)
constant TASK_SP_ONLY(0x0008)
constant VIDEO_C_IMAGE_SIZE(WIDTH * HEIGHT * (HICOLOR * 2 + 2))
constant VIDEO_C_IMAGE_SIZE(WIDTH * HEIGHT * DEPTH)
constant VIDEO_Z_IMAGE_SIZE(WIDTH * HEIGHT * 2)
constant VIDEO_OUTPUT_SIZE(0x18000) // technically a buffer?
constant VIDEO_STACK_SIZE(0x8000) // used for dlist calls, pushing matrices, etc?

View File

@ -15,6 +15,11 @@ include "n64_si.inc"
include "n64_pif.inc"
include "n64_util.inc"
// Rates
constant CLOCK_RATE(93750000)
constant COUNT_RATE(CLOCK_RATE / 2) // for use with the CP0 Count register.
constant COP_RATE(CLOCK_RATE * 2 / 3)
// Memory Map
constant RDRAM_BASE($A3F0) // $03F00000 RDRAM Base
constant RDRAM_DEVICE_TYPE($00) // $03F00000 Device Type

View File

@ -408,7 +408,6 @@ K_MI_AI:
andi s0, ~MI_INTR_AI
K_MI_VI:
lw a0, KV_RES(k0)
lw a1, KV_MODE(k0)
jal SetScreenNTSC

View File

@ -23,9 +23,13 @@ include "kernel.asm"
Main:
lui s0, MAIN_BASE
jal LoadFont16
lui a0, FONT_BASE
if MAIN_DECOMP_IMAGE {
DecompImage:
lui s0, MAIN_BASE
nop; nop; nop; nop
mfc0 t0, CP0_Count
@ -72,8 +76,7 @@ Start3D:
mfc0 t0, CP0_Status
mtc0 t0, CP0_Status
lui a0, MAIN_BASE
ori a0, MAIN_DLIST
ori a0, s0, MAIN_DLIST
jal WriteDList
or a1, s1, r0
jal PokeDataCache
@ -91,9 +94,8 @@ Start3D:
// only the lowest 12 bits are used, so 00000000 is equivalent to 04001000.
sw r0, SP_PC(a0)
lui a0, MAIN_BASE
jal PushVideoTask
ori a0, MAIN_SP_TASK
ori a0, s0, MAIN_SP_TASK
jal LoadRSPBoot
nop
@ -106,6 +108,8 @@ Start3D:
EnableInt()
MainLoop:
mfc0 s2, CP0_Count
WriteString(S_SP_Wait)
-
mfc0 t0, CP0_Status
@ -117,6 +121,79 @@ MainLoop:
beqz t0,-
nop
mfc0 s3, CP0_Count
subu s3, s2
addiu s3, COUNT_RATE / (60 * 200) // for rounding
li t9, COUNT_RATE / (60 * 100)
divu s3, t9
mflo s2 // s2: frame budget spent in (integer) percent
// there are faster ways, but i'll prefer smaller codesize for now.
lli t9, 10
divu s2, t9
mfhi s3 // s3: (RTL) first digit
mflo t0
divu t0, t9
mfhi s4 // s4: (RTL) second digit
mflo t0
divu t0, t9
mfhi s5 // s5: (RTL) third digit
if !HICOLOR {
if HIRES {
lli s6, 64 // s6: X position
lli s7, 48 // s7: Y position
} else {
lli s6, 32 // s6: X position
lli s7, 24 // s7: Y position
}
la s8, VIDEO_C_IMAGE // s8: output image buffer
beqz s1,+
nop
la s8, VIDEO_C_IMAGE_ALT
+
beqz s5,+
lui a0, FONT_BASE
addiu a1, s5, '0'
sll a2, s7, 16
or a2, s6
move a3, s8
jal DrawChar16
+
addiu s6, FONT_WIDTH
or at, s5, s6
beqz at,+
lui a0, FONT_BASE
addiu a1, s4, '0'
sll a2, s7, 16
or a2, s6
move a3, s8
jal DrawChar16
+
addiu s6, FONT_WIDTH
lui a0, FONT_BASE
addiu a1, s3, '0'
sll a2, s7, 16
or a2, s6
move a3, s8
jal DrawChar16
addiu s6, FONT_WIDTH
lui a0, FONT_BASE
addiu a1, r0, '%'
sll a2, s7, 16
or a2, s6
move a3, s8
jal DrawChar16
addiu s6, FONT_WIDTH
}
// queue buffers to swap
lui a0, K_BASE
beqz s1, SwapToMain
@ -197,6 +274,7 @@ if MAIN_DECOMP_IMAGE {
}
include "dlist.asm"
include "task.asm"
include "font.8x16.asm"
if pc() > (MAIN_BASE << 16) {
error "ran out of memory for code and data"

Binary file not shown.

Binary file not shown.

View File

@ -5,10 +5,15 @@ PushVideoTask:
lli t0, 1 // mode: video
lli t1, TASK_DP_WAIT // flags
li t2, UCODE_BOOT // does not need masking (not actually used?)
li t2, UCODE_BOOT & ADDR_MASK // not actually used?
li t3, UCODE_BOOT.size
li t4, F3DZEX_IMEM & ADDR_MASK
constant IMEM_SIZE(F3DZEX_IMEM.size) // weird bass quirk
if IMEM_SIZE > 0xFC0 {
li t5, 0xFC0
} else {
li t5, F3DZEX_IMEM.size
}
li t6, F3DZEX_DMEM & ADDR_MASK
li t7, F3DZEX_DMEM.size
sw t0, 0x00(a0)
@ -25,7 +30,7 @@ PushVideoTask:
li t2, (VIDEO_OUTPUT & ADDR_MASK) | UNCACHED
// most commercial games re-use the yield pointer, so i assume it's fine:
li t3, VIDEO_YIELD & ADDR_MASK // stores output buffer size
li t4, ((MAIN_BASE << 16) | MAIN_DLIST_JUMPER) & ADDR_MASK // initial DList
li t4, ((MAIN_BASE << 16) | MAIN_DLIST_JUMPER) // initial DList
lli t5, 8 // size of one jump command. this is ignored and 0xA8 is used instead
li t6, VIDEO_YIELD & ADDR_MASK
li t7, VIDEO_YIELD_SIZE
@ -38,6 +43,8 @@ PushVideoTask:
sw t6, 0x38(a0)
sw t7, 0x3C(a0)
nop; nop; nop; nop
// tell data cache to write itself out
cache 0x19, 0x00(a0)
cache 0x19, 0x10(a0)

12
text.txt Normal file
View File

@ -0,0 +1,12 @@
Done with the battles he once
waged across time, he embarked
on a journey. A secret and
personal journey...
A journey in search of a
beloved and invaluable friend...
A friend with whom he parted
ways when he finally fulfilled his
heroic destiny and took his place
among legends...