Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rdram size testing #31

Open
bryanperris opened this issue Aug 25, 2019 · 17 comments
Open

Rdram size testing #31

bryanperris opened this issue Aug 25, 2019 · 17 comments

Comments

@bryanperris
Copy link

I have ran into the issue that the cart bootrom is writing 0 for osMemSize (vaddr A0000318) therefore breaking program execution, and don't know what is causing it. A test could check that the reported value is valid by being either 4 MB or 8 MB. Also the test could check the other fields of the structure "os_boot_config_t". Once I figure out what bug causes this issue, I can update about it here, then the test can check for that too.

@PeterLemon
Copy link
Owner

Hi bryanperris, I made a simple test for RDRAM size testing here: https://github.com/PeterLemon/N64/tree/master/RDRAMTest
I made this for a friend who made a special 8MB extended RDRAM (12MB total) but the N64 HW is limited to just 4MB extended RDRAM (8MB total), your idea sounds cool, let me know how you get on =D

@bryanperris
Copy link
Author

Thank you :), and I will keep investigating this bug, maybe your test will identify something right away.

@bryanperris
Copy link
Author

bryanperris commented Aug 25, 2019

So far the test seems to be stuck in an infinite loop, it has gone over $A0800000 and continued running till the emulator crashed.

Update 1: I forced rdram to check bounds, so this allows the test to work correctly now. I will now match all of the register values that the screenshot shows, I know some of those values are actually checked in the IPL cart bootrom.

Update 2: Here are the values I get back in the test, I noticed that mode is different compared to the ones that are just zero: https://imgur.com/a/uuJuv5f

Update 3: Fixing some of the initial values of the RDRAM registers has not affected osSizeMem, and mode is still the same value too. I did not think it would matter anyways since I know in emulators like pj64 do not bother setting them either. It seems only MI_VERSION is the most important one because the IPL does check it.

Update 4: Starting with RI_SELECT register to not equal to zero will cause the IPL to skip RDRAM configuration stuff, including writing osMemSize. It could be possible to use this as an advantage if the emulator provides the information instead. Also the 'defect' for RDRAM mode isn't there either.

Update 5: Undocumented RDRAM registers?

Example: RDRAM Delay is actually $A3F00008 but the address being used is $A3F80008

In your boot.asm source:
sw t1,MI_INIT_MODE(t4) // WORD[$A4300000] MI_INIT_MODE = $010F
lui t1,$1808 // T1 = $18080000
ori t1,$2838 // T1 = $18082838
sw t1,RDRAM_DELAY(t2) // WORD[$A3F80008] RDRAM_DELAY = $18082838
sw r0,RDRAM_REF_ROW(t2) // WORD[$A3F80014] RDRAM_REF_ROW = 0
lui t1,$8000 // T1 = $80000000
sw t1,RDRAM_DEVICE_ID(t2) // WORD[$A3F80004] RDRAM_DEVICE_ID = $80000000

In my trace log:
A40000E8 sw t1,$0000(t4)
>> Memory write access to CPU MIPS Interface Reg: Init Mode: 04300000
A40000EC lui t1,$1808
A40000F0 ori t1,t1,$2838
A40000F4 sw t1,$0008(t2)
>> Memory write access to RDRAM Reg: Unknown: 03F80008
A40000F8 sw zero,$0014(t2)
>> Memory write access to RDRAM Reg: Unknown: 03F80014
A40000FC lui t1,$8000
A4000100 sw t1,$0004(t2)
>> Memory write access to RDRAM Reg: Unknown: 03F80004

@bryanperris
Copy link
Author

bryanperris commented Aug 31, 2019

I was debugging the interpreter for Project64 and created a memory write breakpoint for address 0xA0000318, the only catch I got was value 0 (s6 = 0), even checked in RAM too, so same result as my emulator. I did not catch anything else (even 80000318) writing into that address. After helloworld runs and prints text to framebuffer, I do a memory search and actually find a value sitting in there. What a strange thing.

@project64 Do you know about the osMemSize field? I can't even find in PJ64's source of any high level routine that fills it in.

