Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
roms.c
Go to the documentation of this file.
1 /* Xep128: Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Copyright (C)2016 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
3  http://xep128.lgb.hu/
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18 
19 #include "xep128.h"
20 #include "roms.h"
21 #include "cpu.h"
22 #include "configuration.h"
23 #include "emu_rom_interface.h"
24 
25 
26 static const Uint8 xep_rom_image[] = {
27 #include "xemu/../rom/ep128/xep_rom.hex"
28 };
29 int xep_rom_seg = -1;
31 const char *rom_name_tab[0x100];
32 static int reloading = 0; // allows to re-load ROM config run-time, this non-zero after the first call of roms_load()
33 
34 
35 static FILE *sram_open ( int seg, const char *mode, char *path )
36 {
37  char fn[64];
38  snprintf(fn, sizeof fn, "@sram-%02X.seg", seg);
39  return open_emu_file(fn, mode, path);
40 }
41 
42 
43 
45 {
46  int a;
47  char path[PATH_MAX + 1];
48  FILE *f = sram_open(seg, "wb", path);
49  DEBUGPRINT("MEM: SRAM: saving SRAM segment %02Xh to file %s" NL, seg, path);
50  if (!f) {
51  ERROR_WINDOW("Cannot create file for saving SRAM segment %02Xh because of file I/O error: %s\nFile name was: %s", seg, ERRSTR(), path);
52  return 1;
53  }
54  a = fwrite(memory + (seg << 14), 0x4000, 1, f);
55  if (a != 1)
56  ERROR_WINDOW("Cannot save SRAM segment %02Xh because of file I/O error: %s\nFile name was: %s", seg, ERRSTR(), path);
57  fclose(f);
58  return a != 1;
59 }
60 
61 
62 
64 {
65  int a;
66  char path[PATH_MAX + 1];
67  FILE *f = sram_open(seg, "rb", path);
68  DEBUGPRINT("MEM: SRAM: loading SRAM segment %02Xh from file %s" NL, seg, path);
69  if (!f) {
70  ERROR_WINDOW("Cannot open file for loading SRAM segment %02Xh because of file I/O error: %s\nFile name was: %s", seg, ERRSTR(), path);
71  return 1;
72  }
73  a = fread(memory + (seg << 14), 0x4000, 1, f);
74  if (a != 1)
75  ERROR_WINDOW("Cannot load SRAM segment %02Xh because of file I/O error: %s\nFile name was: %s", seg, ERRSTR(), path);
76  fclose(f);
77  return a != 1;
78 }
79 
80 
81 
83 {
84  int a, ret = 0;
85  for (a = 0; a < 0x100; a++ )
87  ret += sram_save_segment(a);
88  return ret;
89 }
90 
91 
92 
93 /* This function also re-initializes the whole memory! Do not call it after you defined RAM for the system, but only before! */
94 int roms_load ( void )
95 {
96  int seg, last = 0;
97  char path[PATH_MAX + 1];
98  if (reloading) // in case of already defined (reloading) memory model, we want to back our SRAM segments up - if any at all ...
100  for (seg = 0; seg < 0x100; seg++ ) {
101  memory_segment_map[seg] = (seg >= 0xFC ? VRAM_SEGMENT : UNUSED_SEGMENT); // 64K VRAM is default, you cannot override that!
102  if (reloading && rom_name_tab[seg])
103  free((void*)rom_name_tab[seg]); // already defined (reloading) situation, we want to free used memory as well
104  rom_name_tab[seg] = NULL;
105  }
106  reloading = 1; // set reloading flag, in next invocation of roms_load(), it will be done in config reload mode!
107  memset(memory, 0xFF, 0x400000);
108  xep_rom_seg = -1;
109  for (seg = 0; seg < 0x100; seg++ ) {
110  void *option = config_getopt("rom", seg, NULL);
111  if (option) {
112  const char *name;
113  int lseg = seg;
114  FILE *f;
115  config_getopt_pointed(option, &name);
116  if (!strcasecmp(name, "XEP") && seg) {
118  DEBUG("CONFIG: ROM: segment %02Xh assigned to internal XEP ROM" NL, seg);
119  xep_rom_seg = seg;
121  } else
122  ERROR_WINDOW("XEP ROM forced segment assignment cannot be done since segment %02X is not unused", seg);
123  continue;
124  }
125  DEBUG("CONFIG: ROM: segment %02Xh file %s" NL, seg, name);
126  f = open_emu_file(name, "rb", path);
127  if (f == NULL) {
128  ERROR_WINDOW("Cannot open ROM image \"%s\" (to be used from segment %02Xh): %s", name, seg, ERRSTR());
129  if (!strcmp(name, COMBINED_ROM_FN)) { // this should be the auto-install functionality, with downloading stuff?
130  }
131  return -1;
132  }
133  DEBUG("CONFIG: ROM: ... file path is %s" NL, path);
134  rom_name_tab[seg] = SDL_strdup(path);
136  for (;;) {
137  int ret;
138  // Note: lseg overflow is not needed to be tested, as VRAM marks will stop reading of ROM image in the worst case ...
139  if (memory_segment_map[lseg] != UNUSED_SEGMENT) {
140  fclose(f);
141  forget_emu_file(path);
142  ERROR_WINDOW("While reading ROM image \"%s\" into segment %02Xh: already used segment (\"%s\")!", path, lseg, memory_segment_map[lseg]);
143  return -1;
144  }
145  ret = fread(memory + (lseg << 14), 1, 0x4000, f);
146  if (ret)
147  DEBUG("CONFIG: ROM: ... trying read 0x4000 bytes in segment %02Xh, result is %d" NL, lseg, ret);
148  if (ret < 0) {
149  ERROR_WINDOW("Cannot read ROM image \"%s\" (to be used in segment %02Xh): %s", path, lseg, ERRSTR());
150  fclose(f);
151  forget_emu_file(path);
152  return -1;
153  } else if (ret == 0) {
154  if (lseg == seg) {
155  fclose(f);
156  forget_emu_file(path);
157  ERROR_WINDOW("Null-sized ROM image \"%s\" (to be used in segment %02Xh).", path, lseg);
158  return -1;
159  }
160  break;
161  } else if (ret != 0x4000) {
162  fclose(f);
163  forget_emu_file(path);
164  ERROR_WINDOW("Bad ROM image \"%s\": not multiple of 16K bytes!", path);
165  return -1;
166  }
167  // check if ROM image contains XEP128_ROM segment signature, if so, try to use XEP ROM from here
168  if (!memcmp(memory + (lseg << 14), "XEP__ROM", 8) && xep_rom_seg == -1) {
169  xep_rom_seg = lseg;
171  } else
173  if (lseg > last)
174  last = lseg;
175  if (ret != 0x4000)
176  break;
177  lseg++;
178  }
179  fclose(f);
180  forget_emu_file(path);
181  } else if (!seg) {
182  ERROR_WINDOW("Fatal ROM image error: No ROM defined for segment 00h, no EXOS is requested!");
183  return -1;
184  }
185  }
186  /* XEP ROM: guess where to place it, or disable it ... */
187  if (config_getopt_int("xeprom")) {
188  // XEP ROM is enabled with 'xeprom' directive
189  if (xep_rom_seg == -1) { // not assigned manually, try to find a place for it ...
190  xep_rom_seg = last + 1; // ... with simply using the segment after the last used ROM segment
191  DEBUGPRINT("CONFIG: ROM: automatic XEP ROM image placer selected segment is %02Xh" NL, xep_rom_seg);
192  }
193  } else {
194  // XEP ROM is disabled (with 'xeprom' directive), _IF_ it was not assigned manually
195  if (xep_rom_seg == -1) {
196  DEBUGPRINT("CONFIG: ROM: XEP ROM is disabled by configuration!" NL);
197  INFO_WINDOW("XEP internal ROM image is disabled by configuration.\nXep128 will work, but no XEP feature will be available.");
198  }
199  }
200  /* XEP ROM: now install our internal ROM, if it's allowed/OK to do so */
201  if (xep_rom_seg > 0) {
203  xep_rom_addr = xep_rom_seg << 14;
204  memset(memory + xep_rom_addr, 0, 0x4000);
205  memcpy(memory + xep_rom_addr, xep_rom_image, sizeof xep_rom_image);
208  DEBUGPRINT("CONFIG: ROM: XEP internal ROM image has been installed in segment %02Xh" NL, xep_rom_seg);
209  } else {
210  DEBUGPRINT("CONFIG: ROM: XEP internal ROM image CANNOT be installed because segment %02Xh is used!!" NL, xep_rom_seg);
211  ERROR_WINDOW("XEP internal ROM image cannot be installed.\nXep128 will work, but no XEP feature will be available.");
212  xep_rom_seg = -1;
213  }
214  } else
215  xep_rom_seg = -1;
216  return 0;
217 }
218 
sram_save_segment
int sram_save_segment(int seg)
Definition: roms.c:73
rom_name_tab
const char * rom_name_tab[0x100]
Definition: roms.c:36
xep_rom_seg
int xep_rom_seg
Definition: roms.c:33
UNUSED_SEGMENT
const char UNUSED_SEGMENT[]
Definition: cpu.c:56
seg
Uint8 seg
Definition: roms.c:41
COMBINED_ROM_FN
#define COMBINED_ROM_FN
Definition: xep128.h:63
sram_load_segment
int sram_load_segment(int seg)
Definition: roms.c:80
roms.h
INFO_WINDOW
#define INFO_WINDOW(...)
Definition: xep128.h:114
fn
const char * fn
Definition: roms.c:42
config_getopt
void * config_getopt(const char *name, const int subopt, void *value)
Definition: configuration.c:254
roms_load
int roms_load(void)
Definition: roms.c:140
Uint8
uint8_t Uint8
Definition: fat32.c:51
SRAM_SEGMENT
const char SRAM_SEGMENT[]
Definition: cpu.c:55
emu_rom_interface.h
open_emu_file
FILE * open_emu_file(const char *name, const char *mode, char *pathbuffer)
Definition: configuration.c:109
cpu.h
memory_segment_map
const char * memory_segment_map[0x100]
Definition: cpu.c:44
DEBUGPRINT
#define DEBUGPRINT(...)
Definition: emutools_basicdefs.h:171
XEPROM_SEGMENT
const char XEPROM_SEGMENT[]
Definition: cpu.c:52
xep_set_default_device_name
void xep_set_default_device_name(const char *name)
Definition: emu_rom_interface.c:95
CHECK_MALLOC
#define CHECK_MALLOC(p)
Definition: xep128.h:119
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
mode
int mode
Definition: vera.c:61
NL
#define NL
Definition: fat32.c:37
memory
Uint8 memory[0x100000]
Definition: commodore_65.c:43
VRAM_SEGMENT
const char VRAM_SEGMENT[]
Definition: cpu.c:54
xep128.h
config_getopt_pointed
void config_getopt_pointed(void *st_in, void *value)
Definition: configuration.c:275
configuration.h
forget_emu_file
void forget_emu_file(const char *path)
Definition: configuration.c:98
ERRSTR
#define ERRSTR()
Definition: enterprise128.h:56
name
const char * name
Definition: joystick.c:46
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
ROM_SEGMENT
const char ROM_SEGMENT[]
Definition: cpu.c:51
last
Uint8 last
Definition: input_devices.c:78
sram_save_all_segments
int sram_save_all_segments(void)
Definition: roms.c:87
xep_rom_addr
int xep_rom_addr
Definition: roms.c:34