#2158 - headspin - Thu Jan 30, 2003 9:20 am
At the moment I've set up a key to do a soft reset bios call, then I can simply apply the exithack and that key will return to Pogoshell instead.
Code: |
void softReset()
{
asm volatile("swi 0x00000"); // 0x00 Soft Reset
}
|
When you apply the exithack the rom won't work in Emulators anymore unless you use the "skip intro" feature.
Using the exithack works well for all goods and purposes, but I'd like to know a way I can put some actual code in my game to exit to Pogoshell. I've noticed some people have managed to do this without needing to skip intro in an emulator. Any ideas?
#2179 - zeuhl - Thu Jan 30, 2003 3:17 pm
I think I'd understand better if you explained what your exithack exactly consists in.
personnaly, I use code for visoly carts (available in the PogoShell sourcecode), to reset the cart's ROM relocation feature (ie, force the cart to boot the shell, not the program), and finally perform a swi 0. this works perfectly on both emulator (VBA) and real hardware.
I must admit I haven't tested the "return to PogoShell" feature on the emulator, using a real PogoShell formatted rom filesystem. I've only run my program in the emulator, and the special reset key combination only resets the emulator, that starts the program again.
#2184 - Herg - Thu Jan 30, 2003 6:15 pm
Here's the reset from my games:
Code: |
void doReset(void)
{
#define ROM_START (u16 *)(0x096B592E)
#define WRITE_LOC_1 (volatile u16 *)(0x987654*2+0x8000000)
#define WRITE_LOC_2 (volatile u16 *)(0x012345*2+0x8000000)
#define WRITE_LOC_3 (volatile u16 *)(0x007654*2+0x8000000)
#define WRITE_LOC_4 (volatile u16 *)(0x765400*2+0x8000000)
#define WRITE_LOC_5 (volatile u16 *)(0x013450*2+0x8000000)
u16 i;
// only try to reset like this if we booted from a ROM...
if(__boot_method == 0)
{
for(i=0;i<1;i++) *WRITE_LOC_1=0x5354;
for(i=0;i<500;i++) *WRITE_LOC_2=0x1234;
for(i=0;i<1;i++) *WRITE_LOC_2=0x5354;
for(i=0;i<500;i++) *WRITE_LOC_2=0x5678;
for(i=0;i<1;i++) *WRITE_LOC_1=0x5354;
for(i=0;i<1;i++) *WRITE_LOC_2=0x5354;
for(i=0;i<1;i++) *WRITE_LOC_4=0x5678;
for(i=0;i<1;i++) *WRITE_LOC_5=0x1234;
for(i=0;i<500;i++) *WRITE_LOC_2=0xabcd;
for(i=0;i<1;i++) *WRITE_LOC_1=0x5354;
*ROM_START=0;
__asm
{
swi 1
swi 0
}
}
}
|
Note: this is written for the ARM compiler rather than GCC.
#2186 - NEiM0D - Thu Jan 30, 2003 6:22 pm
eh, what is that?
I'm assuming that's flashcart specific code?
#2208 - tepples - Fri Jan 31, 2003 4:11 am
Yes, it's flash cart specific code, designed to work on any flash cart with the same hardware interface as Visoly flash carts.
After seeing Herg's reset and comparing it to visoly.s from PogoShell, I went and added reset support to TOD pre-Milestone 3. Here's the function that works in GCC:
Code: |
#define ROM_BANKSWITCH (volatile u16 *)(0x096B592E)
#define WRITE_LOC_1 (volatile u16 *)(0x987654*2+0x8000000)
#define WRITE_LOC_2 (volatile u16 *)(0x012345*2+0x8000000)
#define WRITE_LOC_3 (volatile u16 *)(0x007654*2+0x8000000)
#define WRITE_LOC_4 (volatile u16 *)(0x765400*2+0x8000000)
#define WRITE_LOC_5 (volatile u16 *)(0x013450*2+0x8000000)
void reset_gba(void)
{
unsigned int i;
INTENABLE = 0;
/* reset cart bankswitching */
for(i=0;i<1;i++) *WRITE_LOC_1=0x5354;
for(i=0;i<500;i++) *WRITE_LOC_2=0x1234;
for(i=0;i<1;i++) *WRITE_LOC_2=0x5354;
for(i=0;i<500;i++) *WRITE_LOC_2=0x5678;
for(i=0;i<1;i++) *WRITE_LOC_1=0x5354;
for(i=0;i<1;i++) *WRITE_LOC_2=0x5354;
for(i=0;i<1;i++) *WRITE_LOC_4=0x5678;
for(i=0;i<1;i++) *WRITE_LOC_5=0x1234;
for(i=0;i<500;i++) *WRITE_LOC_2=0xabcd;
for(i=0;i<1;i++) *WRITE_LOC_1=0x5354;
*ROM_BANKSWITCH=0;
/* reset GBA */
*(u16 *)0x03007ffa = 0; /* reset to ROM (= 0) rather than RAM (= 1) */
asm volatile(
"mov r0, #0xfc \n" /* clear everything other than RAM */
"swi 0x01 \n"
"swi 0x00 \n"
::: "r0", "r1", "r2", "r3");
}
|
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#2222 - zeuhl - Fri Jan 31, 2003 10:34 am
Hi, I have an assembler-version of this resetcode, which was included in PogoShell.
It works perfectly in IWRAM, as is.
I have tried to convert it to THUMB code, in order to be able to run it from ROM, in the aim to reduce the IWRAM usage. but it doesn't work anymore ! even the same ARM code doesn't work when run from ROM.
I guess the "for" loops are here for timing purposes, and as the execution time (from ROM) should not be the same as when run from IWRAM, this may be the reason of my problem.
Another possible reason (to me) is that it's not possible to change the ROM page relocation configuration, using code that is in ROM itself. But I thought the ROM relocation was only effective after a software reset.
Has somebody got a good explanation for this problem ?
#2228 - gb_feedback - Fri Jan 31, 2003 12:47 pm
Quote: |
I guess the "for" loops are here for timing purposes, and as the execution time (from ROM) should not be the same as when run from IWRAM, this may be the reason of my problem. |
I would have thought that the writes were a complex validation sequence to prevent accidentally writing to the cart unless this exact sequence is followed. In that case reading FROM the cart in between would no doubt interrupt the sequence of writes and invalidate it.
Just my theory...
#2229 - zeuhl - Fri Jan 31, 2003 12:52 pm
I haven't thought about that !
Obviously, running code from ROM causes ROM reads.
Anyway, a simple solution to this problem would be to copy the code from ROM to RAM when needed, then execute it.
Thanks for this explanation !
#2230 - FluBBa - Fri Jan 31, 2003 1:27 pm
If you try to switch the rom area that your code is running from it wont very good will it? Just like on the NES, most bankswitching code should run from RAM and not the ROM space that your switching in/out.
/FluBBa
#2242 - tepples - Fri Jan 31, 2003 3:17 pm
FluBBa wrote: |
If you try to switch the rom area that your code is running from it wont very good will it? |
I write mostly multiboot programs, and those run from EWRAM rather than ROM. Yes, if you're bankswitching on the GBA, you have to run your bankswitch code from EWRAM or IWRAM.
Quote: |
Just like on the NES, most bankswitching code should run from RAM and not the ROM space that your switching in/out. |
Only a few mappers on the NES (such as Rare's AOROM) actually bankswitched the whole cartridge at once. Most would bankswitch parts of the program area and leave the rest hardwired to the last bank of the cartridge.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#2353 - headspin - Sun Feb 02, 2003 11:28 am
Thanks for the help guys!
#2477 - Malefactor - Tue Feb 04, 2003 4:58 pm
hrm...
I tried both of those methods in my own program and both work great in visual boy, but both freeze my program on hardware with pogoshell 1.0
Update:
I just tried it with pogoshell 1.2 and same results
ExitHack just makes it go back to pogoshell immediatley upon loading.
Looks like my rom won't be having an 'Exit to boot menu' option...
Maybe I should leave it in though and call it 'Freeze'
_________________
[Images not permitted - Click here to view it]
#2486 - Herg - Tue Feb 04, 2003 9:01 pm
As mentioned above, whichever method you use, the code has to run from RAM rather than ROM. My games are small enough to fit entirely in EWRAM, so I copy the entire ROM there upon startup. For exithack, it works the same way, except only the exithack code is copied to RAM, and only at the point that the reset code needs to be executed.
#2502 - Malefactor - Wed Feb 05, 2003 1:44 am
I thought that that was what the problem was, but I was really hoping it wasn't...
Putting code in RAM is over my head because I don't understand crt0.s, linkerscipts or makefiles.
...I have one of those .s files, but I don't even know what its for, and I don't use a linkerscript or a makefile because I've never had the need of learning this stuff before...
Could you suggest some learning recourses?
_________________
[Images not permitted - Click here to view it]
#4131 - wtuck - Thu Mar 20, 2003 3:28 am
I was looking over the email trail and I thought I would try to copy the softReset from my ROM over to EWRAM I tried the following, but got compiler errors. Any one have a better Idea or code snipet?
Code: |
{
unsigned int* EWRAM = (unsigned int*)0x02000000;
typedef void (*entrypoint_t(void));
entrypoint_t entrypoint;
memcpy(EWRAM, &SoftReset, 100); // don't know how big it really is
entrypoint = (entrypoint_t) (0x2000000); //** THIS IS THE ERROR **
entrypoint();
}
|
#4138 - tepples - Thu Mar 20, 2003 5:03 pm
The following workaround will work for this specific case but won't work for cases where you have to go to EWRAM and return to ROM.
1. Make a multiboot program that just runs the exit code. (To make a multiboot program, make a global variable int __gba_multiboot;)
2. Copy it to EWRAM and run it (see my Multiboot Menu code for details).
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.
#5440 - Quirky - Sun Apr 27, 2003 9:08 pm
Sorry for resurrecting this old thread, but I've just incorporated tepples code into my project and thought this might be handy as it hasn't been mentioned yet. I used the old trick of:
Code: |
// this goes in the header file
#define CODE_IN_EWRAM __attribute__ ((section (".ewram"), long_call))
#define RESET_GBA __FarProcedure(reset_gba)
void reset_gba(void) CODE_IN_EWRAM;
// this goes in the .c file
CODE_IN_EWRAM void reset_gba(void)
{
/* rest of the code tepples gave..... */
}
// then in my game, when "Quit to PogoShell" is chosen...
void foo(void) {
REG_IME = 0x00; // disable interrupts
RESET_GBA;
}
|
Hope that helps someone! PogoShell is great, isn't it?[/code]