Search
lxdream.org :: lxdream/src/loader.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/loader.c
changeset 1075:1a21750d300c
prev1036:af7b0c5905dd
next1095:a8b798030464
author nkeynes
date Mon Aug 03 08:41:11 2009 +1000 (14 years ago)
permissions -rw-r--r--
last change Rearrange frame output slightly.
pvr2_display_frame renamed to pvr2_next_frame and changed to update the
frame data without displaying it.
pvr2_redraw_display renamed to pvr2_draw_frame, called internally after
pvr2_next_frame
Add swap_buffers() method to the display driver
Remove explicit glDrawBuffer() calls where they're referencing the window.
pvr2_draw_frame now gets to decide where to draw.
Add force_vsync flag to force double-buffering (not configurable yet)
view annotate diff log raw
     1 /**
     2  * $Id$
     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 <unistd.h>
    21 #include <stdio.h>
    22 #include <string.h>
    23 #include <fcntl.h>
    24 #include <sys/stat.h>
    25 #include <errno.h>
    26 #include <stdint.h>
    27 #include <elf.h>
    28 #include "mem.h"
    29 #include "bootstrap.h"
    30 #include "dreamcast.h"
    31 #include "config.h"
    32 #include "loader.h"
    34 char bootstrap_magic[32] = "SEGA SEGAKATANA SEGA ENTERPRISES";
    35 char iso_magic[6] = "\001CD001";
    36 char *file_loader_extensions[][2] = { 
    37         { "sbi", "Self Boot Inducer" },
    38         { "bin", "SH4 Bin file" },
    39         { NULL, NULL } };
    41 #define BOOTSTRAP_LOAD_ADDR 0x8C008000
    42 #define BOOTSTRAP_SIZE 32768
    44 #define BINARY_LOAD_ADDR 0x8C010000
    46 #define CDI_V2 0x80000004
    47 #define CDI_V3 0x80000005
    49 gboolean file_load_elf_fd( const gchar *filename, int fd );
    52 gboolean file_load_magic( const gchar *filename )
    53 {
    54     char buf[32];
    55     struct stat st;
    56     gboolean result = TRUE;
    58     int fd = open( filename, O_RDONLY );
    59     if( fd == -1 ) {
    60         return FALSE;
    61     }
    63     fstat( fd, &st );
    65     /* begin magic */
    66     if( read( fd, buf, 32 ) != 32 ) {
    67         ERROR( "Unable to read from file '%s'", filename );
    68         close(fd);
    69         return FALSE;
    70     }
    71     if( memcmp( buf, bootstrap_magic, 32 ) == 0 ) {
    72         /* we have a DC bootstrap */
    73         if( st.st_size == BOOTSTRAP_SIZE ) {
    74             sh4ptr_t load = mem_get_region( BOOTSTRAP_LOAD_ADDR );
    75             lseek( fd, 0, SEEK_SET );
    76             read( fd, load, BOOTSTRAP_SIZE );
    77             bootstrap_dump( load, TRUE );
    78             dreamcast_program_loaded( filename, BOOTSTRAP_LOAD_ADDR + 0x300 );
    79         } else {
    80             /* look for a valid ISO9660 header */
    81             lseek( fd, 32768, SEEK_SET );
    82             read( fd, buf, 8 );
    83             if( memcmp( buf, iso_magic, 6 ) == 0 ) {
    84                 /* Alright, got it */
    85                 WARN( "ISO images not supported yet" );
    86             }
    87         }
    88     } else if( memcmp( buf, "PK\x03\x04", 4 ) == 0 ) {
    89         /* ZIP file, aka SBI file */
    90         WARN( "SBI files not supported yet" );
    91         result = FALSE;
    92     } else if( memcmp( buf, DREAMCAST_SAVE_MAGIC, 16 ) == 0 ) {
    93         /* Save state */
    94         result = (dreamcast_load_state( filename )==0);
    95     } else if( buf[0] == 0x7F && buf[1] == 'E' && 
    96             buf[2] == 'L' && buf[3] == 'F' ) {
    97         /* ELF binary */
    98         lseek( fd, 0, SEEK_SET );
    99         result = file_load_elf_fd( filename, fd );
   100     } else {
   101         result = FALSE;
   102     }
   103     close(fd);
   104     return result;
   105 }
   107 void file_load_postload( const gchar *filename, int pc )
   108 {
   109     gchar *bootstrap_file = lxdream_get_global_config_path_value(CONFIG_BOOTSTRAP);
   110     if( bootstrap_file != NULL && bootstrap_file[0] != '\0' ) {
   111         /* Load in a bootstrap before the binary, to initialize everything
   112          * correctly
   113          */
   114         if( mem_load_block( bootstrap_file, BOOTSTRAP_LOAD_ADDR, BOOTSTRAP_SIZE ) == 0 ) {
   115             dreamcast_program_loaded( filename, BOOTSTRAP_LOAD_ADDR+0x300 );
   116             g_free(bootstrap_file);
   117             return;
   118         }
   119     }
   120     dreamcast_program_loaded( filename, pc );
   121     g_free(bootstrap_file);
   122 }    
   125 gboolean file_load_binary( const gchar *filename )
   126 {
   127     /* Load the binary itself */
   128     if(  mem_load_block( filename, BINARY_LOAD_ADDR, -1 ) == 0 ) {
   129         file_load_postload( filename, BINARY_LOAD_ADDR );
   130         return TRUE;
   131     } else {
   132         return FALSE;
   133     }
   134 }
   136 gboolean file_load_elf_fd( const gchar *filename, int fd ) 
   137 {
   138     Elf32_Ehdr head;
   139     Elf32_Phdr phdr;
   140     int i;
   142     if( read( fd, &head, sizeof(head) ) != sizeof(head) )
   143         return FALSE;
   144     if( head.e_ident[EI_CLASS] != ELFCLASS32 ||
   145             head.e_ident[EI_DATA] != ELFDATA2LSB ||
   146             head.e_ident[EI_VERSION] != 1 ||
   147             head.e_type != ET_EXEC ||
   148             head.e_machine != EM_SH ||
   149             head.e_version != 1 ) {
   150         ERROR( "File is not an SH4 ELF executable file" );
   151         return FALSE;
   152     }
   154     /* Program headers */
   155     for( i=0; i<head.e_phnum; i++ ) {
   156         lseek( fd, head.e_phoff + i*head.e_phentsize, SEEK_SET );
   157         read( fd, &phdr, sizeof(phdr) );
   158         if( phdr.p_type == PT_LOAD ) {
   159             lseek( fd, phdr.p_offset, SEEK_SET );
   160             sh4ptr_t target = mem_get_region( phdr.p_vaddr );
   161             read( fd, target, phdr.p_filesz );
   162             if( phdr.p_memsz > phdr.p_filesz ) {
   163                 memset( target + phdr.p_filesz, 0, phdr.p_memsz - phdr.p_filesz );
   164             }
   165             INFO( "Loaded %d bytes to %08X", phdr.p_filesz, phdr.p_vaddr );
   166         }
   167     }
   169     file_load_postload( filename, head.e_entry );
   170     return TRUE;
   171 }
.