Search
lxdream.org :: lxdream/src/loader.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/loader.c
changeset 180:e6dcf9b65658
prev171:3542185a8cf9
next294:a5beff9b2b85
author nkeynes
date Mon Jan 15 08:32:09 2007 +0000 (13 years ago)
permissions -rw-r--r--
last change Break vram routines out into pvr2mem.c
Initial (untested) implementation of stride textures
Hookup YUV converter code in pvr2.c
view annotate diff log raw
     1 /**
     2  * $Id: loader.c,v 1.14 2006-07-02 04:59:00 nkeynes Exp $
     3  *
     4  * File loading routines, mostly for loading demos without going through the
     5  * whole procedure of making a CD image for them.
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or
    12  * (at your option) any later version.
    13  *
    14  * This program is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU General Public License for more details.
    18  */
    20 #include <stdio.h>
    21 #include <fcntl.h>
    22 #include <sys/stat.h>
    23 #include <errno.h>
    24 #include <stdint.h>
    25 #include <elf.h>
    26 #include "gui/gui.h"
    27 #include "mem.h"
    28 #include "sh4core.h"
    29 #include "bootstrap.h"
    30 #include "dreamcast.h"
    32 char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";
    33 char iso_magic[6] = "\001CD001";
    34 char *file_loader_extensions[][2] = { 
    35     { "sbi", "Self Boot Inducer" },
    36     { "bin", "SH4 Bin file" },
    37     { NULL, NULL } };
    39 #define BOOTSTRAP_LOAD_ADDR 0x8C008000
    40 #define BOOTSTRAP_SIZE 32768
    42 #define BINARY_LOAD_ADDR 0x8C010000
    44 #define CDI_V2 0x80000004
    45 #define CDI_V3 0x80000005
    47 gboolean file_load_magic( const gchar *filename )
    48 {
    49     char buf[32];
    50     uint32_t tmpa[2];
    51     struct stat st;
    53     int fd = open( filename, O_RDONLY );
    54     if( fd == -1 ) {
    55         ERROR( "Unable to open file: '%s' (%s)", filename,
    56                strerror(errno) );
    57         return FALSE;
    58     }
    60     fstat( fd, &st );
    61     /*
    62     if( st.st_size < 32768 ) {
    63         ERROR( "File '%s' too small to be a dreamcast image", filename );
    64         close(fd);
    65         return FALSE;
    66     }
    67     */
    69     /* begin magic */
    70     if( read( fd, buf, 32 ) != 32 ) {
    71         ERROR( "Unable to read from file '%s'", filename );
    72         close(fd);
    73         return FALSE;
    74     }
    75     if( memcmp( buf, bootstrap_magic, 32 ) == 0 ) {
    76         /* we have a DC bootstrap */
    77         if( st.st_size == BOOTSTRAP_SIZE ) {
    78             char *load = mem_get_region( BOOTSTRAP_LOAD_ADDR );
    79             lseek( fd, 0, SEEK_SET );
    80             read( fd, load, BOOTSTRAP_SIZE );
    81             bootstrap_dump( load, TRUE );
    82             sh4_set_pc( BOOTSTRAP_LOAD_ADDR + 0x300 );
    83             gtk_gui_update();
    84         } else {
    85             /* look for a valid ISO9660 header */
    86             lseek( fd, 32768, SEEK_SET );
    87             read( fd, buf, 8 );
    88             if( memcmp( buf, iso_magic, 6 ) == 0 ) {
    89                 /* Alright, got it */
    90                 INFO( "Loading ISO9660 filesystem from '%s'",
    91                       filename );
    92             }
    93         }
    94     } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {
    95 	/* ZIP file, aka SBI file */
    96 	WARN( "SBI files not supported yet" );
    97     } else if( buf[0] == 0x7F && buf[1] == 'E' && 
    98 	       buf[2] == 'L' && buf[3] == 'F' ) {
    99 	/* ELF binary */
   100 	lseek( fd, 0, SEEK_SET );
   101 	file_load_elf_fd( fd );
   102     } else {
   103 	/* Assume raw binary */
   104 	file_load_binary( filename );
   105     } 
   106     close(fd);
   107     return TRUE;
   108 }
   110 int file_load_postload( int pc )
   111 {
   112     const gchar *bootstrap_file = dreamcast_get_config_value(CONFIG_BOOTSTRAP);
   113     if( bootstrap_file != NULL ) {
   114 	/* Load in a bootstrap before the binary, to initialize everything
   115 	 * correctly
   116 	 */
   117 	if( mem_load_block( bootstrap_file, BOOTSTRAP_LOAD_ADDR, BOOTSTRAP_SIZE ) != 0 ) {
   118 	    /* Try it without the bootstrap */
   119 	    sh4_set_pc( pc );
   120 	} else {
   121 	    sh4_set_pc( BOOTSTRAP_LOAD_ADDR + 0x300 );
   122 	}
   123     } else {
   124 	sh4_set_pc( pc );
   125     }
   126     bios_install();
   127     dcload_install();
   128     gtk_gui_update();
   129 }    
   132 int file_load_binary( const gchar *filename )
   133 {
   134     /* Load the binary itself */
   135     mem_load_block( filename, BINARY_LOAD_ADDR, -1 );
   136     file_load_postload( BINARY_LOAD_ADDR );
   137 }
   139 int file_load_elf_fd( int fd ) 
   140 {
   141     Elf32_Ehdr head;
   142     Elf32_Phdr phdr;
   143     int i;
   145     if( read( fd, &head, sizeof(head) ) != sizeof(head) )
   146 	return -1;
   147     if( head.e_ident[EI_CLASS] != ELFCLASS32 ||
   148 	head.e_ident[EI_DATA] != ELFDATA2LSB ||
   149 	head.e_ident[EI_VERSION] != 1 ||
   150 	head.e_type != ET_EXEC ||
   151 	head.e_machine != EM_SH ||
   152 	head.e_version != 1 ) {
   153 	ERROR( "File is not an SH4 ELF executable file" );
   154 	return -1;
   155     }
   157     /* Program headers */
   158     for( i=0; i<head.e_phnum; i++ ) {
   159 	lseek( fd, head.e_phoff + i*head.e_phentsize, SEEK_SET );
   160 	read( fd, &phdr, sizeof(phdr) );
   161 	if( phdr.p_type == PT_LOAD ) {
   162 	    lseek( fd, phdr.p_offset, SEEK_SET );
   163 	    char *target = mem_get_region( phdr.p_vaddr );
   164 	    read( fd, target, phdr.p_filesz );
   165 	    if( phdr.p_memsz > phdr.p_filesz ) {
   166 		memset( target + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz );
   167 	    }
   168 	    INFO( "Loaded %d bytes to %08X", phdr.p_filesz, phdr.p_vaddr );
   169 	}
   170     }
   172     return file_load_postload( head.e_entry );
   173 }
.