Page 2 of 3 FirstFirst 123 LastLast
Results 11 to 20 of 21
  1. #11
    EmuTalk Member Aphex123's Avatar
    Join Date
    Jul 2010
    Location
    Nottingham, England
    Posts
    12
    Quote Originally Posted by zoinkity View Post
    Incidentally, there's six different CRC checks within the 64DD's IPL. That thing's a real pain.
    ret = (A3 == 0xE1F9D977)
    ret &=(T2 == 0xDA29C069)
    ret &=(T3 == 0xBC587021)
    ret &=(S0 == 0x33E17503)
    ret &=(A2 == 0x96310A49)
    ret &=(T4 == 0x08E5FB8C)

    [edit]
    Just noticed you pointed out that PIF ROM executes between that jump to rdram and sets some static values.

    Incidentally, Nemu64's solution was to ignore all BGEZALs. Ran into a problem with custom code that used that particular op. Throw a breakpoint on it sometime after invalidating the CRC. It will walk right past it.

    Incidentally, you wouldn't have a list of all the static values that are set by the hardware? Very few are set by hardware, but among them the video mode/region value.

    For reference:
    05000000 is 64DD device registers
    06000000 is 64DD IPL
    08000000 is the typical address for FLASHram/SRAM

    Incidentally, GameShark/Pro Action Replays have a unique setup. It's apparently some 16bit memory system that uses an exploit for 32bit access. The upper halfwords are readable from 1EE00000 and the lower halfwords from 1EF00000. There are points where these are read and intermeshed via software.
    With some basic emulation of the PIF, I have managed to get most games to pass all CRC checks with no hacks (such as ignoring instructions etc) in my emulator. There's one little hack which I copied from MESS. The PIF ROM fiddles with the CIC status byte in the PIF RAM and presumably expects a response from the CIC chip to be reflected in that byte, perhaps. All that needs to be done though, is set the CIC status byte to 0x80 upon reads to 0x1fC007e4. I have a feeling that the CIC status is some kind of bitfield, but even after reading the N64's security chip patent, I still don't know the details.

    When referring to the static values set by the hardware, are you referring to the values that the PIF ROM writes to the hardware registers? Well, here's a dump from my emu of a portion of all the load/store word to hardware registers (up to the point where the execution is at the boot offset address specified in the cart header), as well as the DMA which are occurring. Just for your info, it's Zelda: Ocarina of Time. Bare in mind that not all of these are from the PIF ROM, the majority are from the cart ROM. Execution begins at the PIF ROM though.

    SP_STATUS_REG (0x04040010) read word
    SP_STATUS_REG (0x04040010) write word 0x0000000A
    RSP halt set
    SP_DMA_BUSY_REG (0x04040018) read word
    PI_STATUS_REG (0x04600010) write word 0x00000003
    VI_INTR_REG (0x0440000C) write word 0x000003FF
    VI_H_START_REG (0x04400024) write word 0x00000000
    VI_CURRENT_REG (0x04400010) write word 0x00000000
    AI_DRAM_ADDR_REG (0x04500000) write word 0x00000000
    AI_LEN_REG (0x04500004) write word 0x00000000
    SP_STATUS_REG (0x04040010) read word
    SI_STATUS_REG (0x04800018) read word
    PI_BSD_DOM1_LAT_REG (0x04600014) write word 0x000000FF
    PI_BSD_DOM1_PWD_REG (0x04600018) write word 0x000000FF
    PI_BSD_DOM1_PGS_REG (0x0460001C) write word 0x0000000F
    PI_BSD_DOM1_RLS_REG (0x04600020) write word 0x00000003
    PI_BSD_DOM1_LAT_REG (0x04600014) write word 0x00000040
    PI_BSD_DOM1_PWD_REG (0x04600018) write word 0x00803712
    PI_BSD_DOM1_PGS_REG (0x0460001C) write word 0x00008037
    PI_BSD_DOM1_RLS_REG (0x04600020) write word 0x00000803
    DPC_STATUS_REG (0x0410000C) read word
    SI_STATUS_REG (0x04800018) read word
    SI_STATUS_REG (0x04800018) read word
    SI_STATUS_REG (0x04800018) read word
    SI_STATUS_REG (0x04800018) read word
    RI_SELECT_REG (0x0470000C) read word
    RI_CONFIG_REG (0x04700004) write word 0x00000040
    RI_CURRENT_LOAD_REG (0x04700008) write word 0x00000000
    RI_SELECT_REG (0x0470000C) write word 0x00000014
    RI_MODE_REG (0x04700000) write word 0x00000000
    RI_MODE_REG (0x04700000) write word 0x0000000E
    MI_INIT_MODE_REG (0x04300000) write word 0x0000010F
    ??? (0x03F80008) write word 0x18082838
    ??? (0x03F80014) write word 0x00000000
    ??? (0x03F80004) write word 0x80000000
    MI_VERSION_REG (0x04300004) read word
    ??? (0x03F08004) write word 0x00000000
    RDRAM_MODE_REG (0x03F0000C) write word 0x46C0C0C0
    RDRAM_MODE_REG (0x03F0000C) write word 0xC6C0C0C0
    MI_INIT_MODE_REG (0x04300000) write word 0x00000000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    RDRAM_MODE_REG (0x03F0000C) write word 0x46C0C0C0
    RDRAM_MODE_REG (0x03F0000C) write word 0xC6C0C0C0
    MI_INIT_MODE_REG (0x04300000) write word 0x00000000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    RDRAM_MODE_REG (0x03F0000C) write word 0x46C0C0C0
    RDRAM_MODE_REG (0x03F0000C) write word 0xC6C0C0C0
    MI_INIT_MODE_REG (0x04300000) write word 0x00000000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    RDRAM_MODE_REG (0x03F0000C) write word 0x46C0C0C0
    RDRAM_MODE_REG (0x03F0000C) write word 0xC6C0C0C0
    MI_INIT_MODE_REG (0x04300000) write word 0x00000000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    MI_INIT_MODE_REG (0x04300000) write word 0x00002000
    RDRAM_MODE_REG (0x03F0000C) read word
    MI_INIT_MODE_REG (0x04300000) write word 0x00001000
    RDRAM_MODE_REG (0x03F0000C) write word 0xC6C0C0C0
    MI_INIT_MODE_REG (0x04300000) write word 0x00000000
    ??? (0x03F8000C) write word 0xC4000000
    ??? (0x03F80004) write word 0x80000000
    ??? (0x03F08004) write word 0x00000000
    RDRAM_MODE_REG (0x03F0000C) write word 0xC6804080
    MI_INIT_MODE_REG (0x04300000) write word 0x00000000
    RI_REFRESH_REG (0x04700010) write word 0x00063634
    RI_REFRESH_REG (0x04700010) read word
    SP_STATUS_REG (0x04040010) write word 0x000000CE
    RSP halt set
    SP_PC_REG (0x04080000) write word 0x00000000
    SP_STATUS_REG (0x04040010) write word 0x000000AD
    RSP halt cleared
    SP_DMA_FULL_REG (0x04040014) read word
    SP_MEM_ADDR_REG (0x04040000) write word 0x00001120
    SP_DRAM_ADDR_REG (0x04040004) write word 0x000001E8
    SP_RD_LEN_REG (0x04040008) write word 0x000001E8
    sp dma read: sp_mem_addr=0x1120, rdram_addr=0x1e8, len=0x1f0, count=0x0, skip=0x0
    PI_DRAM_ADDR_REG (0x04600000) write word 0x00000400
    SP_DMA_BUSY_REG (0x04040018) read word
    PI_STATUS_REG (0x04600010) read word
    SP_DMA_BUSY_REG (0x04040018) read word
    SP_SEMAPHORE_REG (0x0404001C) read word
    SP_DRAM_ADDR_REG (0x04040004) read word
    PI_CART_ADDR_REG (0x04600004) write word 0x10001000
    PI_WR_LEN_REG (0x0460000C) write word 0x000FFFFF
    pi dma write: cart_addr=0x10001000, rdram_addr=0x400, len=0x100000
    SP_MEM_ADDR_REG (0x04040000) write word 0x00000000
    SP_DRAM_ADDR_REG (0x04040004) write word 0x00000180
    SP_RD_LEN_REG (0x04040008) write word 0x00000000
    SP_SEMAPHORE_REG (0x0404001C) read word
    SP_SEMAPHORE_REG (0x0404001C) read word
    SP_SEMAPHORE_REG (0x0404001C) read word
    PI_STATUS_REG (0x04600010) read word
    SP_SEMAPHORE_REG (0x0404001C) read word
    SP_SEMAPHORE_REG (0x0404001C) read word
    SP_SEMAPHORE_REG (0x0404001C) write word 0x00000000
    SP_SEMAPHORE_REG (0x0404001C) read word
    SP_MEM_ADDR_REG (0x04040000) write word 0x00000000
    SP_DRAM_ADDR_REG (0x04040004) write word 0x00000400
    SP_RD_LEN_REG (0x04040008) write word 0x00000FFF
    sp dma read: sp_mem_addr=0x0, rdram_addr=0x400, len=0x1000, count=0x0, skip=0x0
    SP_DMA_BUSY_REG (0x04040018) read word
    SP_MEM_ADDR_REG (0x04040000) write word 0x0000B120
    SP_DRAM_ADDR_REG (0x04040004) write word 0xB12FB1F0
    SP_WR_LEN_REG (0x0404000C) write word 0xFE817000
    DPC_STATUS_REG (0x0410000C) write word 0x00000240
    SP_STATUS_REG (0x04040010) write word 0x00AAAAAE
    RSP halt set
    MI_INTR_MASK_REG (0x0430000C) write word 0x00000555
    SI_STATUS_REG (0x04800018) write word 0x00000000
    Unhandled write to SI mem address
    AI_STATUS_REG (0x0450000C) write word 0x00000000
    MI_INIT_MODE_REG (0x04300000) write word 0x00000800
    PI_STATUS_REG (0x04600010) write word 0x00000002
    Breakpoint detected @ 0x80000400
    Last edited by Aphex123; June 7th, 2012 at 17:03.

  2. #12
    EmuTalk Member
    Join Date
    Mar 2004
    Posts
    117
    To be more specific, at what point are the values between 80000300 and 80000318 written? They seem written by hardware after jumping from PIF to the bootstrap. The NMI buffer is software-managed though (cleared and filled after testing the flag by software).

    It should be some kind of bitfield, concidering that's the same register used to trigger PIF command reads. I had always assumed that final byte in PIFram was just like the other register fields, where setting status immediately sets the interrupt, akin to setting a read or write length for DMA/PI/VI/etc. or setting status in virtually any of them. It is particularly obscure. We probably have a better reference for the RDP than the PIF.

  3. #13
    EmuTalk Member
    Join Date
    Jun 2012
    Posts
    2
    Quote Originally Posted by zoinkity View Post
    To be more specific, at what point are the values between 80000300 and 80000318 written? They seem written by hardware after jumping from PIF to the bootstrap. The NMI buffer is software-managed though (cleared and filled after testing the flag by software).
    Values at 0x80000300 are layed out this way :
    typedef struct {
    u32_t tv_type; (1=NTSC, 0=PAL,2=MPAL)
    u32_t rom_type; (0=GamePack,1=DD)
    u32_t rom_base; (0xb0000000 for GamePack, 0xa6000000 for DD)
    u32_t reset_type; (0=ColdReset, 1=NMI)
    u32_t cic_id; (CIC6103 writes 6103, CIC6106 writes 6104, CIC6105 writes 6105, CIC6102 & CIC6101 do not write anything)
    u32_t version; (???)
    u32_t mem_size; (specify the amount of detected rdram 4Mo or 8Mo usually)
    u8_t app_nmi_buffer[64];
    } os_boot_config_t;

    They are written at the end of IPL3 just before clearing IMEM & DMEM and jumping to game entrypoint, except for 0x80000318 (mem_size)
    which is written earlier at the end of rdram initialization (but still in IPL3).

    However most of what is written directly comes from registers (s3..s7) initialized during IPL2 (part of PIF BootROM executed in RSP IMEM) :
    s3 : rom_type
    s4 : tv_type
    s5 : reset_type
    s6 : SEED (not related to os_boot_config, but still a very interesting value...)
    s7 : version

    IPL2 determines these values by reading at 0x1fc007e4 (PIF+0x24) and parse the value returned.
    tv_type is an exception, because it is hardcoded in PIF BootROM.

    For cic_id, different CIC types write different values :
    CIC6101 & CIC6102 do not write anything
    CIC6103 writes 6103
    CIC6105 writes 6105
    CIC6106 writes 6104 (yes it is 6104 not 6106)

  4. #14
    EmuTalk Member Aphex123's Avatar
    Join Date
    Jul 2010
    Location
    Nottingham, England
    Posts
    12
    Thanks bobby.smiles32, that's very useful info.

  5. #15
    EmuTalk Member
    Join Date
    Mar 2004
    Posts
    117
    Thank you thank you!



    • Advertising

      advertising
      EmuTalk.net
      has no influence
      on the ads that
      are displayed
        
       

  6. #16
    EmuTalk Member
    Join Date
    Aug 2012
    Location
    The Land of Enchantment
    Posts
    5
    Sorry to bump the thread, but I did have a question related to an earlier post.

    Quote Originally Posted by Aphex123 View Post
    Of course, this is all very low level information that most N64 programmers wouldn't need to know. As far as I'm aware, the libraries would convert vertex information (provided by the programmers) to edge/slope format for the RDP to process. The conversion between vertex values and edge coefficients is fairly straight forward, but if somebody wants to know, i'll be happy to detail what i know of it.
    Low-level info you don't need to know IF you're using the leaked Nintendo or PsyQ SDK to write your N64 programs. I use libdragon, a completely Nintendo-code free development kit for programming the N64. It has support for the Rectangle RDP commands, but not the Triangle RDP commands. I was working on my own "microcode" (silly name for a pcode interpreter if you ask me) and while a mixer is dead simple, I wanted to add in handling vertexes and the like, as well as adding support for triangle commands. While I could scrape enough brain cells together to figure out how to calculate the values the triangle command needs, I noticed your post here and decided to ask... yes, I would very much like to know about the conversion between vertex values and edge coefficients.

    Thanks.

  7. #17
    EmuTalk Member Aphex123's Avatar
    Join Date
    Jul 2010
    Location
    Nottingham, England
    Posts
    12
    Quote Originally Posted by Chilly Willy View Post
    Sorry to bump the thread, but I did have a question related to an earlier post.



    Low-level info you don't need to know IF you're using the leaked Nintendo or PsyQ SDK to write your N64 programs. I use libdragon, a completely Nintendo-code free development kit for programming the N64. It has support for the Rectangle RDP commands, but not the Triangle RDP commands. I was working on my own "microcode" (silly name for a pcode interpreter if you ask me) and while a mixer is dead simple, I wanted to add in handling vertexes and the like, as well as adding support for triangle commands. While I could scrape enough brain cells together to figure out how to calculate the values the triangle command needs, I noticed your post here and decided to ask... yes, I would very much like to know about the conversion between vertex values and edge coefficients.

    Thanks.
    Okay, sure. Right now, I'll just talk about converting the x/y coordinates to edge coefficients. The texture, Z and shading values are a little complex and I have yet to fully figure out an algorithm for converting to the RDP coefficient format. However, once you get the basic idea, it shouldn't be too much of a stretch. See sheet 73,74 of patent 6,239,810 for details on the RDP edge coefficients. I assume that you understand how the edge coefficients work, none of this will really make sense unless you understand how the triangles are rendered from the edge coeficcients (see my earlier posts).

    Let's say you have three typical vertices (i'll represent this in C), each with an X and Y coordinate:

    Vertex2f v[3] = { {47, 126}, {200, 20}, {300, 260} };

    The first thing we do is sort the vertices by their Y coordinate, low to high. Just doing this, we already have our "Y coordinate of high minor, middle minor and low major edge". The X major (XH) and X middle (XM) edge coefficients can either be the same or have one pixel difference (to make a convincing triangle). Either way, XH and XM will be derived from the X value of the vertex with the lowest Y value (v[0] in our case, since we sorted them). X low (XL) will be the X value of the vertex with the middle Y value (v[1] in our case). The RDP also needs to know which direction the triangle is facing (which side XL is on). The triangle is a left major triangle if (v[2].x < v[1].x), else it's a right major triangle. If you take a look at the diagram on sheet 74, you can see why this is true.

    Now that we have all the edge values, we need to calculate the inverse slopes, DxHDy, DxMDy and DxLDy. The inverse slopes effectively tell the RDP how to interpolate the spans of the triangle which are being rendered. That is, for each scanline, the RDP will increase each edge value by it's corresponding inverse slope. To calculate an inverse slope of two XY points, you use the following formula (remembering to use signed arithmetic).

    (x1 - x0) / (y1 - y0)

    So, given that the vertices are all sorted in Y order, it's quite trivial to calculate each inverse slope.

    e.g. DxHDy = (v[2].x - v[0]) / (v[2] - v[0])
    etc...

    Now, given all that, we have calculated the values for all needed edge coefficients. However, the RDP expects these values in a specific format. For example, all X edges and inverse slopes are expect to be in fixed 16.16 format (16 bits integer, 16 bits fractional). Instead of telling you how to convert these values, I will just post this snippet of code that I was in the process of writing. I (for whatever reason) never finished it, however, it does take 3 (C float) vertices and outputs a binary RDP triangle command (although, only flat shaded triangles). Feel free to use this meager code in anyway you want.

    The next step I was trying to achieve was to calculate the coefficients for Goraud shaded, textured or Z buffered triangles. However, I never quite understood one of the RDP's coefficient values, the "change in <whatever value> along the edge". This is present in the shade, texture and Z coefficients. If anyone can shed a light on this, it would be helpful. I did at one point ask the original architect of the RDP (Tim Van Hook) what this value was, but I don't think he could really recall.
    Last edited by Aphex123; September 17th, 2012 at 00:49.

  8. #18
    EmuTalk Member
    Join Date
    Aug 2012
    Location
    The Land of Enchantment
    Posts
    5
    Quote Originally Posted by Aphex123 View Post
    Okay, sure. Right now, I'll just talk about converting the x/y coordinates to edge coefficients. The texture, Z and shading values are a little complex and I have yet to fully figure out an algorithm for converting to the RDP coefficient format. However, once you get the basic idea, it shouldn't be too much of a stretch. See sheet 73,74 of patent 6,239,810 for details on the RDP edge coefficients. I assume that you understand how the edge coefficients work, none of this will really make sense unless you understand how the triangles are rendered from the edge coeficcients (see my earlier posts).
    Yes, your earlier posts were most enlightening. I hadn't had much exposure to edge-walkers before.


    Let's say you have three typical vertices (i'll represent this in C), each with an X and Y coordinate:

    Vertex2f v[3] = { {47, 126}, {200, 20}, {300, 260} };

    The first thing we do is sort the vertices by their Y coordinate, low to high. Just doing this, we already have our "Y coordinate of high minor, middle minor and low major edge". The X major (XH) and X middle (XM) edge coefficients can either be the same or have one pixel difference (to make a convincing triangle). Either way, XH and XM will be derived from the X value of the vertex with the lowest Y value (v[0] in our case, since we sorted them). X low (XL) will be the X value of the vertex with the middle Y value (v[1] in our case). The RDP also needs to know which direction the triangle is facing (which side XL is on). The triangle is a left major triangle if (v[2].x < v[1].x), else it's a right major triangle. If you take a look at the diagram on sheet 74, you can see why this is true.

    Now that we have all the edge values, we need to calculate the inverse slopes, DxHDy, DxMDy and DxLDy. The inverse slopes effectively tell the RDP how to interpolate the spans of the triangle which are being rendered. That is, for each scanline, the RDP will increase each edge value by it's corresponding inverse slope. To calculate an inverse slope of two XY points, you use the following formula (remembering to use signed arithmetic).

    (x1 - x0) / (y1 - y0)

    So, given that the vertices are all sorted in Y order, it's quite trivial to calculate each inverse slope.

    e.g. DxHDy = (v[2].x - v[0]) / (v[2] - v[0])
    etc...

    Now, given all that, we have calculated the values for all needed edge coefficients. However, the RDP expects these values in a specific format. For example, all X edges and inverse slopes are expect to be in fixed 16.16 format (16 bits integer, 16 bits fractional). Instead of telling you how to convert these values, I will just post this snippet of code that I was in the process of writing. I (for whatever reason) never finished it, however, it does take 3 (C float) vertices and outputs a binary RDP triangle command (although, only flat shaded triangles). Feel free to use this meager code in anyway you want.
    Thanks. That will be helpful. I should be able to put that right into a sample app using libdragon to check it out.


    The next step I was trying to achieve was to calculate the coefficients for Goraud shaded, textured or Z buffered triangles. However, I never quite understood one of the RDP's coefficient values, the "change in <whatever value> along the edge". This is present in the shade, texture and Z coefficients. If anyone can shed a light on this, it would be helpful. I did at one point ask the original architect of the RDP (Tim Van Hook) what this value was, but I don't think he could really recall.
    If I figure any of that out, I'll be sure to post.

  9. #19
    EmuTalk Member Aphex123's Avatar
    Join Date
    Jul 2010
    Location
    Nottingham, England
    Posts
    12
    Thanks. That will be helpful. I should be able to put that right into a sample app using libdragon to check it out.
    I was originally tempted to contact the creator or libdragon, since I noticed that it had no support for rendering triangles. I would love to see an unofficial library doing all the things the official ones can, and in my opinion, it's certainly not out of reach. Even when it comes to the RSP, there is documentation/code detailing the inner workings and architecture.

    Anyway, I would love to see some home-brew triangles being rendered on the real N64. Rectangles are boring. Good luck.
    Last edited by Aphex123; September 17th, 2012 at 04:06.

  10. #20
    I Am The Stig Martin's Avatar
    Join Date
    Nov 2001
    Location
    Malmö
    Posts
    3,830
    Great thread, keep the info coming


    The Emulation64 Network offers you free hosting!
    Click here for requirements and contact info.

Page 2 of 3 FirstFirst 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •