Our culture has advanced beyond all that you could possibly comprehend with one hundred percent of your brain.
It is currently Sun Jul 14, 2024 12:11 am

All times are UTC - 8 hours [ DST ]

Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Fri Jan 15, 2016 7:14 pm 
User avatar

Joined: Sun May 03, 2009 8:11 am
Posts: 17
Location: somewhere over the rainbow
Title: pwntendoer
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:

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

// 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)
    lui     r1, $A010
    lui     r2, $0004
    ori     r2, r2, $B000

    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:

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.

Reply with quote  
PostPosted: Sat Sep 30, 2017 11:26 pm 
Krew (Admin)
Krew (Admin)
User avatar

Joined: Sun Oct 01, 2006 9:26 pm
Posts: 3768
Title: All in a day's work.
Woah, old post is old! But this is a really interesting question. I have no idea if you ever found a solution, but I do have a little information that I can share.

Address BFC007FC is in PIF RAM (which is 64 bytes total). There's really no reason that the console should crash if you don't write the magic number 8 to the end of PIF RAM. (This is definitely some cargo-cult programming here.)

Anyway, I have disassembled all of the various CIC boot codes in the past, and they do a lot of arcane stuff with the various hardware registers, like the MIPS interface and RDRAM interface. AFAIK, this is the only code that ever touches that stuff, so it's hard to find documentation on any of it. I wouldn't be surprised if what you're missing is something along the lines of setting up the RDRAM refresh rates or something.

I have to return some video tapes.

Feed me a stray cat.

Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 8 hours [ DST ]

Who is online

Users browsing this forum: Google [Bot] and 1 guest

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group