Page 1 of 1

How to read bootfile name from system.cnf?

Posted: August 2nd, 2013, 12:39 am
by Type 79
I want to add in my program possibility to start game discs, but I don't know how to read filename from inside system.cnf :?:

GTA2 system.cnf

Code: Select all

BOOT = cdrom:\SLES_014.04;1
TCB = 4
EVENT = 10
STACK = 801ffff0
Testcode to start GTA2, only

Code: Select all

#include <sys/types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libcd.h>
#include <libetc.h>

char *file = "cdrom:\SLES_014.04;1";

int main( void )
{
    ResetGraph(3);
    StopCallback();
    _96_init();
    LoadExec(file, 0x801ffff0, 0);
}

Re: How to read bootfile name from system.cnf?

Posted: August 3rd, 2013, 12:05 am
by rsoft
You'd have to write a parser for system.cnf files as you would also want to read the other values like tcb, stack and event.
It's a bit of work but should be doable.

Re: How to read bootfile name from system.cnf?

Posted: August 3rd, 2013, 2:40 am
by Shendo
Fun fact:
According to Martin's (no$psx) documents LoadExec is designed to load SYSTEM.CNF
if you pass null or invalid exe name. Unfortunately the function has a bug and it
doesn't load EXE specified by the SYSTEM.CNF.

So yeah, you need to manually do it like Rsoft said.

Re: How to read bootfile name from system.cnf?

Posted: August 3rd, 2013, 5:35 am
by Type 79
This works with most games I tested.
Doesn't work with Gran Turismo for some reason. Maybe because in LoadExec stacksize = 0, don't know where to get correct size.

Code: Select all

#include <sys/types.h>
#include <libgte.h>
#include <libgpu.h>
#include <libcd.h>
#include <libetc.h>

CdlFILE fp;
char *file = "\\SYSTEM.CNF;1";

char data[128];
char bootfile[20];
char stack[10] = { 48, 120 };

int i, j;

int main( void )
{
    CdInit();

    if(CdSearchFile(&fp, file) == 0)
        printf("\nSYSTEM.CNF not found\n");
    else
    {
        CdReadFile(file, (u_long*)&data, 0);

        if(CdReady(0,0) == CdlDataReady)
        {
            if(data[4]==32) j=7;        // BOOT = cdrom..
            else j=5;                   // BOOT=cdrom..
            for(i=0; i<18; i++)
                bootfile[i]=data[i+j];  // cdrom:\abdc_xxx.yy
                bootfile[18]=59;        // ;
                bootfile[19]=49;        // 1

            for(i=2; i<10; i++)
                stack[i]=data[fp.size-12+i];

            printf("\nBOOT: %s\nSTACK: %s\n\n", bootfile, stack);

            ResetGraph(3);
            StopCallback();
            _96_init();
            LoadExec(bootfile, stack, 0);
        }
    }
}

Re: How to read bootfile name from system.cnf?

Posted: August 3rd, 2013, 6:27 am
by inc^lightforce
i have a scene tool with it you can read the absolute start address by an game exe file. maybe this will help?
and another scene tool will read the absolute start sector by a complete IMAGE of the game.

lemme know.

Re: How to read bootfile name from system.cnf?

Posted: August 3rd, 2013, 7:12 am
by Orion_
This will most likely corrupt your RAM, because CdReadFile read by chunk of 2048 bytes.
so your 'data' buffer must be at least 2048 byte.
I recommand using standard C functions to search for specific string or char in your buffer, such as strstr ou strchr, it will be safer than hardcoded position.

Re: How to read bootfile name from system.cnf?

Posted: August 3rd, 2013, 7:04 pm
by Shadow
I have the code to do this task, but I am having trouble parsing the PS-EXE into LoadExec.
When I have it working I will share it. For now, here is Sony's compiled version.
You can load this PS-EXE and it will boot from the CD-ROM the PS-EXE it finds in the SYSTEM.CNF file.
CDEXEC.CPE
CDEXEC.EXE

Re: How to read bootfile name from system.cnf?

Posted: August 3rd, 2013, 10:04 pm
by Type 79
Gran Turismo's exe-header is different than other games that I have, and LoadExec doesn't seem to like it.

GTA2: normal exe

Code: Select all

