Hello all,
For perverse reasons, I'm interested in squeezing small graphical effects into the boot code of an N64 rom. The code I have so far sets up the frame buffer and writes some garbage to it producing a pink screen. It works perfectly on Project64 2.2, but when I attempt to run it on real hardware, I see the pink screen for about 2 seconds and then it goes black. I have used extensively code from Peter Lemon's N64 github repo. I am assembling with bass. Here is my source code:
Code:
arch n64.cpu
endian msb
output "@party2016.n64", create
fill 1052672
include "N64.INC"
include "N64_GFX.INC"
origin $00000000
base $A4000000
// N64 Header (64 bytes)
db $80 // Initial PI_BSB_DOM1_LAT_REG Value
db $37 // Initial PI_BSB_DOM1_PGS_REG Value
db $12 // Initial PI_BSB_DOM1_PWD_REG Value
db $40 // Initial PI_BSB_DOM1_PGS_REG Value
dd $0000000F // Initial clock rate
dd BootcodeStart // Boot address (normally this is in RDRAM)
dd $00001444 // Release offset
db "CRC1" // CRC1
db "CRC2" // CRC2
dd $00000000 // Unknown
dd $00000000 // Unknown
db "@PARTY2016 " // Program title (20 bytes)
dd $00000000 // Unknown
db $00 // Unknown
db $00 // Unknown
db $00 // Unknown
db $00 // Developer ID code "N" = Nintendo
dw $0000 // Cartridge ID code
db $00 // Country code
db $00 // Unused
BootcodeStart:
// Write 8 to $BFC007FC. This is supposed to stop the N64 from freezing after a
// couple of seconds. Don't ask me why, I just read it on the internet.
li r1, 8
lui r2, $BFC0
sw r1, $07FC (r2)
// Initialize the screen buffer
ScreenNTSC(320, 240, BPP32, $A0100000)
PaintScreen:
lui r1, $A010
lui r2, $0004
ori r2, r2, $B000
DrawLoop:
sw r1, $0000 (r1)
bne r1, r2, DrawLoop
addiu r1, r1, 4
j PaintScreen
ScreenNTSC just initializes the screen buffer. It is a macro that is defined in the following way:
Code:
macro ScreenNTSC(width,height, status, origin) {
lui a0,VI_BASE // A0 = VI Base Register ($A4400000)
li t0,{status} // T0 = Status/Control
sw t0,VI_STATUS(a0) // Store Status/Control To VI Status Register ($A4400000)
la t0,{origin} // T0 = Origin (Frame Buffer Origin In Bytes)
sw t0,VI_ORIGIN(a0) // Store Origin To VI Origin Register ($A4400004)
lli t0,{width} // T0 = Width (Frame Buffer Line Width In Pixels)
sw t0,VI_WIDTH(a0) // Store Width To VI Width Register ($A4400008)
lli t0,$200 // T0 = Vertical Interrupt (Interrupt When Current Half-Line $200)
sw t0,VI_V_INTR(a0) // Store Vertical Interrupt To VI Interrupt Register ($A440000C)
lli t0,0 // T0 = Current Vertical Line (Current Half-Line, Sampled Once Per Line = 0)
sw t0,VI_V_CURRENT_LINE(a0) // Store Current Vertical Line To VI Current Register ($A4400010)
li t0,$3E52239 // T0 = Video Timing (Start Of Color Burst In Pixels from H-Sync = 3, Vertical Sync Width In Half Lines = 229, Color Burst Width In Pixels = 34, Horizontal Sync Width In Pixels = 57)
sw t0,VI_TIMING(a0) // Store Video Timing To VI Burst Register ($A4400014)
lli t0,$20D // T0 = Vertical Sync (Number Of Half-Lines Per Field = 525)
sw t0,VI_V_SYNC(a0) // Store Vertical Sync To VI V Sync Register ($A4400018)
lli t0,$C15 // T0 = Horizontal Sync (5-bit Leap Pattern Used For PAL only = 0, Total Duration Of A Line In 1/4 Pixel = 3093)
sw t0,VI_H_SYNC(a0) // Store Horizontal Sync To VI H Sync Register ($A440001C)
li t0,$C150C15 // T0 = Horizontal Sync Leap (Identical To H Sync = 3093, Identical To H Sync = 3093)
sw t0,VI_H_SYNC_LEAP(a0) // Store Horizontal Sync Leap To VI Leap Register ($A4400020)
li t0,$6C02EC // T0 = Horizontal Video (Start Of Active Video In Screen Pixels = 108, End Of Active Video In Screen Pixels = 748)
sw t0,VI_H_VIDEO(a0) // Store Horizontal Video To VI H Start Register ($A4400024)
li t0,$2501FF // T0 = Vertical Video (Start Of Active Video In Screen Half-Lines = 37, End Of Active Video In Screen Half-Lines = 511)
sw t0,VI_V_VIDEO(a0) // Store Vertical Video To VI V Start Register ($A4400028)
li t0,$E0204 // T0 = Vertical Burst (Start Of Color Burst Enable In Half-Lines = 14, End Of Color Burst Enable In Half-Lines = 516)
sw t0,VI_V_BURST(a0) // Store Vertical Burst To VI V Burst Register ($A440002C)
lli t0,($100*({width}/160)) // T0 = X-Scale (Horizontal Subpixel Offset In 2.10 Format = 0, 1/Horizontal Scale Up Factor In 2.10 Format)
sw t0,VI_X_SCALE(a0) // Store X-Scale To VI X Scale Register ($A4400030)
lli t0,($100*({height}/60)) // T0 = Y-Scale (Vertical Subpixel Offset In 2.10 Format = 0, 1/Vertical Scale Up Factor In 2.10 Format)
sw t0,VI_Y_SCALE(a0) // Store Y-Scale To VI Y Scale Register ($A4400034)
}
Are there any N64 hardware gurus who know why this might be freezing after a couple of seconds? I'm sure there is something that the bootcode does which prevents this from happening, but if anyone knows what it is before I spend the rest of the week picking apart the bootcode disassembly I have, it would be immensely helpful.