1 /*
2  *  This file is part of x48, an emulator of the HP-48sx Calculator.
3  *  Copyright (C) 1994  Eddie C. Dost  (ecd@dressler.de)
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 
20 /* $Log: romio.c,v $
21  * Revision 1.1  1995/01/11  18:11:25  ecd
22  * Initial revision
23  *
24  *
25  * $Id: romio.c,v 1.1 1995/01/11 18:11:25 ecd Exp ecd $
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <sys/stat.h>
32 
33 #include "global.h"
34 #include "resources.h"
35 #include "romio.h"
36 
37 unsigned int opt_gx = 0;
38 unsigned int rom_size = 0;
39 
40 int
41 #ifdef __FunctionProto__
read_rom_file(char * name,unsigned char ** mem,int * size)42 read_rom_file(char *name, unsigned char **mem, int *size)
43 #else
44 read_rom_file(name, mem, size)
45 char *name;
46 unsigned char **mem;
47 int *size;
48 #endif
49 {
50   struct stat st;
51   FILE *fp;
52   unsigned char *tmp_mem;
53   unsigned char byte;
54   unsigned char four[4];
55   int i, j;
56 
57   *mem = NULL;
58   *size = 0;
59   if (NULL == (fp = fopen(name, "r")))
60     {
61       fprintf(stderr, "can\'t open %s\n", name);
62       return 0;
63     }
64 
65   if (stat(name, &st) < 0)
66     {
67       fprintf(stderr, "can\'t stat %s\n", name);
68       fclose(fp);
69       return 0;
70     }
71 
72   if (fread(four, 1, 4, fp) != 4)
73     {
74       fprintf(stderr, "can\'t read first 4 bytes of %s\n", name);
75       fclose(fp);
76       return 0;
77     }
78 
79   if (four[0] == 0x02 && four[1] == 0x03 &&
80       four[2] == 0x06 && four[3] == 0x09)
81     {
82       *size = st.st_size;
83     }
84   else if (four[0] == 0x32 && four[1] == 0x96 &&
85            four[2] == 0x1b && four[3] == 0x80)
86     {
87       *size = 2 * st.st_size;
88     }
89   else if (four[1] = 0x49)
90     {
91       fprintf(stderr, "%s is an HP49 ROM\n", name);
92       *size = 2 * st.st_size;
93     }
94   else if (four[0])
95     {
96       printf("%d\n", st.st_size);
97       *size = st.st_size;
98     }
99   else
100     {
101       fprintf(stderr, "%s is not a HP48 ROM\n", name);
102       fclose(fp);
103       return 0;
104     }
105 
106   if (fseek(fp, 0, 0) < 0)
107     {
108       fprintf(stderr, "can\'t fseek to position 0 in %s\n", name);
109       *size = 0;
110       fclose(fp);
111       return 0;
112     }
113 
114   *mem = (unsigned char *)malloc(*size);
115 
116   if (st.st_size == *size)
117     {
118       /*
119        * size is same as memory size, old version file
120        */
121       if (fread(*mem, 1, (size_t)*size, fp) != *size)
122         {
123           fprintf(stderr, "can\'t read %s\n", name);
124           free(*mem);
125           *mem = NULL;
126           *size = 0;
127           fclose(fp);
128           return 0;
129         }
130     }
131   else
132     {
133       /*
134        * size is different, check size and decompress memory
135        */
136 
137       if (st.st_size != *size / 2)
138         {
139           fprintf(stderr, "strange size %s, expected %d, found %ld\n",
140                   name, *size / 2, st.st_size);
141           free(*mem);
142           *mem = NULL;
143           *size = 0;
144           fclose(fp);
145           return 0;
146         }
147 
148       if (NULL == (tmp_mem = (unsigned char *)malloc((size_t)st.st_size)))
149         {
150           for (i = 0, j = 0; i < *size / 2; i++)
151             {
152               if (1 != fread(&byte, 1, 1, fp))
153                 {
154                   fprintf(stderr, "can\'t read %s\n", name);
155                   free(*mem);
156                   *mem = NULL;
157                   *size = 0;
158                   fclose(fp);
159                   return 0;
160                 }
161               (*mem)[j++] = byte & 0xf;
162               (*mem)[j++] = (byte >> 4) & 0xf;
163             }
164         }
165       else
166         {
167           if (fread(tmp_mem, 1, (size_t)*size / 2, fp) != *size / 2)
168             {
169               fprintf(stderr, "can\'t read %s\n", name);
170               free(*mem);
171               *mem = NULL;
172               *size = 0;
173               fclose(fp);
174               free(tmp_mem);
175               return 0;
176             }
177 
178           for (i = 0, j = 0; i < *size / 2; i++)
179             {
180               (*mem)[j++] = tmp_mem[i] & 0xf;
181               (*mem)[j++] = (tmp_mem[i] >> 4) & 0xf;
182             }
183 
184           free(tmp_mem);
185         }
186     }
187 
188   fclose(fp);
189 
190   if ((*mem)[0x29] == 0x00)
191     {
192       if (*size == ROM_SIZE_GX)
193         {
194           opt_gx = 1;
195         }
196       else
197       if (*size == 4 * ROM_SIZE_GX)
198         {
199           fprintf(stderr, "%s seems to be HP49 ROM, but size is 0x%x\n",
200 		  name, *size);
201           opt_gx = 2;
202         }
203       else
204       if (*size == 8 * ROM_SIZE_GX)
205         {
206           fprintf(stderr, "%s seems to be HP49 ROM, but size is 0x%x\n",
207 		  name, *size);
208           opt_gx = 2;
209         }
210       else
211         {
212           fprintf(stderr, "%s seems to be G/GX ROM, but size is 0x%x\n",
213 		  name, *size);
214           free(*mem);
215           *mem = NULL;
216           *size = 0;
217           return 0;
218         }
219     }
220   else
221     {
222       if (*size == ROM_SIZE_SX)
223         {
224           opt_gx = 0;
225         }
226       else
227         {
228           fprintf(stderr, "%s seems to be S/SX ROM, but size is 0x%x\n",
229 		  name, *size);
230           free(*mem);
231           *mem = NULL;
232           *size = 0;
233           return 0;
234         }
235     }
236 
237   if (verbose)
238     printf("%s: read %s\n", progname, name);
239 
240   return 1;
241 }
242 
243