ExeType: 'PS-X EXE'
Offset text: 00000000
Offset data: 00000000
Program counter: 800156D8
Global Pointer: 00000000
t_addr: 80010000
t_size: 00029800
d_addr: 00000000
d_size: 00000000
b_addr: 00000000
b_size: 00000000
s_addr: 801FFFF0
s_size: 00000000
Gran Turismo: SCE exe

Code: Select all

ExeType: 'PS-X EXE'
Offset text: 00000800
Offset data: 00022BC8
Program counter: 80032258
Global Pointer: 80040650
t_addr: 80010000
t_size: 00022800
d_addr: 80032800
d_size: 00000438
b_addr: 00000000
b_size: 00000000
s_addr: 00000000
s_size: 00000000
psx-exe header.txt

Code: Select all

                 --===Playstation Executable Information===--
 
___PSX Exe Header___
 
Fixed a little typo in d_addr...
 
I know of 3 types (SCE,PS-X,CPE), but 2 of them are almost the same, and share
most of the fields. The CPE structure will be left for another time as i miss
some info that is needed to start parsing objects. 
typedef struct _EXE_HEADER_ {
	u_byte id[8];
	u_long text;			/* SCE only */
	u_long data;			/* SCE only */
	u_long pc0;
	u_long gp0;			/* SCE only */
	u_long t_addr;
	u_long t_size;
	u_long d_addr;			/* SCE only */
	u_long d_size;			/* SCE only */
	u_long b_addr;			/* SCE only */
	u_long b_size;			/* SCE only */
	u_long s_addr;
	u_long s_size;
	u_long SavedSP;
	u_long SavedFP;
	u_long SavedGP;
	u_long SavedRA;
	u_long SavedS0;
} EXE_HEADER;
 

Explanation
 
  + ExeType = { 'SCE EXE' || 'PS-X EXE' }; 
  + text - Offset of the text segment 
  + data - Offset of the data segment 
  + pc0 - Program Counter. 
  + gp0 - Address of the Global Pointer 
  + t_addr - The address where the text segment is loaded 
  + t_size - The size of the text segment 
  + d_addr - The address where the data segment is loaded 
  + d_size - The size of the data segment 
  + b_addr - The address of the BSS segment 
  + b_size - The size of the BSS segment 
  + s_addr - The address of the stack 
  + s_size - The size of the stack. 
  + SavedXX - The Exec system call saves some registers to these fields before
jumping to the program.

Re: How to read bootfile name from system.cnf?

Posted: July 14th, 2014, 3:11 am
by Shadow
Okay, a little more light on this subject.
Sony's CDEXEC above was compiled 4/AUGUST/1995 11:55PM. It can be located in the Psy-Q/BIN directory.
If you do a search in your SDK directories, you will eventually find another program called CDEXEC but it only contains these lines:

Code: Select all

/*
 * $PSLibId: Run-time Library Release 4.4$
 */
/*
 *          Sample Program: H2000 Boot Module
 *
 *      Copyright (C) 1995 by Sony Computer Entertainment Inc.
 *          All rights Reserved
 *
 *   Version    Date
 *  ------------------------------------------
 *  1.10        May,19,1995 yoshi
 *  1.11        Aug,15,1997 yoshi moved the description to readme file.
 */

main()
{
	_96_remove();
	_96_init();
	LoadExec("cdrom:\\PSX.EXE;1", 0x801fff00, 0);
		/* File name, stack pointer, stack size */
}
That version is useless compared to the first one they made since it only works with PS-EXE's that are only called 'PSX.EXE'.

I have been trying to find the source code to this binary they compiled since it is remarkably simple.
I disassembled it using IDA, and this is what I have figured out:

- _96_init(); is called first.
- LoadExec() is then called trying to load PSX.EXE first. If it fails, then...
- A kernel open() function is then called.
- A kernel read() is then issued.
- A bcopy() is performed, following a bzero().
- Lastly, LoadExec() is called again but this time pointing to the PS-EXE found within SYSTEM.CNF.

I booted Gran Turismo using the original 1995 CDEXEC.CPE and EXE via CAETLA 0.34 (linked above) and it worked perfectly fine.

Oh, and in case you're wondering what happened to the code I was working on, it does work, but I'm not happy with it when I disassembled Sonys version. The version they made seems to be much more simplistic and I would rather use that instead :P