filename | src/loader.c |
changeset | 1075:1a21750d300c |
prev | 1036:af7b0c5905dd |
next | 1095: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 }
.