rewrite the way VI is handled
warning: only 240p is tested, and i think 480i is broken.
This commit is contained in:
parent
850108b157
commit
c8e5d24975
4 changed files with 216 additions and 30 deletions
|
@ -13,6 +13,10 @@ constant K_ERRORPC(0x0614)
|
||||||
constant K_BADVADDR(0x0618)
|
constant K_BADVADDR(0x0618)
|
||||||
constant K_HISTORY(0x061C)
|
constant K_HISTORY(0x061C)
|
||||||
|
|
||||||
|
constant KV_RES(0x0620)
|
||||||
|
constant KV_MODE(0x0624)
|
||||||
|
constant KV_ORIGIN(0x0628)
|
||||||
|
|
||||||
constant K_64DRIVE_MAGIC(0x0700)
|
constant K_64DRIVE_MAGIC(0x0700)
|
||||||
constant K_CI_BASE(0x0704)
|
constant K_CI_BASE(0x0704)
|
||||||
constant K_CONSOLE_AVAILABLE(0x0708)
|
constant K_CONSOLE_AVAILABLE(0x0708)
|
||||||
|
|
149
inc/n64_vi.inc
149
inc/n64_vi.inc
|
@ -55,6 +55,155 @@ constant VI_NTSC_CLOCK(48681812) // NTSC: Hz = 48.681812 MHz
|
||||||
constant VI_PAL_CLOCK(49656530) // PAL: Hz = 49.656530 MHz
|
constant VI_PAL_CLOCK(49656530) // PAL: Hz = 49.656530 MHz
|
||||||
constant VI_MPAL_CLOCK(48628316) // MPAL: Hz = 48.628316 MHz
|
constant VI_MPAL_CLOCK(48628316) // MPAL: Hz = 48.628316 MHz
|
||||||
|
|
||||||
|
// enum for video resolutions; values are arbitrary.
|
||||||
|
// interlaced:
|
||||||
|
constant RES_640_480(480) // no padding.
|
||||||
|
constant RES_576_432(432) // 640x480 after VI padding.
|
||||||
|
constant RES_512_448(448) // stretched to 640x448, 640x480 after VI padding.
|
||||||
|
// not interlaced:
|
||||||
|
constant RES_320_240(240) // upscaled 2x.
|
||||||
|
constant RES_288_216(216) // upscaled 2x. 640x480 after VI padding.
|
||||||
|
constant RES_256_224(224) // upscaled 2x, stretched to 640x448, etc.
|
||||||
|
|
||||||
|
macro MakeSetScreenNTSC() {
|
||||||
|
// note that you can only call this macro once.
|
||||||
|
|
||||||
|
SetScreenNTSC:
|
||||||
|
// this version expects to be called every frame.
|
||||||
|
// a0: resolution to use (enum).
|
||||||
|
// a1: desired VI settings (status/control). mutable.
|
||||||
|
// a2: image color buffer origin address. mutable.
|
||||||
|
// v0: zero on success, non-zero on failure (bad enum or VI settings).
|
||||||
|
|
||||||
|
lui v1, VI_BASE
|
||||||
|
lw t0, VI_V_CURRENT_LINE(v1)
|
||||||
|
andi t0, 1
|
||||||
|
|
||||||
|
andi t1, a1, 3 // extract BPP
|
||||||
|
subiu t1, 2 // now 16 BPP is 0 and 32 BPP is 1
|
||||||
|
bltz t1, SetScreenNTSC_Fail // fail if it's not set to 16 or 32 BPP
|
||||||
|
|
||||||
|
lli t8, RES_640_480 // delay slot
|
||||||
|
beq a0, t8, SetScreenNTSC_480
|
||||||
|
|
||||||
|
lli t9, RES_576_432 // delay slot
|
||||||
|
beq a0, t9, SetScreenNTSC_432
|
||||||
|
|
||||||
|
lli t8, RES_512_448 // delay slot
|
||||||
|
beq a0, t8, SetScreenNTSC_448
|
||||||
|
|
||||||
|
lli t9, RES_320_240 // delay slot
|
||||||
|
beq a0, t9, SetScreenNTSC_240
|
||||||
|
|
||||||
|
lli t8, RES_288_216 // delay slot
|
||||||
|
beq a0, t8, SetScreenNTSC_216
|
||||||
|
|
||||||
|
lli t9, RES_256_224 // delay slot
|
||||||
|
beq a0, t9, SetScreenNTSC_224
|
||||||
|
|
||||||
|
SetScreenNTSC_Fail:
|
||||||
|
lli v0, 1 // delay slot
|
||||||
|
jr ra
|
||||||
|
sw r0, VI_V_CURRENT_LINE(v1) // clear interrupt
|
||||||
|
|
||||||
|
SetScreenNTSC_SetInterlaced:
|
||||||
|
beqz t0, SetScreenNTSC_Set // nothing more to do on even fields.
|
||||||
|
ori a1, INTERLACE
|
||||||
|
|
||||||
|
// handle odd fields.
|
||||||
|
addu a2, t2 // add width to origin
|
||||||
|
addu a2, t2 // and again for a full row (when 16 BPP)
|
||||||
|
beqz t1, SetScreenNTSC_Set // branch when 16 BPP
|
||||||
|
subiu t7, 2 // prevents bottom line from displaying out-of-bounds garbage
|
||||||
|
addu a2, t2
|
||||||
|
addu a2, t2 // full row (when 32 BPP)
|
||||||
|
|
||||||
|
SetScreenNTSC_Set:
|
||||||
|
lw t1, VI_V_CURRENT_LINE(v1)
|
||||||
|
|
||||||
|
// variable stuff:
|
||||||
|
sw t1, VI_V_CURRENT_LINE(v1)
|
||||||
|
sw t2, VI_WIDTH(v1) // VI_H_WIDTH
|
||||||
|
sw t3, VI_V_SYNC(v1)
|
||||||
|
sw t4, VI_X_SCALE(v1)
|
||||||
|
sw t5, VI_Y_SCALE(v1)
|
||||||
|
sw t6, VI_H_VIDEO(v1) // VI_H_START
|
||||||
|
sw t7, VI_V_VIDEO(v1) // VI_V_START
|
||||||
|
|
||||||
|
// constant stuff:
|
||||||
|
lli t1, 2
|
||||||
|
li t2, 57 | (34 << 8) | (5 << 16) | (62 << 20)
|
||||||
|
lli t3, 3093
|
||||||
|
li t4, 3093 | (3093 << 16)
|
||||||
|
li t5, (0x0E << 16) | 0x204
|
||||||
|
sw t1, VI_V_INTR(v1) // VI_INTR
|
||||||
|
sw t2, VI_TIMING(v1) // VI_BURST
|
||||||
|
sw t3, VI_H_SYNC(v1)
|
||||||
|
sw t4, VI_H_SYNC_LEAP(v1) // VI_LEAP
|
||||||
|
sw t5, VI_V_BURST(v1)
|
||||||
|
|
||||||
|
// final variable stuff:
|
||||||
|
sw a1, VI_STATUS(v1) // VI_CONTROL
|
||||||
|
sw a2, VI_ORIGIN(v1) // VI_DRAM_ADDR
|
||||||
|
|
||||||
|
jr ra
|
||||||
|
lli v0, 0
|
||||||
|
|
||||||
|
SetScreenNTSC_480:
|
||||||
|
lli t2, 640
|
||||||
|
li t4, 0x400
|
||||||
|
li t5, 0x800 | (0x200 << 16)
|
||||||
|
li t6, (0x6C << 16) | (0x6C + 640)
|
||||||
|
li t7, (0x23 << 16) | (0x23 + 480)
|
||||||
|
b SetScreenNTSC_SetInterlaced
|
||||||
|
lli t3, 525 - 1
|
||||||
|
|
||||||
|
SetScreenNTSC_432:
|
||||||
|
lli t2, 576
|
||||||
|
li t4, 0x400
|
||||||
|
li t5, 0x800 | (0x200 << 16)
|
||||||
|
li t6, (0x8C << 16) | (0x8C + 576)
|
||||||
|
li t7, (0x3B << 16) | (0x3B + 432)
|
||||||
|
b SetScreenNTSC_SetInterlaced
|
||||||
|
lli t3, 525 - 1
|
||||||
|
|
||||||
|
SetScreenNTSC_448:
|
||||||
|
lli t2, 512
|
||||||
|
li t4, (512 * 256 + 128) / 160
|
||||||
|
li t5, 0x800 | (0x200 << 16)
|
||||||
|
li t6, (0x6C << 16) | (0x6C + 640)
|
||||||
|
li t7, (0x33 << 16) | (0x33 + 448)
|
||||||
|
b SetScreenNTSC_SetInterlaced
|
||||||
|
lli t3, 525 - 1
|
||||||
|
|
||||||
|
SetScreenNTSC_240:
|
||||||
|
lli t2, 320
|
||||||
|
li t4, 0x200
|
||||||
|
li t5, 0x400
|
||||||
|
li t6, (0x6C << 16) | (0x6C + 640)
|
||||||
|
li t7, (0x23 << 16) | (0x23 + 480)
|
||||||
|
b SetScreenNTSC_Set
|
||||||
|
lli t3, 525
|
||||||
|
|
||||||
|
SetScreenNTSC_216:
|
||||||
|
lli t2, 288
|
||||||
|
li t4, 0x200
|
||||||
|
li t5, 0x400
|
||||||
|
li t6, (0x8C << 16) | (0x8C + 576)
|
||||||
|
li t7, (0x3B << 16) | (0x3B + 432)
|
||||||
|
b SetScreenNTSC_Set
|
||||||
|
lli t3, 525
|
||||||
|
|
||||||
|
SetScreenNTSC_224:
|
||||||
|
lli t2, 256
|
||||||
|
li t4, (256 * 256 + 128) / 160
|
||||||
|
li t5, 0x400
|
||||||
|
li t6, (0x6C << 16) | (0x6C + 640)
|
||||||
|
li t7, (0x33 << 16) | (0x33 + 448)
|
||||||
|
b SetScreenNTSC_Set
|
||||||
|
lli t3, 525
|
||||||
|
}
|
||||||
|
|
||||||
macro ScreenNTSC(width,height, status, origin) {
|
macro ScreenNTSC(width,height, status, origin) {
|
||||||
lui a0,VI_BASE // A0 = VI Base Register ($A4400000)
|
lui a0,VI_BASE // A0 = VI Base Register ($A4400000)
|
||||||
la t0,{origin} // T0 = Origin (Frame Buffer Origin In Bytes)
|
la t0,{origin} // T0 = Origin (Frame Buffer Origin In Bytes)
|
||||||
|
|
41
kernel.asm
41
kernel.asm
|
@ -24,6 +24,9 @@ include "init.asm"
|
||||||
sw r0, K_UNUSED(gp)
|
sw r0, K_UNUSED(gp)
|
||||||
sw r0, K_CONSOLE_AVAILABLE(gp)
|
sw r0, K_CONSOLE_AVAILABLE(gp)
|
||||||
sw r0, K_HISTORY(gp)
|
sw r0, K_HISTORY(gp)
|
||||||
|
sw r0, KV_RES(gp)
|
||||||
|
sw r0, KV_MODE(gp)
|
||||||
|
sw r0, KV_ORIGIN(gp)
|
||||||
|
|
||||||
Drive64Init:
|
Drive64Init:
|
||||||
lui t9, CI_BASE
|
lui t9, CI_BASE
|
||||||
|
@ -368,12 +371,12 @@ K_MI_Loop:
|
||||||
nop
|
nop
|
||||||
|
|
||||||
K_MI_SP:
|
K_MI_SP:
|
||||||
KWriteString(KS_MI_SP)
|
|
||||||
|
|
||||||
lli t0, SP_INT_CLR
|
lli t0, SP_INT_CLR
|
||||||
lui a1, SP_BASE
|
lui a1, SP_BASE
|
||||||
sw t0, SP_STATUS(a1)
|
sw t0, SP_STATUS(a1)
|
||||||
|
|
||||||
|
KWriteString(KS_MI_SP)
|
||||||
|
|
||||||
lw t0, K_HISTORY(k0)
|
lw t0, K_HISTORY(k0)
|
||||||
ori t0, MI_INTR_SP
|
ori t0, MI_INTR_SP
|
||||||
sw t0, K_HISTORY(k0)
|
sw t0, K_HISTORY(k0)
|
||||||
|
@ -381,11 +384,11 @@ K_MI_SP:
|
||||||
andi s0, ~MI_INTR_SP
|
andi s0, ~MI_INTR_SP
|
||||||
|
|
||||||
K_MI_SI:
|
K_MI_SI:
|
||||||
KWriteString(KS_MI_SI)
|
|
||||||
|
|
||||||
lui a1, SI_BASE
|
lui a1, SI_BASE
|
||||||
sw r0, SI_STATUS(a1)
|
sw r0, SI_STATUS(a1)
|
||||||
|
|
||||||
|
KWriteString(KS_MI_SI)
|
||||||
|
|
||||||
lw t0, K_HISTORY(k0)
|
lw t0, K_HISTORY(k0)
|
||||||
ori t0, MI_INTR_SI
|
ori t0, MI_INTR_SI
|
||||||
sw t0, K_HISTORY(k0)
|
sw t0, K_HISTORY(k0)
|
||||||
|
@ -393,11 +396,11 @@ K_MI_SI:
|
||||||
andi s0, ~MI_INTR_SI
|
andi s0, ~MI_INTR_SI
|
||||||
|
|
||||||
K_MI_AI:
|
K_MI_AI:
|
||||||
KWriteString(KS_MI_AI)
|
|
||||||
|
|
||||||
lui a1, AI_BASE
|
lui a1, AI_BASE
|
||||||
sw r0, AI_STATUS(a1)
|
sw r0, AI_STATUS(a1)
|
||||||
|
|
||||||
|
KWriteString(KS_MI_AI)
|
||||||
|
|
||||||
lw t0, K_HISTORY(k0)
|
lw t0, K_HISTORY(k0)
|
||||||
ori t0, MI_INTR_AI
|
ori t0, MI_INTR_AI
|
||||||
sw t0, K_HISTORY(k0)
|
sw t0, K_HISTORY(k0)
|
||||||
|
@ -405,11 +408,13 @@ K_MI_AI:
|
||||||
andi s0, ~MI_INTR_AI
|
andi s0, ~MI_INTR_AI
|
||||||
|
|
||||||
K_MI_VI:
|
K_MI_VI:
|
||||||
KWriteString(KS_MI_VI)
|
|
||||||
|
|
||||||
lui a1, VI_BASE
|
lw a0, KV_RES(k0)
|
||||||
lw t0, VI_V_CURRENT_LINE(a1)
|
lw a1, KV_MODE(k0)
|
||||||
sw t0, VI_V_CURRENT_LINE(a1)
|
jal SetScreenNTSC
|
||||||
|
lw a2, KV_ORIGIN(k0)
|
||||||
|
|
||||||
|
KWriteString(KS_MI_VI)
|
||||||
|
|
||||||
lw t0, K_HISTORY(k0)
|
lw t0, K_HISTORY(k0)
|
||||||
ori t0, MI_INTR_VI
|
ori t0, MI_INTR_VI
|
||||||
|
@ -418,12 +423,12 @@ K_MI_VI:
|
||||||
andi s0, ~MI_INTR_VI
|
andi s0, ~MI_INTR_VI
|
||||||
|
|
||||||
K_MI_PI:
|
K_MI_PI:
|
||||||
KWriteString(KS_MI_PI)
|
|
||||||
|
|
||||||
lli t0, 0x02
|
lli t0, 0x02
|
||||||
lui a1, PI_BASE
|
lui a1, PI_BASE
|
||||||
sw t0, PI_STATUS(a1)
|
sw t0, PI_STATUS(a1)
|
||||||
|
|
||||||
|
KWriteString(KS_MI_PI)
|
||||||
|
|
||||||
lw t0, K_HISTORY(k0)
|
lw t0, K_HISTORY(k0)
|
||||||
ori t0, MI_INTR_PI
|
ori t0, MI_INTR_PI
|
||||||
sw t0, K_HISTORY(k0)
|
sw t0, K_HISTORY(k0)
|
||||||
|
@ -431,12 +436,12 @@ K_MI_PI:
|
||||||
andi s0, ~MI_INTR_PI
|
andi s0, ~MI_INTR_PI
|
||||||
|
|
||||||
K_MI_DP:
|
K_MI_DP:
|
||||||
KWriteString(KS_MI_DP)
|
|
||||||
|
|
||||||
lli t0, 0x0800
|
lli t0, 0x0800
|
||||||
lui a1, MI_BASE
|
lui a1, MI_BASE
|
||||||
sw t0, MI_INIT_MODE(a1)
|
sw t0, MI_INIT_MODE(a1)
|
||||||
|
|
||||||
|
KWriteString(KS_MI_DP)
|
||||||
|
|
||||||
lw t0, K_HISTORY(k0)
|
lw t0, K_HISTORY(k0)
|
||||||
ori t0, MI_INTR_DP
|
ori t0, MI_INTR_DP
|
||||||
sw t0, K_HISTORY(k0)
|
sw t0, K_HISTORY(k0)
|
||||||
|
@ -485,6 +490,14 @@ dw KCode20, KCode21, KCode22, KCode23
|
||||||
dw KCode24, KCode25, KCode26, KCode27
|
dw KCode24, KCode25, KCode26, KCode27
|
||||||
dw KCode28, KCode29, KCode30, KCode31
|
dw KCode28, KCode29, KCode30, KCode31
|
||||||
|
|
||||||
|
K_SetScreenNTSC:
|
||||||
|
lui a3, K_BASE
|
||||||
|
sw a0, KV_RES(a3)
|
||||||
|
sw a1, KV_MODE(a3)
|
||||||
|
sw a2, KV_ORIGIN(a3)
|
||||||
|
// fall-thru
|
||||||
|
MakeSetScreenNTSC()
|
||||||
|
|
||||||
include "debug.asm"
|
include "debug.asm"
|
||||||
|
|
||||||
if K_DEBUG {
|
if K_DEBUG {
|
||||||
|
|
52
main.asm
52
main.asm
|
@ -117,8 +117,23 @@ MainLoop:
|
||||||
beqz t0,-
|
beqz t0,-
|
||||||
nop
|
nop
|
||||||
|
|
||||||
WriteString(S_VI_Wait)
|
// queue buffers to swap
|
||||||
|
lui a0, K_BASE
|
||||||
|
beqz s1, SwapToMain
|
||||||
|
nop
|
||||||
|
SwapToAlt:
|
||||||
|
la t0, VIDEO_C_IMAGE_ALT | UNCACHED
|
||||||
|
sw t0, KV_ORIGIN(a0)
|
||||||
|
b +
|
||||||
|
lli s1, 0
|
||||||
|
SwapToMain:
|
||||||
|
la t0, VIDEO_C_IMAGE | UNCACHED
|
||||||
|
sw t0, KV_ORIGIN(a0)
|
||||||
|
lli s1, 1
|
||||||
|
+
|
||||||
|
|
||||||
// wait on VI too
|
// wait on VI too
|
||||||
|
WriteString(S_VI_Wait)
|
||||||
lui a0, VI_BASE
|
lui a0, VI_BASE
|
||||||
-
|
-
|
||||||
lw t0, VI_V_CURRENT_LINE(a0)
|
lw t0, VI_V_CURRENT_LINE(a0)
|
||||||
|
@ -129,24 +144,27 @@ MainLoop:
|
||||||
|
|
||||||
WriteString(SNewFrame)
|
WriteString(SNewFrame)
|
||||||
|
|
||||||
// swap buffers
|
j Start3D
|
||||||
lui a0, VI_BASE
|
|
||||||
beqz s1, SwitchToAlt
|
|
||||||
nop
|
nop
|
||||||
SwitchToMain:
|
|
||||||
la t0, VIDEO_C_IMAGE_ALT | UNCACHED
|
|
||||||
sw t0, VI_ORIGIN(a0)
|
|
||||||
j Start3D
|
|
||||||
lli s1, 0
|
|
||||||
SwitchToAlt:
|
|
||||||
la t0, VIDEO_C_IMAGE | UNCACHED
|
|
||||||
sw t0, VI_ORIGIN(a0)
|
|
||||||
j Start3D
|
|
||||||
lli s1, 1
|
|
||||||
|
|
||||||
SetupScreen:
|
SetupScreen:
|
||||||
ScreenNTSC(WIDTH, HEIGHT, VIDEO_MODE, VIDEO_C_IMAGE | UNCACHED)
|
if WIDTH == 640 {
|
||||||
jr ra
|
lli a0, RES_640_480
|
||||||
|
} else if WIDTH == 576 {
|
||||||
|
lli a0, RES_576_432
|
||||||
|
} else if WIDTH == 512 {
|
||||||
|
lli a0, RES_512_448
|
||||||
|
} else if WIDTH == 320 {
|
||||||
|
lli a0, RES_320_240
|
||||||
|
} else if WIDTH == 288 {
|
||||||
|
lli a0, RES_288_216
|
||||||
|
} else if WIDTH == 256 {
|
||||||
|
lli a0, RES_256_224
|
||||||
|
}
|
||||||
|
|
||||||
|
li a1, VIDEO_MODE
|
||||||
|
la a2, VIDEO_C_IMAGE | UNCACHED
|
||||||
|
j K_SetScreenNTSC // tail-call
|
||||||
nop
|
nop
|
||||||
|
|
||||||
MainDumpWrite:
|
MainDumpWrite:
|
||||||
|
@ -164,6 +182,8 @@ MainDumpWrite:
|
||||||
addiu sp, 0x18
|
addiu sp, 0x18
|
||||||
|
|
||||||
Die:
|
Die:
|
||||||
|
mfc0 t0, CP0_Status
|
||||||
|
mtc0 t0, CP0_Status
|
||||||
j Die
|
j Die
|
||||||
nop
|
nop
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue