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_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"
|
||||
|
|
27
dlist.asm
27
dlist.asm
|
@ -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
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_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) {
|
||||
|
|
12
inc/main.inc
12
inc/main.inc
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
88
main.asm
88
main.asm
|
@ -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"
|
||||
|
|
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 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
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…
Reference in a new issue