DCEmulation

dreamcast development • homebrew software • hardware hacking • indie games • emulators • and more!
Back to main site
It is currently Sun Nov 23, 2014 11:41 am

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Wed Aug 08, 2012 9:00 am 
Offline
DCEmu Newbie
DCEmu Newbie

Joined: Wed Aug 08, 2012 8:16 am
Posts: 8
Hi,

This is my second post here and I thought I'd introduce myself a bit...

I'm the same OzOnE from the ASSEMblergames forum and I'm still working on bypassing the GD drive and loading from CF / HDD / SD instead.
I hope it's OK to post a link to the forum? Just so people can catch up on the last few pages...

http://www.assemblergames.com/forums/sh ... roup/page8

I'm famous for typing / talking a lot, so there are now two fairly big threads on AG forums about my efforts with the FPGA board.
I will likely repeat some stuff below, but I thought I'd tell the basic story...

Basically, after I got stuck with the FPGA project, it was suggested (by @cybdyn and others) to try bypassing the BIOS GD syscalls themselves...

This lead to the interesting combination of a Dreamcast with an IDE cable soldered directly to the G1 port test pads and a cheap CF adapter hanging off the other end. :wink:

Well, I've never coded for the DC before, and I'm still learning C/C++. I found the DC DEV R4 ISO and installed it fine, then compiled some KOS examples (eventually) and managed to send commands directly to the hardware regs and talk to the CF card...

I've got it to a point where I can redirect the basic GD DMA syscall and force it to read the data from CF card instead.
The good thing is that it works with the CF card set to Slave, so you don't need to unplug the GDD (and GD disks still boot fine with the stock BIOS).

I think it's important to note that it is NOT YET BOOTING from CF / HDD! 8-)

So, I was hoping to get some help here with the programming side of things now that it's turned into a DC coding effort.

atm, I have a small debug app which can read sectors from a real GD disk via PIO (DMA not working yet), I can then enable GD syscall redirection (Y button) to read from ATA (CF card). DMA is working fine from CF card (which is what the stock BIOS syscall uses).

I've also managed to spoof the basic 3-track GD TOC and can even WRITE back to the CF card (although it freezes the DC afterwards).

What I'm stuck with is how to actually start the stock boot process? I'm using the Dreamshell "Bootloader with BIOS" flash, which I understand is based on BIOS version "1_004_01.bios".

I need to be able to jump directly to the boot function in the stock part of the BIOS, but only AFTER it has written it's GD syscall vector to 0x8c0000bc.

I'm hoping the stock BIOS will at least attempt to read IP.BIN after it finds my TOC?
The problem is that I'm using the KOS libraries, so my .bin file is big (~270KB).