@project64
Copy link

rightly or wrongly pj64 does it on the first dma (CDMA::OnFirstDMA)

g_MMU->SW_PAddr(base + offset, rt);

now on the real n64, I can not remember how it is set, I assume from the pif rom booting, in which case not sure why i do it on the first dma and not on start.

@bryanperris
Copy link
Author

Thanks zilmar! In the IPL bootrom from the cartridge, if you look at boot.asm in this repo, you will find the comment osMemSize. When you debug that line of code, the register contains 0 but really it should be the detected RDRAM size from the boot logic.

Injecting a value from start will not work because it will be replaced by 0, so it must be why you did that in the first DMA which always is the one that copies the game code right into RDRAM so it makes sense. I can continue my work now by creating my own hack, but that was very helpful to know that its a known issue not just in my emulator.

If I could understand the rdram configuration routine better, a test rom could identify what is missing that causes that happen. I don't know what goes on for cen64, but without being able to debug it, I can't dump out differences in CPU states, but I know it boots from the real PIF rom, so I am sure its not using any hacks to make osMemSize to work.

@tj90241
Copy link

tj90241 commented Aug 31, 2019

cen64 takes a dumb approach and just and sets the memory byte before the console even starts executing the first stage of IPL.

  // Specify 8MiB RDRAM for 6102/6105 carts.
  if (si->ram[0x26] == 0x3F && si->ram[0x27] == 0x3F)
    bus_write_word(si->bus, 0x318, 0x800000, ~0U);

  else if (si->ram[0x26] == 0x91 && si->ram[0x27] == 0x3F)
    bus_write_word(si->bus, 0x3F0, 0x800000, ~0U);

@tj90241
Copy link

tj90241 commented Aug 31, 2019

(and yes, +1 to @project64 - the actual console probes the RAC during IPL and sets osMemSize at that time)

@bryanperris
Copy link
Author

@tj90241 So the hardware itself is just dumping this value right into memory just right after IPL writes a 0 to it?

@tj90241
Copy link

tj90241 commented Aug 31, 2019

Don't believe so. It should populate $s6 with a non-zero value before the write to that address.

@bryanperris
Copy link
Author

Interesting. From the assembly source, I was trying to figure out how s6 was being filled. I did find some logic that would write 1s into RDRAM, and then read it back, and that would loop many times but no idea on what was supposed to happen based on that. Thanks for the info, this sheds a lot more light.

@bryanperris
Copy link
Author

@PeterLemon I guess the test only needs to display the values from os config data, and that the screenshot shows they need to be filled in with.

@Nabile-Rahmani
Copy link
Contributor

Nabile-Rahmani commented Oct 21, 2019

I partly "reverse engineered" the IPL3 and I can tell you it's a horrible mess with like 3 copies of similar code paths and variables and I still can't figure out why the detection refuses to go through. I hunted down various docs to give names to magic values, but unfortunately there are holes.

Either way, only mupen64plus got it right, so I should check what they're doing right by comparing the runtime.
For some reason they XOR the RDRAMs' Mode register on reads or something.

I might share my abomination of a file full of scattered comments and naughty words.

@bryanperris
Copy link
Author

EE folk can do strange things with hardware. Sounds those routines are used for debugging purposes and to trigger the memory probe.

@Nabile-Rahmani
Copy link
Contributor

Problem is they hardcoded these paths for specific memory chips they ordered for the console, instead of using the DeviceType fields to compute the memory size.
On one hand their method ensures the memory is properly working, but on the other hand they have fallback values for non-NEC chips, it's kinda weird because the documentation for RDRAMs seems to have a generic way of handling the calibration anyways, so I don't know why Nintendo did things this way.

@Nabile-Rahmani
Copy link
Contributor

@bryanperris as promised, here it is in all its infamy: https://nabile.duckdns.org/Shared/IPL3.c

I spilled some more beans on the Discord64 server, if you'd like to join the discussion.

@bryanperris
Copy link
Author

Thanks for sharing this file

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants