TOS compliant reboot from C

C and PASCAL (or any other high-level languages) in here please

Moderators: exxos, simonsunnyboy, Mug UK, Zorro 2, Moderator Team

Badwolf
Atariator
Atariator
Posts: 26
Joined: Thu Mar 16, 2017 12:09 pm

TOS compliant reboot from C

Postby Badwolf » Thu May 25, 2017 1:18 pm

Hi all,

I'm a bit of a lurker, so apologies for the question out of the blue. I fancied doing a bit of Atari programming as I never really got around to it back in the 90s!

I've put together a AUTO program to set my Falcon's NVRAM, time/date etc. since the battery died, but it needs a reboot after changing the values and I can't for the life of me figure out how to do that legally in C (I'm using both Pure and GCC).

There's a Shutdown() command for MiNT, but I was hoping there was a TOS-legal way to do this. I assume it'd involve typdefing a function to a pointer location and calling it, but I've not had a lot of luck.

Would anyone be willing to point me in the right direction?

Thanks,

BW.

User avatar
Greenious
Hardware Guru
Hardware Guru
Posts: 1161
Joined: Sat Apr 24, 2004 5:39 pm
Location: Sweden

Re: TOS compliant reboot from C

Postby Greenious » Thu May 25, 2017 1:24 pm

Well, the easiest way is to grab the values off the reset vector, set ssp and jump to TOS...

Vector 0 (address $0) is SSP at boot.
Vector 1 (address $4) is TOS starting address.

That would basically do a warm reset.
Updated my guides as of june 28th, 2016. Check'em out and feedback!
viewtopic.php?t=5040

User avatar
Arne
Captain Atari
Captain Atari
Posts: 400
Joined: Thu Nov 01, 2007 10:01 am

Re: TOS compliant reboot from C

Postby Arne » Thu May 25, 2017 1:43 pm

Code: Select all

typedef void (*tFunction)(void);

static const      kWarmStartAddress_U32 = 0xE00000ul;
tFunction         JumpToTOS;
uint32_t         myJumpAddress_U32;

myJumpAddress_U32 = (*(volatile uint32_t*) (kWarmStartAddress_U32 + sizeof(uint32_t)));   /* slot #0 is occupied by SSP   */
JumpToTOS = (tFunction) myJumpAddress_U32;
JumpToTOS();
Image

Badwolf
Atariator
Atariator
Posts: 26
Joined: Thu Mar 16, 2017 12:09 pm

Re: TOS compliant reboot from C

Postby Badwolf » Thu May 25, 2017 2:08 pm

Thanks guys,

This is actually pretty close to what I've been trying so I'll give it another crack tonight with Arne's code when I can get my hands on a vanilla TOS machine.

Cheers! :-)

BW.

User avatar
simonsunnyboy
Moderator
Moderator
Posts: 4872
Joined: Wed Oct 23, 2002 4:36 pm
Location: Friedrichshafen, Germany
Contact:

Re: TOS compliant reboot from C

Postby simonsunnyboy » Thu May 25, 2017 5:38 pm

IIRC there is a BIOS compliant way without having to explicitly access system adresses.
use the BIOS call to read the exception vectors for the reset and then use Supexec() from XBIOS to actually call it.
Simon Sunnyboy/Paradize - http://paradize.atari.org/ - STOT: http://www.npoi.de/stot/

Stay cool, stay Atari!

1x2600jr, 1x1040STFm, 1x1040STE 4MB+TOS2.06+SatanDisk, 1xF030 14MB+FPU+NetUS-Bee

Jabber: simonsunnyboy@atari-jabber.org

ThorstenOtto
Captain Atari
Captain Atari
Posts: 178
Joined: Sun Aug 03, 2014 5:54 pm

Re: TOS compliant reboot from C

Postby ThorstenOtto » Fri May 26, 2017 2:48 am

There a 2 shortcomings in Arne's example: you have to use Supexec() to execute the function, otherwise it will just give you 8 bombs for a privilege violation. Also, you should use the value from address 0x4, which is a mirror of the ROM. You don't have to worry about the value at address 0x0 (the initial SSP), since it is also mirrored from the ROM and contains a branch instruction instead of something useful, so TOS ignores it and sets up a stack of its own.

Badwolf
Atariator
Atariator
Posts: 26
Joined: Thu Mar 16, 2017 12:09 pm

Re: TOS compliant reboot from C

Postby Badwolf » Fri May 26, 2017 10:02 am

Sheepish confession time: I wasn't calling Super() [or Supexec()] :oops:

Thanks all for the hints [esp. Simonsunnyboy who mentioned Supexec() which gave me the forehead-slap moment].

:cheers:

This is what I'm using now. I'm curious that if there is an even more BIOS-friendly way to do it, that'd be ace.

(This is the Pure C version, the MiNT/gcc version will probably use OSHEADER and int32_ts instead)

Code: Select all

#include <tos.h>

long get_os_start() {
        SYSHDR *sysbase;

        sysbase = *( (SYSHDR**)(0x4f2L) );
        return sysbase->os_start;
}

int main() {
        long os_start;

        os_start = Supexec( get_os_start );
        Supexec( os_start );
        return 255;
}


Social Media

     

Return to “C / PASCAL etc.”

Who is online

Users browsing this forum: No registered users and 2 guests