Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
roms.c
Go to the documentation of this file.
1 /* Minimalistic Enterprise-128 emulator with focus on "exotic" hardware
2  Part of the Xemu project, please visit: https://github.com/lgblgblgb/xemu
3  Copyright (C)2016,2020-2021 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
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 "xemu/emutools.h"
20 #include "xemu/emutools_files.h"
21 #include "xemu/emutools_config.h"
22 #include "enterprise128.h"
23 #include "roms.h"
24 #include "cpu.h"
25 #include "emu_rom_interface.h"
26 #include <errno.h>
27 #include <string.h>
28 
29 
30 static const Uint8 xep_rom_image[] = {
31 #include "rom/ep128/xep_rom.hex"
32 };
33 int xep_rom_seg = -1;
36 const char *rom_name_tab[0x100];
37 static int reloading = 0; // allows to re-load ROM config run-time, this non-zero after the first call of roms_load()
38 
39 #define ROM_REQUEST_LIST_MAX_SIZE 32
40 static struct {
42  const char *fn;
43 } rom_request_list[ROM_REQUEST_LIST_MAX_SIZE];
44 static int rom_request_list_size = 0;
45 
46 
47 const char *rom_parse_opt ( const char *optname, const char *optvalue )
48 {
49  //DEBUGPRINT("PARSE_ROM: optname=%s optvalue=%s" NL, optname, optvalue);
50  const char *p = strchr(optname, '@');
51  if (!p || !p[1])
52  return "rom option should specify segment, ie: rom@XX (XX=hex)";
53  int seg = 0;
54  while (*++p) {
55  if ((*p >= 'A' && *p <= 'F') || (*p >= 'a' && *p <= 'f'))
56  seg = (seg << 4) + (*p & 0xF) + 9;
57  else if (*p >= '0' && *p <= '9')
58  seg = (seg << 4) + *p - '0';
59  else {
60  return "Invalid HEX value character after rom@ in the option name";
61  }
62  if (seg >= 0xFC)
63  return "Invalid segment specified after the rom@ option";
64  }
65  if (rom_request_list_size >= ROM_REQUEST_LIST_MAX_SIZE)
66  return "too many rom options!";
67  rom_request_list[rom_request_list_size].seg = seg;
68  rom_request_list[rom_request_list_size].fn = xemu_strdup(optvalue);
69  rom_request_list_size++;
70  return NULL;
71 }
72 
74 {
75  char fn[PATH_MAX];
76  sprintf(fn, SRAM_BACKUP_FILE_FORMAT, seg);
77  return xemu_save_file(fn, memory + (seg << 14), 0x4000, "Cannot save SRAM segment");
78 }
79 
81 {
82  char fn[PATH_MAX];
83  sprintf(fn, SRAM_BACKUP_FILE_FORMAT, seg);
84  return xemu_load_file(fn, memory + (seg << 14), 0x4000, 0x4000, "Cannot load SRAM segment") != 0x4000;
85 }
86 
88 {
89  int ret = 0;
90  for (int a = 0; a < 0x100; a++ )
92  ret += sram_save_segment(a) ? 1 : 0;
93  return ret;
94 }
95 
96 
97 static int load_rom_image ( int seg, const char *fn )
98 {
99  if (seg < 0 || seg >= 0xFC)
100  FATAL("Invalid ROM segment: %02Xh", seg);
101  if (!fn || !*fn)
102  FATAL("Invalid ROM name: NULL or empty string for segment #%02Xh", seg);
103  int size = xemu_load_file(fn, NULL, 0x4000, 0x400000 - 0x10000, "Cannot open/load requested ROM");
104  if (size <= 0) {
105  if (!strcmp(fn, DEFAULT_ROM_FN) && seg == 0) { // this should be the auto-install functionality, with downloading stuff? TODO
106  }
107  return -1;
108  }
109  if ((size & 0x3FFF)) {
110  ERROR_WINDOW("BAD ROM image \"%s\": length is not multiple of 16Kbytes!", xemu_load_filepath);
111  free(xemu_load_buffer_p);
112  return -1;
113  }
114  size >>= 14; // size in segments from this point
115  // Note: no need to check overflow of the loaded ROM, as if it would hit VRAM, it's not UNUSED_SEGMENT ...
116  for (int i = seg; i < seg + size; i++) {
118  ERROR_WINDOW("ERROR while loading ROM to segment #%02Xh: segment is already in use\n%s", i, xemu_load_filepath);
119  free(xemu_load_buffer_p);
120  return -1;
121  }
122  }
123  memcpy(memory + (seg << 14), xemu_load_buffer_p, size << 14);
124  free(xemu_load_buffer_p);
126  for (int i = seg; i < seg + size; i++) {
127  // check if ROM image contains XEP128_ROM segment signature, if so, try to use XEP ROM from here
128  if (!memcmp(memory + (i << 14), "XEP__ROM", 8) && xep_rom_seg == -1) {
129  xep_rom_seg = i;
131  } else
133  }
134  return 0;
135 }
136 
137 
138 
139 /* This function also re-initializes the whole memory! Do not call it after you defined RAM for the system, but only before! */
140 int roms_load ( void )
141 {
142  //int seg, last = 0;
143  //char path[PATH_MAX + 1];
144  if (reloading) // in case of already defined (reloading) memory model, we want to back our SRAM segments up - if any at all ...
146  for (int seg = 0; seg < 0x100; seg++ ) {
147  memory_segment_map[seg] = (seg >= 0xFC ? VRAM_SEGMENT : UNUSED_SEGMENT); // 64K VRAM is default, you cannot override that!
148  if (reloading && rom_name_tab[seg])
149  free((void*)rom_name_tab[seg]); // already defined (reloading) situation, we want to free used memory as well
150  rom_name_tab[seg] = NULL;
151  }
152  reloading = 1; // set reloading flag, in next invocation of roms_load(), it will be done in config reload mode!
153  memset(memory, 0xFF, 0x400000);
154  xep_rom_seg = -1;
155  // Load requested list at cmdline+cfgfile parser step
156  for (int i = 0; i < rom_request_list_size; i++) {
157  load_rom_image(rom_request_list[i].seg, rom_request_list[i].fn);
158  free((void*)rom_request_list[i].fn);
159  }
161  ERROR_WINDOW("Invalid config, segment zero must be ROM");
162  return 1;
163  }
165  // no valid config (no ROM in segment zero)
166  if (rom_request_list_size) {
167  // if there was some ROM config (rom_request_list_size is non-zero) then it's
168  // a fatal error resulted this bad configuration!
169  ERROR_WINDOW("Invalid config: No ROM image was defined for segment 0!");
170  return 1;
171  }
172  // ... though if there was no ROM config, some defaults should be nice to try,
173  // so here it is:
174  DEBUGPRINT("CONFIG: ROM: no ROM was defined by user. Trying the default one for segment 0: %s" NL, DEFAULT_ROM_FN);
175  if (load_rom_image(0, DEFAULT_ROM_FN))
176  return 1;
177  // ... if it also fails, end of game.
178  }
179  rom_request_list_size = 0;
180  /* XEP ROM: guess where to place it, or disable it ... */
181  if (!cfg_noexprom) {
182  // XEP ROM is enabled with 'xeprom' directive
183  if (xep_rom_seg == -1) { // not assigned manually, try to find a place for it ...
184  for (int seg = 0; seg < 0xFC; seg++) {
186  xep_rom_seg = seg;
187  break;
188  }
189  }
190  if (xep_rom_seg != -1)
191  DEBUGPRINT("CONFIG: ROM: automatic XEP ROM image placer selected segment is %02Xh" NL, xep_rom_seg);
192  else
193  DEBUGPRINT("CONFIG: ROM: could not find place for XEP ROM ..." NL);
194  }
195  } else {
196  // XEP ROM is disabled (with 'xeprom' directive), _IF_ it was not assigned manually
197  if (xep_rom_seg == -1) {
198  DEBUGPRINT("CONFIG: ROM: XEP ROM is disabled by configuration!" NL);
199  INFO_WINDOW("XEP internal ROM image is disabled by configuration.\nXep128 will work, but no XEP feature will be available.");
200  }
201  }
202  /* XEP ROM: now install our internal ROM, if it's allowed/OK to do so */
203  if (xep_rom_seg > 0) {
205  xep_rom_addr = xep_rom_seg << 14;
206  memset(memory + xep_rom_addr, 0, 0x4000);
207  memcpy(memory + xep_rom_addr, xep_rom_image, sizeof xep_rom_image);
209  DEBUGPRINT("CONFIG: ROM: XEP internal ROM image has been installed in segment %02Xh" NL, xep_rom_seg);
211  } else {
212  DEBUGPRINT("CONFIG: ROM: XEP internal ROM image CANNOT be installed because segment %02Xh is used!!" NL, xep_rom_seg);
213  ERROR_WINDOW("XEP internal ROM image cannot be installed.\nXep128 will work, but no XEP feature will be available.");
214  xep_rom_seg = -1;
215  }
216  } else
217  xep_rom_seg = -1;
218  DEBUGPRINT("CONFIG: ROM init end." NL);
219  return 0;
220 }
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
ROM_REQUEST_LIST_MAX_SIZE
#define ROM_REQUEST_LIST_MAX_SIZE
Definition: roms.c:39
emutools.h
DEFAULT_ROM_FN
#define DEFAULT_ROM_FN
Definition: enterprise128.h:28
seg
Uint8 seg
Definition: roms.c:41
sram_load_segment
int sram_load_segment(int seg)
Definition: roms.c:80
SRAM_BACKUP_FILE_FORMAT
#define SRAM_BACKUP_FILE_FORMAT
Definition: enterprise128.h:31
emu_rom_interface.h
INFO_WINDOW
#define INFO_WINDOW(...)
Definition: xep128.h:114
fn
const char * fn
Definition: roms.c:42
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
emutools_files.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
xemu_save_file
int xemu_save_file(const char *filename_in, void *data, int size, const char *cry)
Definition: emutools_files.c:622
roms.h
xep_set_default_device_name
void xep_set_default_device_name(const char *name)
Definition: emu_rom_interface.c:95
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
rom_parse_opt
const char * rom_parse_opt(const char *optname, const char *optvalue)
Definition: roms.c:47
cpu.h
NL
#define NL
Definition: fat32.c:37
emutools_config.h
memory
Uint8 memory[0x100000]
Definition: commodore_65.c:43
xemu_load_file
int xemu_load_file(const char *filename, void *store_to, int min_size, int max_size, const char *cry)
Definition: emutools_files.c:674
xemu_load_buffer_p
void * xemu_load_buffer_p
Definition: emutools_files.c:34
VRAM_SEGMENT
const char VRAM_SEGMENT[]
Definition: cpu.c:54
size
int size
Definition: inject.c:37
cfg_noexprom
int cfg_noexprom
Definition: roms.c:35
xemu_strdup
char * xemu_strdup(const char *s)
Definition: emutools.c:278
xemu_load_filepath
char xemu_load_filepath[PATH_MAX]
Definition: emutools_files.c:35
enterprise128.h
FATAL
#define FATAL(...)
Definition: xep128.h:117
ROM_SEGMENT
const char ROM_SEGMENT[]
Definition: cpu.c:51
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