rewrite the way VI is handled

warning: only 240p is tested, and i think 480i is broken.
This commit is contained in:
Connor Olding 2018-10-21 17:31:03 +02:00
parent 850108b157
commit c8e5d24975
4 changed files with 216 additions and 30 deletions

View File

@ -13,6 +13,10 @@ constant K_ERRORPC(0x0614)
constant K_BADVADDR(0x0618)
constant K_HISTORY(0x061C)
constant KV_RES(0x0620)
constant KV_MODE(0x0624)
constant KV_ORIGIN(0x0628)
constant K_64DRIVE_MAGIC(0x0700)
constant K_CI_BASE(0x0704)
constant K_CONSOLE_AVAILABLE(0x0708)

View File

@ -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_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) {
lui a0,VI_BASE // A0 = VI Base Register ($A4400000)
la t0,{origin} // T0 = Origin (Frame Buffer Origin In Bytes)

View File

@ -24,6 +24,9 @@ include "init.asm"
sw r0, K_UNUSED(gp)
sw r0, K_CONSOLE_AVAILABLE(gp)
sw r0, K_HISTORY(gp)
sw r0, KV_RES(gp)
sw r0, KV_MODE(gp)
sw r0, KV_ORIGIN(gp)
Drive64Init:
lui t9, CI_BASE
@ -368,12 +371,12 @@ K_MI_Loop:
nop
K_MI_SP:
KWriteString(KS_MI_SP)
lli t0, SP_INT_CLR
lui a1, SP_BASE
sw t0, SP_STATUS(a1)
KWriteString(KS_MI_SP)
lw t0, K_HISTORY(k0)
ori t0, MI_INTR_SP
sw t0, K_HISTORY(k0)
@ -381,11 +384,11 @@ K_MI_SP:
andi s0, ~MI_INTR_SP
K_MI_SI:
KWriteString(KS_MI_SI)
lui a1, SI_BASE
sw r0, SI_STATUS(a1)
KWriteString(KS_MI_SI)
lw t0, K_HISTORY(k0)
ori t0, MI_INTR_SI
sw t0, K_HISTORY(k0)
@ -393,11 +396,11 @@ K_MI_SI:
andi s0, ~MI_INTR_SI
K_MI_AI:
KWriteString(KS_MI_AI)
lui a1, AI_BASE
sw r0, AI_STATUS(a1)
KWriteString(KS_MI_AI)
lw t0, K_HISTORY(k0)
ori t0, MI_INTR_AI
sw t0, K_HISTORY(k0)
@ -405,11 +408,13 @@ K_MI_AI:
andi s0, ~MI_INTR_AI
K_MI_VI:
KWriteString(KS_MI_VI)
lui a1, VI_BASE
lw t0, VI_V_CURRENT_LINE(a1)
sw t0, VI_V_CURRENT_LINE(a1)
lw a0, KV_RES(k0)
lw a1, KV_MODE(k0)
jal SetScreenNTSC
lw a2, KV_ORIGIN(k0)
KWriteString(KS_MI_VI)
lw t0, K_HISTORY(k0)
ori t0, MI_INTR_VI
@ -418,12 +423,12 @@ K_MI_VI:
andi s0, ~MI_INTR_VI
K_MI_PI:
KWriteString(KS_MI_PI)
lli t0, 0x02
lui a1, PI_BASE
sw t0, PI_STATUS(a1)
KWriteString(KS_MI_PI)
lw t0, K_HISTORY(k0)
ori t0, MI_INTR_PI
sw t0, K_HISTORY(k0)
@ -431,12 +436,12 @@ K_MI_PI:
andi s0, ~MI_INTR_PI
K_MI_DP:
KWriteString(KS_MI_DP)
lli t0, 0x0800
lui a1, MI_BASE
sw t0, MI_INIT_MODE(a1)
KWriteString(KS_MI_DP)
lw t0, K_HISTORY(k0)
ori t0, MI_INTR_DP
sw t0, K_HISTORY(k0)
@ -485,6 +490,14 @@ dw KCode20, KCode21, KCode22, KCode23
dw KCode24, KCode25, KCode26, KCode27
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"
if K_DEBUG {

View File

@ -117,8 +117,23 @@ MainLoop:
beqz t0,-
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
WriteString(S_VI_Wait)
lui a0, VI_BASE
-
lw t0, VI_V_CURRENT_LINE(a0)
@ -129,24 +144,27 @@ MainLoop:
WriteString(SNewFrame)
// swap buffers
lui a0, VI_BASE
beqz s1, SwitchToAlt
j Start3D
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:
ScreenNTSC(WIDTH, HEIGHT, VIDEO_MODE, VIDEO_C_IMAGE | UNCACHED)
jr ra
if WIDTH == 640 {
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
MainDumpWrite:
@ -164,6 +182,8 @@ MainDumpWrite:
addiu sp, 0x18
Die:
mfc0 t0, CP0_Status
mtc0 t0, CP0_Status
j Die
nop