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:
parent
fab37799e2
commit
2dda303281
13 changed files with 374 additions and 158 deletions
106
cachetest.asm
106
cachetest.asm
|
@ -44,8 +44,8 @@ constant MAIN_FROM(0x0000)
|
||||||
constant MAIN_TO(0x0080)
|
constant MAIN_TO(0x0080)
|
||||||
constant MAIN_FONT(0x4000)
|
constant MAIN_FONT(0x4000)
|
||||||
|
|
||||||
constant WIDTH(640)
|
constant WIDTH(576) // 640 * 0.9
|
||||||
constant HEIGHT(480)
|
constant HEIGHT(432) // 480 * 0.9
|
||||||
constant DEPTH(2)
|
constant DEPTH(2)
|
||||||
constant VIDEO_BUFFER(0x80400000 - WIDTH * HEIGHT * DEPTH)
|
constant VIDEO_BUFFER(0x80400000 - WIDTH * HEIGHT * DEPTH)
|
||||||
constant VIDEO_MODE(BPP16 | INTERLACE | AA_MODE_2 | DIVOT_EN | PIXEL_ADV_3 | DITHER_FILTER_EN)
|
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 t1, 0xDEADBEEF
|
||||||
li t2, 0xCAFEBABE
|
li t2, 0xCAFEBABE
|
||||||
li t3, 0xABAD1DEA
|
li t3, 0xABAD1DEA
|
||||||
li t4, 0x12345678
|
li t4, 0xADD0BEE5
|
||||||
|
|
||||||
lui a0, MAIN_BASE
|
lui a0, MAIN_BASE
|
||||||
// spaced out a bit just to see what happens.
|
// spaced out a bit just to see what happens.
|
||||||
|
@ -137,8 +137,8 @@ if 0 {
|
||||||
ori a0, MAIN_FONT
|
ori a0, MAIN_FONT
|
||||||
|
|
||||||
// show our results on-screen.
|
// show our results on-screen.
|
||||||
lli s0, 64 // s0: X
|
lli s0, 16 // s0: X
|
||||||
lli s1, 48 // s1: Y
|
lli s1, 12 // s1: Y
|
||||||
lli s2, 0x20 / 4 // s2: number of words to draw
|
lli s2, 0x20 / 4 // s2: number of words to draw
|
||||||
lui s3, MAIN_BASE
|
lui s3, MAIN_BASE
|
||||||
ori s3, MAIN_TO // s3: start of data to dump
|
ori s3, MAIN_TO // s3: start of data to dump
|
||||||
|
@ -148,12 +148,12 @@ MainHexDumpLoop:
|
||||||
|
|
||||||
lw s4, 0(s3) // s4: current word being drawn
|
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
|
lli s5, 8 // s5: inner loop iteration count
|
||||||
|
|
||||||
MainHexDumpInnerLoop:
|
MainHexDumpInnerLoop:
|
||||||
andi t0, s4, 0x0F
|
andi t0, s4, 0x0F
|
||||||
subiu s0, 8
|
subiu s0, FONT_WIDTH
|
||||||
|
|
||||||
lui a0, MAIN_BASE
|
lui a0, MAIN_BASE
|
||||||
ori a0, MAIN_FONT
|
ori a0, MAIN_FONT
|
||||||
|
@ -169,10 +169,40 @@ MainHexDumpInnerLoop:
|
||||||
srl s4, 4
|
srl s4, 4
|
||||||
|
|
||||||
subiu s2, 1
|
subiu s2, 1
|
||||||
addiu s1, 12
|
addiu s1, FONT_HEIGHT
|
||||||
bnez s2, MainHexDumpLoop
|
bnez s2, MainHexDumpLoop
|
||||||
addiu s3, 4
|
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.
|
// use our old cache-poking utility for now.
|
||||||
jal PokeDataCache
|
jal PokeDataCache
|
||||||
nop
|
nop
|
||||||
|
@ -180,50 +210,57 @@ MainHexDumpInnerLoop:
|
||||||
lui a0, VI_BASE
|
lui a0, VI_BASE
|
||||||
li t1, VIDEO_MODE
|
li t1, VIDEO_MODE
|
||||||
li t2, VIDEO_BUFFER & ADDR_MASK
|
li t2, VIDEO_BUFFER & ADDR_MASK
|
||||||
li t3, 640 // width in pixels (for the buffer)
|
li t3, WIDTH // width of the buffer in pixels
|
||||||
li t4, 0 // interrupt on line
|
li t4, 0 // interrupt on line, 0 to disable (i think?)
|
||||||
li t5, 0 // current line; any write clears VI interrupt
|
li t5, 0 // current line; any write clears VI interrupt
|
||||||
li t6, 0x03E52239 // timings (split into 4)
|
li t6, 0x03E52239 // timings (split into 4)
|
||||||
li t7, 525 - 1 // lines. subtracting by one enables interlacing.
|
li t7, 525 - 1 // lines; subtracting by one enables interlacing
|
||||||
sw t1, 4 * 0(a0)
|
sw t1, VI_STATUS(a0) // offset 0x00
|
||||||
sw t2, 4 * 1(a0)
|
sw t2, VI_ORIGIN(a0) // offset 0x04
|
||||||
sw t3, 4 * 2(a0)
|
sw t3, VI_WIDTH(a0) // offset 0x08
|
||||||
sw t4, 4 * 3(a0)
|
sw t4, VI_V_INTR(a0) // offset 0x0C
|
||||||
sw t5, 4 * 4(a0)
|
sw t5, VI_V_CURRENT_LINE(a0) // offset 0x10
|
||||||
sw t6, 4 * 5(a0)
|
sw t6, VI_TIMING(a0) // offset 0x14
|
||||||
sw t7, 4 * 6(a0)
|
sw t7, VI_V_SYNC(a0) // offset 0x18
|
||||||
|
|
||||||
li t1, 0x00000C15 // divide VI clock to get proper NTSC rate
|
li t1, 0x00000C15 // divide VI clock to get proper NTSC rate
|
||||||
li t2, 0x0C150C15 // likewise (this is only different on PAL)
|
li t2, 0x0C150C15 // likewise (this is only different on PAL)
|
||||||
li t3, 0x006C02EC // 640 pixels per row, starting at 108 units
|
li t3, 0x008C02CC // 576 pixels per row, starting at ... units
|
||||||
li t4, 0x00230203 // 480 pixels per column, starting at 35 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 t5, 0x000E0204 // video burst starts at 14 and lasts for 502 units
|
||||||
li t6, 0x00000400 // x offset and x step size (inverse scaling)
|
li t6, 0x00000400 // x offset and x step size (inverse scaling)
|
||||||
li t7, 0x00000800 // y offset and y step size (inverse scaling)
|
li t7, 0x02000800 // y offset and y step size (inverse scaling)
|
||||||
sw t1, 4 * 7(a0)
|
// setting y offset to 0.5 (it's Q10 fixed point)
|
||||||
sw t2, 4 * 8(a0)
|
// reduces interlacing jitter at the cost of a little image sharpness.
|
||||||
sw t3, 4 * 9(a0)
|
sw t1, VI_H_SYNC(a0) // offset 0x1C
|
||||||
sw t4, 4 * 10(a0)
|
sw t2, VI_H_SYNC_LEAP(a0) // offset 0x20
|
||||||
sw t5, 4 * 11(a0)
|
sw t3, VI_H_VIDEO(a0) // offset 0x24
|
||||||
sw t6, 4 * 12(a0)
|
sw t4, VI_V_VIDEO(a0) // offset 0x28
|
||||||
sw t7, 4 * 13(a0)
|
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:
|
VideoLoop:
|
||||||
lui a0, VI_BASE
|
lui a0, VI_BASE
|
||||||
li t1, VIDEO_BUFFER & ADDR_MASK
|
li t1, VIDEO_BUFFER & ADDR_MASK
|
||||||
|
|
||||||
-
|
-
|
||||||
|
// wait until we're done displaying the frame.
|
||||||
lw t0, VI_V_CURRENT_LINE(a0)
|
lw t0, VI_V_CURRENT_LINE(a0)
|
||||||
sltiu at, t0, 2 + 1
|
sltiu at, t0, 2 + 1
|
||||||
beqz at,-
|
beqz at,-
|
||||||
nop
|
nop
|
||||||
|
|
||||||
andi t0, 1
|
andi t0, 1 // check if we're on an odd field.
|
||||||
bnez t0,+
|
li t2, 0x003B01EB
|
||||||
|
bnez t0,+ // if we're not, branch.
|
||||||
nop
|
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 t1, VI_ORIGIN(a0)
|
||||||
|
sw t2, VI_V_VIDEO(a0)
|
||||||
|
|
||||||
j VideoLoop
|
j VideoLoop
|
||||||
nop
|
nop
|
||||||
|
@ -250,4 +287,9 @@ PokeDataCache:
|
||||||
jr ra
|
jr ra
|
||||||
nop
|
nop
|
||||||
|
|
||||||
include "font.asm"
|
align(16)
|
||||||
|
insert TEXT, "text.txt"
|
||||||
|
db 0
|
||||||
|
align(4)
|
||||||
|
|
||||||
|
include "font.8x16.asm"
|
||||||
|
|
27
dlist.asm
27
dlist.asm
|
@ -174,14 +174,25 @@ if HIRES {
|
||||||
gMatrix(view_mat1, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION)
|
gMatrix(view_mat1, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION)
|
||||||
|
|
||||||
gPipeSync()
|
gPipeSync()
|
||||||
gSetCombine(15,15,31,4,7,7,7,4, 15,15,31,4,7,7,7,4)
|
gSetCombine(0,0,0,4,0,0,0,4, 0,0,0,4,0,0,0,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)
|
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)
|
gGeometryMode(0, G_ZBUFFER | G_SHADE | G_CULL_FRONT | G_SHADING_SMOOTH)
|
||||||
|
|
||||||
gSetSegment6(model)
|
gSetSegment6(model)
|
||||||
gMatrix(model_mat, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW)
|
gMatrix(model_mat, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW)
|
||||||
gDisplayList((6 << 24) | MODEL_START)
|
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.
|
// finish.
|
||||||
gFullSync()
|
gFullSync()
|
||||||
gEndList()
|
gEndList()
|
||||||
|
@ -204,8 +215,8 @@ align(8)
|
||||||
|
|
||||||
viewport:
|
viewport:
|
||||||
// note that the third parameters here affect the range of Z-buffering.
|
// 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, 0x1FF, 0 // scale
|
||||||
dh WIDTH/2*4, HEIGHT/2*4, 0x000, 0 // translation
|
dh WIDTH/2*4, HEIGHT/2*4, 0x1FF, 0 // translation
|
||||||
|
|
||||||
view_mat0:
|
view_mat0:
|
||||||
if FOV90 {
|
if FOV90 {
|
||||||
|
@ -215,10 +226,10 @@ if FOV90 {
|
||||||
Mat.X($0001'4C8D, $0000'0000, $0000'0000, $0000'0000)
|
Mat.X($0001'4C8D, $0000'0000, $0000'0000, $0000'0000)
|
||||||
Mat.Y($0000'0000, $0001'BB67, $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.Z($0000'0000, $0000'0000, $FFFE'FF9A, $FFFF'0000)
|
||||||
Mat.W($0000'0000, $0000'0000, $FFFD'FF00, $0000'0000)
|
Mat.W($0000'0000, $0000'0000, $FFEB'FC00, $0000'0000)
|
||||||
Mat.rix()
|
Mat.rix()
|
||||||
constant PERSPECTIVE_NORMALIZATION($00FF)
|
constant PERSPECTIVE_NORMALIZATION($000A)
|
||||||
|
|
||||||
view_mat1:
|
view_mat1:
|
||||||
Mat.X($0001'0000, $0000'0000, $0000'0000, $0000'0000)
|
Mat.X($0001'0000, $0000'0000, $0000'0000, $0000'0000)
|
||||||
|
@ -265,6 +276,6 @@ constant MODEL_START(pc() - model)
|
||||||
gQuadTri(2, 3, 7, 6)
|
gQuadTri(2, 3, 7, 6)
|
||||||
gEndList()
|
gEndList()
|
||||||
} else {
|
} else {
|
||||||
constant MODEL_START(0x32B0)
|
constant MODEL_START(0)
|
||||||
insert model, "res/teapot.F3D"
|
insert model, "res/teapot.F3D"
|
||||||
}
|
}
|
||||||
|
|
144
font.8x16.asm
Normal file
144
font.8x16.asm
Normal 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
103
font.asm
|
@ -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"
|
|
|
@ -159,16 +159,29 @@ constant CVG_DST_WRAP(0x100)
|
||||||
constant CVG_DST_FULL(0x200)
|
constant CVG_DST_FULL(0x200)
|
||||||
constant CVG_DST_SAVE(0x300)
|
constant CVG_DST_SAVE(0x300)
|
||||||
// more Z stuff
|
// more Z stuff
|
||||||
constant ZMODE_OPA(0)
|
constant ZMODE_OPA(0) // opaque
|
||||||
constant ZMODE_INTER(0x400)
|
constant ZMODE_INTER(0x400) // interpenetrating
|
||||||
constant ZMODE_XLU(0x800)
|
constant ZMODE_XLU(0x800) // translucent
|
||||||
constant ZMODE_DEC(0xC00)
|
constant ZMODE_DEC(0xC00) // decal
|
||||||
// more coverage stuff
|
// more coverage stuff
|
||||||
constant CVG_X_ALPHA(0x1000)
|
constant CVG_X_ALPHA(0x1000)
|
||||||
constant ALPHA_CVG_SEL(0x2000)
|
constant ALPHA_CVG_SEL(0x2000)
|
||||||
// blending
|
// blending
|
||||||
constant FORCE_BL(0x4000) // no effect?
|
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() {
|
macro gNoOp() {
|
||||||
// stalls the RDP (and not the RSP?)
|
// stalls the RDP (and not the RSP?)
|
||||||
_g(0x00, 0, 0)
|
_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.
|
// fixes the Z value to a constant for the following primitives.
|
||||||
// useful for 2.5D effects, maybe?
|
// useful for 2.5D effects, maybe?
|
||||||
// TODO: what are the ranges?
|
// TODO: what are the ranges?
|
||||||
_g(0xEE, 0, (z << 16) | d)
|
_g(0xEE, 0, (z << 16) | dz)
|
||||||
}
|
}
|
||||||
|
|
||||||
macro gRdpSetOtherMode(variable omodeH, variable omodeL) {
|
macro gRdpSetOtherMode(variable omodeH, variable omodeL) {
|
||||||
|
|
12
inc/main.inc
12
inc/main.inc
|
@ -5,7 +5,7 @@ constant HICOLOR(0)
|
||||||
|
|
||||||
constant MAIN_DECOMP_IMAGE(HIRES & HICOLOR)
|
constant MAIN_DECOMP_IMAGE(HIRES & HICOLOR)
|
||||||
|
|
||||||
constant MAIN_BASE(0x800E)
|
constant MAIN_BASE(0x8004)
|
||||||
constant MAIN_COUNTS(0x0010)
|
constant MAIN_COUNTS(0x0010)
|
||||||
constant MAIN_SP_TASK(0x0040)
|
constant MAIN_SP_TASK(0x0040)
|
||||||
constant MAIN_XXD(0x0080)
|
constant MAIN_XXD(0x0080)
|
||||||
|
@ -13,6 +13,8 @@ constant MAIN_DLIST(0x1000)
|
||||||
constant MAIN_DLIST_SIZE(0xF000)
|
constant MAIN_DLIST_SIZE(0xF000)
|
||||||
constant MAIN_DLIST_JUMPER(MAIN_DLIST - 0xA8)
|
constant MAIN_DLIST_JUMPER(MAIN_DLIST - 0xA8)
|
||||||
|
|
||||||
|
constant FONT_BASE(0x8005)
|
||||||
|
|
||||||
if HIRES {
|
if HIRES {
|
||||||
constant WIDTH(640)
|
constant WIDTH(640)
|
||||||
constant HEIGHT(480)
|
constant HEIGHT(480)
|
||||||
|
@ -21,6 +23,12 @@ if HIRES {
|
||||||
constant HEIGHT(240)
|
constant HEIGHT(240)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if HICOLOR {
|
||||||
|
constant DEPTH(4)
|
||||||
|
} else {
|
||||||
|
constant DEPTH(2)
|
||||||
|
}
|
||||||
|
|
||||||
if HIRES {
|
if HIRES {
|
||||||
if HICOLOR {
|
if HICOLOR {
|
||||||
// 640x480, 32-bit
|
// 640x480, 32-bit
|
||||||
|
@ -44,7 +52,7 @@ constant TASK_DP_WAIT(0x0002)
|
||||||
constant TASK_LOADABLE(0x0004)
|
constant TASK_LOADABLE(0x0004)
|
||||||
constant TASK_SP_ONLY(0x0008)
|
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_Z_IMAGE_SIZE(WIDTH * HEIGHT * 2)
|
||||||
constant VIDEO_OUTPUT_SIZE(0x18000) // technically a buffer?
|
constant VIDEO_OUTPUT_SIZE(0x18000) // technically a buffer?
|
||||||
constant VIDEO_STACK_SIZE(0x8000) // used for dlist calls, pushing matrices, etc?
|
constant VIDEO_STACK_SIZE(0x8000) // used for dlist calls, pushing matrices, etc?
|
||||||
|
|
|
@ -15,6 +15,11 @@ include "n64_si.inc"
|
||||||
include "n64_pif.inc"
|
include "n64_pif.inc"
|
||||||
include "n64_util.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
|
// Memory Map
|
||||||
constant RDRAM_BASE($A3F0) // $03F00000 RDRAM Base
|
constant RDRAM_BASE($A3F0) // $03F00000 RDRAM Base
|
||||||
constant RDRAM_DEVICE_TYPE($00) // $03F00000 Device Type
|
constant RDRAM_DEVICE_TYPE($00) // $03F00000 Device Type
|
||||||
|
|
|
@ -408,7 +408,6 @@ K_MI_AI:
|
||||||
andi s0, ~MI_INTR_AI
|
andi s0, ~MI_INTR_AI
|
||||||
|
|
||||||
K_MI_VI:
|
K_MI_VI:
|
||||||
|
|
||||||
lw a0, KV_RES(k0)
|
lw a0, KV_RES(k0)
|
||||||
lw a1, KV_MODE(k0)
|
lw a1, KV_MODE(k0)
|
||||||
jal SetScreenNTSC
|
jal SetScreenNTSC
|
||||||
|
|
88
main.asm
88
main.asm
|
@ -23,9 +23,13 @@ include "kernel.asm"
|
||||||
|
|
||||||
Main:
|
Main:
|
||||||
|
|
||||||
|
lui s0, MAIN_BASE
|
||||||
|
|
||||||
|
jal LoadFont16
|
||||||
|
lui a0, FONT_BASE
|
||||||
|
|
||||||
if MAIN_DECOMP_IMAGE {
|
if MAIN_DECOMP_IMAGE {
|
||||||
DecompImage:
|
DecompImage:
|
||||||
lui s0, MAIN_BASE
|
|
||||||
|
|
||||||
nop; nop; nop; nop
|
nop; nop; nop; nop
|
||||||
mfc0 t0, CP0_Count
|
mfc0 t0, CP0_Count
|
||||||
|
@ -72,8 +76,7 @@ Start3D:
|
||||||
mfc0 t0, CP0_Status
|
mfc0 t0, CP0_Status
|
||||||
mtc0 t0, CP0_Status
|
mtc0 t0, CP0_Status
|
||||||
|
|
||||||
lui a0, MAIN_BASE
|
ori a0, s0, MAIN_DLIST
|
||||||
ori a0, MAIN_DLIST
|
|
||||||
jal WriteDList
|
jal WriteDList
|
||||||
or a1, s1, r0
|
or a1, s1, r0
|
||||||
jal PokeDataCache
|
jal PokeDataCache
|
||||||
|
@ -91,9 +94,8 @@ Start3D:
|
||||||
// only the lowest 12 bits are used, so 00000000 is equivalent to 04001000.
|
// only the lowest 12 bits are used, so 00000000 is equivalent to 04001000.
|
||||||
sw r0, SP_PC(a0)
|
sw r0, SP_PC(a0)
|
||||||
|
|
||||||
lui a0, MAIN_BASE
|
|
||||||
jal PushVideoTask
|
jal PushVideoTask
|
||||||
ori a0, MAIN_SP_TASK
|
ori a0, s0, MAIN_SP_TASK
|
||||||
|
|
||||||
jal LoadRSPBoot
|
jal LoadRSPBoot
|
||||||
nop
|
nop
|
||||||
|
@ -106,6 +108,8 @@ Start3D:
|
||||||
EnableInt()
|
EnableInt()
|
||||||
|
|
||||||
MainLoop:
|
MainLoop:
|
||||||
|
mfc0 s2, CP0_Count
|
||||||
|
|
||||||
WriteString(S_SP_Wait)
|
WriteString(S_SP_Wait)
|
||||||
-
|
-
|
||||||
mfc0 t0, CP0_Status
|
mfc0 t0, CP0_Status
|
||||||
|
@ -117,6 +121,79 @@ MainLoop:
|
||||||
beqz t0,-
|
beqz t0,-
|
||||||
nop
|
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
|
// queue buffers to swap
|
||||||
lui a0, K_BASE
|
lui a0, K_BASE
|
||||||
beqz s1, SwapToMain
|
beqz s1, SwapToMain
|
||||||
|
@ -197,6 +274,7 @@ if MAIN_DECOMP_IMAGE {
|
||||||
}
|
}
|
||||||
include "dlist.asm"
|
include "dlist.asm"
|
||||||
include "task.asm"
|
include "task.asm"
|
||||||
|
include "font.8x16.asm"
|
||||||
|
|
||||||
if pc() > (MAIN_BASE << 16) {
|
if pc() > (MAIN_BASE << 16) {
|
||||||
error "ran out of memory for code and data"
|
error "ran out of memory for code and data"
|
||||||
|
|
BIN
res/fonts/NotoSansMono-SemiCondensedMedium.16.i4
Normal file
BIN
res/fonts/NotoSansMono-SemiCondensedMedium.16.i4
Normal file
Binary file not shown.
BIN
res/teapot.F3D
BIN
res/teapot.F3D
Binary file not shown.
11
task.asm
11
task.asm
|
@ -5,10 +5,15 @@ PushVideoTask:
|
||||||
|
|
||||||
lli t0, 1 // mode: video
|
lli t0, 1 // mode: video
|
||||||
lli t1, TASK_DP_WAIT // flags
|
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 t3, UCODE_BOOT.size
|
||||||
li t4, F3DZEX_IMEM & ADDR_MASK
|
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 t5, F3DZEX_IMEM.size
|
||||||
|
}
|
||||||
li t6, F3DZEX_DMEM & ADDR_MASK
|
li t6, F3DZEX_DMEM & ADDR_MASK
|
||||||
li t7, F3DZEX_DMEM.size
|
li t7, F3DZEX_DMEM.size
|
||||||
sw t0, 0x00(a0)
|
sw t0, 0x00(a0)
|
||||||
|
@ -25,7 +30,7 @@ PushVideoTask:
|
||||||
li t2, (VIDEO_OUTPUT & ADDR_MASK) | UNCACHED
|
li t2, (VIDEO_OUTPUT & ADDR_MASK) | UNCACHED
|
||||||
// most commercial games re-use the yield pointer, so i assume it's fine:
|
// 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 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
|
lli t5, 8 // size of one jump command. this is ignored and 0xA8 is used instead
|
||||||
li t6, VIDEO_YIELD & ADDR_MASK
|
li t6, VIDEO_YIELD & ADDR_MASK
|
||||||
li t7, VIDEO_YIELD_SIZE
|
li t7, VIDEO_YIELD_SIZE
|
||||||
|
@ -38,6 +43,8 @@ PushVideoTask:
|
||||||
sw t6, 0x38(a0)
|
sw t6, 0x38(a0)
|
||||||
sw t7, 0x3C(a0)
|
sw t7, 0x3C(a0)
|
||||||
|
|
||||||
|
nop; nop; nop; nop
|
||||||
|
|
||||||
// tell data cache to write itself out
|
// tell data cache to write itself out
|
||||||
cache 0x19, 0x00(a0)
|
cache 0x19, 0x00(a0)
|
||||||
cache 0x19, 0x10(a0)
|
cache 0x19, 0x10(a0)
|
||||||
|
|
12
text.txt
Normal file
12
text.txt
Normal 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...
|
Loading…
Add table
Reference in a new issue