(probably best to read my post #159 on the AG forum for the other KOS issues.)

Anyway, I think you get the idea. Please help! :|

Cheers,
OzOnE.


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 11:49 am 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4303
If your target game works anything like PSO, you should just be able to jump to the first stage of the IP.BIN bootloader after resetting a few registers to what the BIOS sets them to.

In my PSO Patcher, all I do is this:
Code:
_clear_and_load:
    ! Disable interrupts
    mov.l       .no_ints_sr, r0
    ldc         r0, sr
    ! Clear out the loader
    mov.l       .loader_base, r0
    mov.l       .loader_end, r1
    mov         #0, r2
.clear_loop:
    mov.l       r2, @r0
    add         #4, r0
    cmp/eq      r0, r1
    bf          .clear_loop
    ! Clean up the various registers...
    ldc         r4, sr
    ldc         r5, vbr
    lds         r6, fpscr
    mov         r7, r15
    ! Jump to IP.BIN
    mov.l       .bin_base, r0
    jmp         @r0
    nop
    .balign     4
.no_ints_sr:
    .long       0x500000F0
.loader_base:
    .long       0xACD00000
.loader_end:
    .long       0xAD000000
.bin_base:
    ! This is actually the first stage of the IP.BIN file.
    .long       0xAC00B800


That said, some games do refuse to work with this rather simple setup. There are a few other avenues I've tried that have worked with some games, but I don't actually have the code handy for any of them. Full file in question (with a few other fun things) available here.

That said, moving this topic off to a more appropriate forum for it...


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 1:22 pm 
Offline
DCEmu Newbie
DCEmu Newbie

Joined: Wed Aug 08, 2012 8:16 am
Posts: 8
That's great, thanks! I'll give it a try.

I'm assuming 0xAC00B800 points to Bootstrap1?

I'm a bit confused about cached / virtual addressing - I can see your IP.BIN and "gd_vector_addr" starts with 0x8C, so are the 0xAC address ranges in the patcher assembly just a mirror?

How do you know or decide on which address range to use (p1 / p2 etc?) Is it basically the same access, just cached?

Very clever stuff. Is the code always resident in memory while PSO is running or does it only need to patch once?
I'll try to get my head around this code. Very interesting.


Thanks again,
OzOnE.
P.S. Sorry, I thought I posted this in a Programming section?


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 1:29 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4303
OzOnE wrote:
I'm assuming 0xAC00B800 points to Bootstrap1?
Yep. That is where it would get loaded by the BIOS, and where my program loads it (in the C code elsewhere). IP.BIN should always be from 0xAC008000 through 0xAC00FFFF (32KiB).

Quote:
I'm a bit confused about cached / virtual addressing - I can see your IP.BIN and "gd_vector_addr" starts with 0x8C, so are the 0xAC address ranges in the patcher assembly just a mirror?

How do you know or decide on which address range to use (p1 / p2 etc?) Is it basically the same access, just cached?
The 0x8C range is cached. The 0xAC range is not.

Quote:
Very clever stuff. Is the code always resident in memory while PSO is running or does it only need to patch once?
Its always resident, in case the user goes into the in-game web browser, which would overwrite my patches when it returns back to the game.

Quote:
P.S. Sorry, I thought I posted this in a Programming section?
Nah, but its all good. Just tread a bit lightly with this topic, as anything related to copying commercial games is frowned upon here. :wink:


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 1:36 pm 
Offline
DCEmu Newbie
DCEmu Newbie

Joined: Wed Aug 08, 2012 8:16 am
Posts: 8
Ahh, I see.

Yep, well it's really for running unscrambled bins and using the extra space in GDI's for homebrew. :wink:

Another quick question why I think of it...

I'm defining the h/w regs like this...

uint32 *SB_GDSTAR = (uint32*)0xa05f7404; // GD_DMA Start Address - address in RAM which DMA will start writing to.
uint32 *SB_GDLEN = (uint32*)0xa05f7408; // GD-DMA Length - number of bytes to transfer, in unit of 0x20 (32) bytes?
uint32 *SB_GDDIR = (uint32*)0xa05f740c; // GD-DMA Direction reg. 0 == "DC to GD-ROM"??. 1 == "GD-ROM to DC".
uint32 *SB_GDEN = (uint32*)0xa05f7414; // GD-DMA Enable reg.
uint32 *SB_GDST = (uint32*)0xa05f7418; // GD-DMA Start / Status reg.

And most stuff works until I try to wait for a DMA to finish...

*SB_GDST = 0x00000001; // Start the DMA !
// while ((*SB_GDST & 0x01) == 1); // Wait until DMA transfer finished (polling for now).

It just gets stuck waiting for the reg to clear to zero (supposed to be a DMA status reg when read)?
So, I have to comment it out and add a small delay instead. I don't think it's a very reliable way of doing it.

Is it the "correct" thing to do to mask the uint32 with 0x01 to test bit 0?

I tried this way too...

// while (*SB_GDLEND != *SB_GDLEN); // Wait until all bytes have been transferred.

...but still freezes?


OzOnE.


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 3:27 pm 
Offline
DCEmu Newbie
DCEmu Newbie

Joined: Wed Aug 08, 2012 8:16 am
Posts: 8
OK, I've added some of your asm code to the debug app and it now jumps and shows the license screen!

Unfortunately, it just reboots after that point. It's very likely that I'll need to add some more stuff to the redir code before it'll work.

I only DMA'd 16 gd-sectors (32KB) from the CF into RAM before doing the jump.
Does Bootstrap1 assume that 1ST_READ.BIN has already been loaded after IP.BIN?

Oh, scrub that. I should have done a bit of searching first...

http://mc.pp.se/dc/ip.bin.html

I'll try to load 1ST_READ.BIN before the jump. :oops:

OzOnE.


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 3:44 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4303
OzOnE wrote:
And most stuff works until I try to wait for a DMA to finish...

*SB_GDST = 0x00000001; // Start the DMA !
// while ((*SB_GDST & 0x01) == 1); // Wait until DMA transfer finished (polling for now).

It just gets stuck waiting for the reg to clear to zero (supposed to be a DMA status reg when read)?
So, I have to comment it out and add a small delay instead. I don't think it's a very reliable way of doing it.

Is it the "correct" thing to do to mask the uint32 with 0x01 to test bit 0?

I tried this way too...

// while (*SB_GDLEND != *SB_GDLEN); // Wait until all bytes have been transferred.
I've done a bit with GD-ROM DMA in the past, but I never tried to wait for it in that way. I always just used the interrupt that fires at the end of the DMA to know when things were done.


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 4:00 pm 
Offline
DCEmu Newbie
DCEmu Newbie

Joined: Wed Aug 08, 2012 8:16 am
Posts: 8
I don't know how to redirect the int routine vector since I'm guessing it's still pointing to the stock BIOS one?
I need the stock routines to stay intact when doing the jump.

I just tried loading 1ST_READ.BIN (210 gd sectors), but it just freezes?

I pretty sure it's because it's overwriting the debug app in RAM. The default makefile in KOS sets the linker / text section to this...

-Ttext=0x8c010000

How do you go about compiling so you can load / run the debug app higher into memory?
I couldn't see anything different in your Makefile - does anything need to be changed at compile time to relocate an app?

I'm loading it via SD under DS. The app is run by doing this in the XML...

onclick="console:exec -b -f /sd/gd.bin -a 0x8c010000"

Do these two addresses need to match, or should I be able to load and exec it from a different location?

Sorry for all the questions.

OzOnE.


Top
 Profile  
 
PostPosted: Wed Aug 08, 2012 4:37 pm 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4303
You'll need to have the linker link your program for a different starting address, either by using a linker script, or specifying a different starting offset for the text segment. That said, I suspect you're using a rather old version of KOS (or a rather old version of GCC), since KOS has been using a linker script for a while for what it does.

That said, I've never used DreamShell, but I would assume you'll have to change the address there as well. You could also create a small loader stub, like I do for my PSO patcher to copy the binary over to the appropriate address. If you were to ever try to boot this from a CD, you'd need to do that anyway, since the BIOS will always load your binary at 0xAC010000/0x8C010000.


Top
 Profile  
 
PostPosted: Thu Aug 09, 2012 8:39 am 
Offline
DCEmu Newbie
DCEmu Newbie

Joined: Wed Aug 08, 2012 8:16 am
Posts: 8
OK, I've recompiled the app for 0x8CD00000 and it's loading OK. I've tried loading in IP.BIN, then grabbing 1ST_READ.BIN to load directly after it (to 0x8C010000).

I've also tried flushing the cache over 0x8c0000bc, IP.BIN and 1ST_READ.BIN, but no boot (just the license screen, then it reboots).

I'm not doing the "clear_and_load" part though - the app needs to stay in RAM because I don't have the syscall redirects as a separate stub yet.

I think a stub with just the ATA routines in would be fairly big, so I'm just testing to see if 1ST_READ.BIN is even attempting to read from the GD syscall redir routines in the app itself - I don't think it reads anything before it reboots though? I very much doubt it's overwriting the app in RAM, it might be detecting it though?

Do you know of any (cheap) ways to debug directly on the DC itself? I'm looking into using UrJTAG or something to set breakpoints on the SH4.

I'm still looking through your code - I see that when "patches_enabled==0", any GD syscall just calls the stock syscall routine...

Then, if "patches_enabled==1", any GD syscall will run your trigger pattern check - if the trig pattern matches, patch the PSO bin then pass back to the stock GD syscall.

What I'm trying to do is "emulate" the GD syscalls completely and DMA from CF / HDD instead of GDD.
I'm fairly confident the data is being DMA'd into memory properly, but I can't debug what happens after I jump to Bootstrap1?

How would you normally go about debugging something like this? Would the serial port still work in many cases?

Regards,
OzOnE.


Top
 Profile  
 
PostPosted: Thu Aug 09, 2012 9:01 am 
Offline
The Crabby Overlord
The Crabby Overlord
User avatar

Joined: Mon May 27, 2002 9:31 am
Posts: 4303
Well, keep in mind that the game may be overwriting the memory you're using for your stub. You need to find a convenient place where the game won't overwrite the code.

With my PSO patcher, the "stub" sits in a very small area of memory (768 bytes) where the game doesn't write anything or read anything. I doubt that would be enough space to do anything major with the code, since that only actually gives you 384 instructions (assuming no data laying around).

Most of my PSO patcher gets cleared out of memory by that clear_and_load function, with the exception of the very small stub that gets left behind (just the stuff in that assembly file, to be specific). That is actually linked to overwrite the first 768 bytes of IP.BIN, since the game doesn't seem to use them at all.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: Yahoo [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