comparison blastem.c @ 2072:cc13c100b027

Merge Sega CD branch now that it sort of works
author Michael Pavone <pavone@retrodev.com>
date Sun, 30 Jan 2022 22:29:29 -0800
parents 7c1760b5b3e5
children 3f29e2726522
comparison
equal deleted inserted replaced
2052:3748a2a8a4b7 2072:cc13c100b027
28 #include "arena.h" 28 #include "arena.h"
29 #include "config.h" 29 #include "config.h"
30 #include "bindings.h" 30 #include "bindings.h"
31 #include "menu.h" 31 #include "menu.h"
32 #include "zip.h" 32 #include "zip.h"
33 #include "cue.h"
33 #include "event_log.h" 34 #include "event_log.h"
34 #ifndef DISABLE_NUKLEAR 35 #ifndef DISABLE_NUKLEAR
35 #include "nuklear_ui/blastem_nuklear.h" 36 #include "nuklear_ui/blastem_nuklear.h"
36 #endif 37 #endif
37 38
89 90
90 size_t filesize = 512 * 1024; 91 size_t filesize = 512 * 1024;
91 size_t readsize = 0; 92 size_t readsize = 0;
92 uint16_t *dst, *buf; 93 uint16_t *dst, *buf;
93 dst = buf = malloc(filesize); 94 dst = buf = malloc(filesize);
94 95
95 96
96 size_t read; 97 size_t read;
97 do { 98 do {
98 if ((readsize + SMD_BLOCK_SIZE > filesize)) { 99 if ((readsize + SMD_BLOCK_SIZE > filesize)) {
99 filesize *= 2; 100 filesize *= 2;
105 dst = process_smd_block(dst, block, read); 106 dst = process_smd_block(dst, block, read);
106 readsize += read; 107 readsize += read;
107 } 108 }
108 } while(read > 0); 109 } while(read > 0);
109 romclose(f); 110 romclose(f);
110 111
111 *buffer = buf; 112 *buffer = buf;
112 113
113 return readsize; 114 return readsize;
114 } 115 }
115 116
116 uint8_t is_smd_format(const char *filename, uint8_t *header) 117 uint8_t is_smd_format(const char *filename, uint8_t *header)
117 { 118 {
130 } 131 }
131 } 132 }
132 return 0; 133 return 0;
133 } 134 }
134 135
135 uint32_t load_rom_zip(const char *filename, void **dst) 136 uint32_t load_media_zip(const char *filename, system_media *dst)
136 { 137 {
137 static const char *valid_exts[] = {"bin", "md", "gen", "sms", "rom", "smd"}; 138 static const char *valid_exts[] = {"bin", "md", "gen", "sms", "rom", "smd"};
138 const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts); 139 const uint32_t num_exts = sizeof(valid_exts)/sizeof(*valid_exts);
139 zip_file *z = zip_open(filename); 140 zip_file *z = zip_open(filename);
140 if (!z) { 141 if (!z) {
141 return 0; 142 return 0;
142 } 143 }
143 144
144 for (uint32_t i = 0; i < z->num_entries; i++) 145 for (uint32_t i = 0; i < z->num_entries; i++)
145 { 146 {
146 char *ext = path_extension(z->entries[i].name); 147 char *ext = path_extension(z->entries[i].name);
147 if (!ext) { 148 if (!ext) {
148 continue; 149 continue;
149 } 150 }
150 for (uint32_t j = 0; j < num_exts; j++) 151 for (uint32_t j = 0; j < num_exts; j++)
151 { 152 {
152 if (!strcasecmp(ext, valid_exts[j])) { 153 if (!strcasecmp(ext, valid_exts[j])) {
153 size_t out_size = nearest_pow2(z->entries[i].size); 154 size_t out_size = nearest_pow2(z->entries[i].size);
154 *dst = zip_read(z, i, &out_size); 155 dst->buffer = zip_read(z, i, &out_size);
155 if (*dst) { 156 if (dst->buffer) {
156 if (is_smd_format(z->entries[i].name, *dst)) { 157 if (is_smd_format(z->entries[i].name, dst->buffer)) {
157 size_t offset; 158 size_t offset;
158 for (offset = 0; offset + SMD_BLOCK_SIZE + SMD_HEADER_SIZE <= out_size; offset += SMD_BLOCK_SIZE) 159 for (offset = 0; offset + SMD_BLOCK_SIZE + SMD_HEADER_SIZE <= out_size; offset += SMD_BLOCK_SIZE)
159 { 160 {
160 uint8_t tmp[SMD_BLOCK_SIZE]; 161 uint8_t tmp[SMD_BLOCK_SIZE];
161 uint8_t *u8dst = *dst; 162 uint8_t *u8dst = dst->buffer;
162 memcpy(tmp, u8dst + offset + SMD_HEADER_SIZE, SMD_BLOCK_SIZE); 163 memcpy(tmp, u8dst + offset + SMD_HEADER_SIZE, SMD_BLOCK_SIZE);
163 process_smd_block((void *)(u8dst + offset), tmp, SMD_BLOCK_SIZE); 164 process_smd_block((void *)(u8dst + offset), tmp, SMD_BLOCK_SIZE);
164 } 165 }
165 out_size = offset; 166 out_size = offset;
166 } 167 }
167 free(ext); 168 dst->extension = ext;
169 dst->dir = path_dirname(filename);
170 dst->name = basename_no_extension(filename);
171 dst->size = out_size;
168 zip_close(z); 172 zip_close(z);
169 return out_size; 173 return out_size;
170 } 174 }
171 } 175 }
172 } 176 }
174 } 178 }
175 zip_close(z); 179 zip_close(z);
176 return 0; 180 return 0;
177 } 181 }
178 182
179 uint32_t load_rom(const char * filename, void **dst, system_type *stype) 183 uint32_t load_media(const char * filename, system_media *dst, system_type *stype)
180 { 184 {
181 uint8_t header[10]; 185 uint8_t header[10];
182 char *ext = path_extension(filename); 186 char *ext = path_extension(filename);
183 if (ext && !strcasecmp(ext, "zip")) { 187 if (ext && !strcasecmp(ext, "zip")) {
184 free(ext); 188 free(ext);
185 return load_rom_zip(filename, dst); 189 return load_media_zip(filename, dst);
186 } 190 }
187 free(ext); 191 free(ext);
188 ROMFILE f = romopen(filename, "rb"); 192 ROMFILE f = romopen(filename, "rb");
189 if (!f) { 193 if (!f) {
190 return 0; 194 return 0;
191 } 195 }
192 if (sizeof(header) != romread(header, 1, sizeof(header), f)) { 196 if (sizeof(header) != romread(header, 1, sizeof(header), f)) {
193 fatal_error("Error reading from %s\n", filename); 197 fatal_error("Error reading from %s\n", filename);
194 } 198 }
195 199
200 uint32_t ret = 0;
196 if (is_smd_format(filename, header)) { 201 if (is_smd_format(filename, header)) {
197 if (stype) { 202 if (stype) {
198 *stype = SYSTEM_GENESIS; 203 *stype = SYSTEM_GENESIS;
199 } 204 }
200 return load_smd_rom(f, dst); 205 ret = load_smd_rom(f, &dst->buffer);
201 } 206 }
202 207
203 size_t filesize = 512 * 1024; 208 if (!ret) {
204 size_t readsize = sizeof(header); 209 size_t filesize = 512 * 1024;
205 210 size_t readsize = sizeof(header);
206 char *buf = malloc(filesize); 211
207 memcpy(buf, header, readsize); 212 char *buf = malloc(filesize);
208 213 memcpy(buf, header, readsize);
209 size_t read; 214
210 do { 215 size_t read;
211 read = romread(buf + readsize, 1, filesize - readsize, f); 216 do {
212 if (read > 0) { 217 read = romread(buf + readsize, 1, filesize - readsize, f);
213 readsize += read; 218 if (read > 0) {
214 if (readsize == filesize) { 219 readsize += read;
215 int one_more = romgetc(f); 220 if (readsize == filesize) {
216 if (one_more >= 0) { 221 int one_more = romgetc(f);
217 filesize *= 2; 222 if (one_more >= 0) {
218 buf = realloc(buf, filesize); 223 filesize *= 2;
219 buf[readsize++] = one_more; 224 buf = realloc(buf, filesize);
220 } else { 225 buf[readsize++] = one_more;
221 read = 0; 226 } else {
222 } 227 read = 0;
223 } 228 }
224 } 229 }
225 } while (read > 0); 230 }
226 231 } while (read > 0);
227 *dst = buf; 232 dst->buffer = buf;
228 233 ret = (uint32_t)readsize;
234 }
235 dst->dir = path_dirname(filename);
236 dst->name = basename_no_extension(filename);
237 dst->extension = path_extension(filename);
238 dst->size = ret;
229 romclose(f); 239 romclose(f);
230 return readsize; 240 if (!strcasecmp(dst->extension, "cue")) {
241 if (parse_cue(dst)) {
242 if (stype) {
243 *stype = SYSTEM_SEGACD;
244 }
245 }
246 }
247
248 return ret;
231 } 249 }
232 250
233 251
234 252
235 int break_on_sync = 0; 253 int break_on_sync = 0;
387 reload_media(); 405 reload_media();
388 cart.chain = &lock_on; 406 cart.chain = &lock_on;
389 free(lock_on.dir); 407 free(lock_on.dir);
390 free(lock_on.name); 408 free(lock_on.name);
391 free(lock_on.extension); 409 free(lock_on.extension);
392 lock_on.dir = path_dirname(lock_on_path); 410 load_media(lock_on_path, &lock_on, NULL);
393 lock_on.name = basename_no_extension(lock_on_path);
394 lock_on.extension = path_extension(lock_on_path);
395 lock_on.size = load_rom(lock_on_path, &lock_on.buffer, NULL);
396 } 411 }
397 412
398 static uint32_t opts = 0; 413 static uint32_t opts = 0;
399 static uint8_t force_region = 0; 414 static uint8_t force_region = 0;
400 void init_system_with_media(const char *path, system_type force_stype) 415 void init_system_with_media(const char *path, system_type force_stype)
409 game_system->free_context(game_system); 424 game_system->free_context(game_system);
410 } else if(current_system) { 425 } else if(current_system) {
411 //start a new arena and save old one in suspended system context 426 //start a new arena and save old one in suspended system context
412 current_system->arena = start_new_arena(); 427 current_system->arena = start_new_arena();
413 } 428 }
414 system_type stype = SYSTEM_UNKNOWN;
415 if (!(cart.size = load_rom(path, &cart.buffer, &stype))) {
416 fatal_error("Failed to open %s for reading\n", path);
417 }
418 free(cart.dir); 429 free(cart.dir);
419 free(cart.name); 430 free(cart.name);
420 free(cart.extension); 431 free(cart.extension);
421 cart.dir = path_dirname(path); 432 system_type stype = SYSTEM_UNKNOWN;
422 cart.name = basename_no_extension(path); 433 if (!(cart.size = load_media(path, &cart, &stype))) {
423 cart.extension = path_extension(path); 434 fatal_error("Failed to open %s for reading\n", path);
435 }
436
424 if (force_stype != SYSTEM_UNKNOWN) { 437 if (force_stype != SYSTEM_UNKNOWN) {
425 stype = force_stype; 438 stype = force_stype;
426 } 439 }
427 if (stype == SYSTEM_UNKNOWN) { 440 if (stype == SYSTEM_UNKNOWN) {
428 stype = detect_system_type(&cart); 441 stype = detect_system_type(&cart);
570 case 'o': { 583 case 'o': {
571 i++; 584 i++;
572 if (i >= argc) { 585 if (i >= argc) {
573 fatal_error("-o must be followed by a lock on cartridge filename\n"); 586 fatal_error("-o must be followed by a lock on cartridge filename\n");
574 } 587 }
575 lock_on.size = load_rom(argv[i], &lock_on.buffer, NULL); 588 if (!load_media(argv[i], &lock_on, NULL)) {
576 if (!lock_on.size) {
577 fatal_error("Failed to load lock on cartridge %s\n", argv[i]); 589 fatal_error("Failed to load lock on cartridge %s\n", argv[i]);
578 } 590 }
579 lock_on.name = basename_no_extension(argv[i]);
580 lock_on.extension = path_extension(argv[i]);
581 cart.chain = &lock_on; 591 cart.chain = &lock_on;
582 break; 592 break;
583 } 593 }
584 case 'h': 594 case 'h':
585 info_message( 595 info_message(
609 } else if (!loaded) { 619 } else if (!loaded) {
610 reader_port = parse_addr_port(argv[i]); 620 reader_port = parse_addr_port(argv[i]);
611 if (reader_port) { 621 if (reader_port) {
612 reader_addr = argv[i]; 622 reader_addr = argv[i];
613 } else { 623 } else {
614 if (!(cart.size = load_rom(argv[i], &cart.buffer, stype == SYSTEM_UNKNOWN ? &stype : NULL))) { 624 if (!load_media(argv[i], &cart, stype == SYSTEM_UNKNOWN ? &stype : NULL)) {
615 fatal_error("Failed to open %s for reading\n", argv[i]); 625 fatal_error("Failed to open %s for reading\n", argv[i]);
616 } 626 }
617 cart.dir = path_dirname(argv[i]);
618 cart.name = basename_no_extension(argv[i]);
619 cart.extension = path_extension(argv[i]);
620 } 627 }
621 romfname = argv[i]; 628 romfname = argv[i];
622 loaded = 1; 629 loaded = 1;
623 } else if (width < 0) { 630 } else if (width < 0) {
624 width = atoi(argv[i]); 631 width = atoi(argv[i]);
625 } else if (height < 0) { 632 } else if (height < 0) {
626 height = atoi(argv[i]); 633 height = atoi(argv[i]);
627 } 634 }
628 } 635 }
629 636
630 int def_width = 0, def_height = 0; 637 int def_width = 0, def_height = 0;
631 char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval; 638 char *config_width = tern_find_path(config, "video\0width\0", TVAL_PTR).ptrval;
632 if (config_width) { 639 if (config_width) {
633 def_width = atoi(config_width); 640 def_width = atoi(config_width);
634 } 641 }
655 } 662 }
656 render_init(width, height, "BlastEm", fullscreen); 663 render_init(width, height, "BlastEm", fullscreen);
657 render_set_drag_drop_handler(on_drag_drop); 664 render_set_drag_drop_handler(on_drag_drop);
658 } 665 }
659 set_bindings(); 666 set_bindings();
660 667
661 uint8_t menu = !loaded; 668 uint8_t menu = !loaded;
662 uint8_t use_nuklear = 0; 669 uint8_t use_nuklear = 0;
663 #ifndef DISABLE_NUKLEAR 670 #ifndef DISABLE_NUKLEAR
664 use_nuklear = !headless && is_nuklear_available(); 671 use_nuklear = !headless && is_nuklear_available();
665 #endif 672 #endif
668 romfname = tern_find_path(config, "ui\0rom\0", TVAL_PTR).ptrval; 675 romfname = tern_find_path(config, "ui\0rom\0", TVAL_PTR).ptrval;
669 if (!romfname) { 676 if (!romfname) {
670 romfname = "menu.bin"; 677 romfname = "menu.bin";
671 } 678 }
672 if (is_absolute_path(romfname)) { 679 if (is_absolute_path(romfname)) {
673 if (!(cart.size = load_rom(romfname, &cart.buffer, &stype))) { 680 if (!(cart.size = load_media(romfname, &cart, &stype))) {
674 fatal_error("Failed to open UI ROM %s for reading", romfname); 681 fatal_error("Failed to open UI ROM %s for reading", romfname);
675 } 682 }
676 } else { 683 } else {
677 cart.buffer = (uint16_t *)read_bundled_file(romfname, &cart.size); 684 cart.buffer = (uint16_t *)read_bundled_file(romfname, &cart.size);
678 if (!cart.buffer) { 685 if (!cart.buffer) {
681 uint32_t rom_size = nearest_pow2(cart.size); 688 uint32_t rom_size = nearest_pow2(cart.size);
682 if (rom_size > cart.size) { 689 if (rom_size > cart.size) {
683 cart.buffer = realloc(cart.buffer, rom_size); 690 cart.buffer = realloc(cart.buffer, rom_size);
684 cart.size = rom_size; 691 cart.size = rom_size;
685 } 692 }
693 cart.dir = path_dirname(romfname);
694 cart.name = basename_no_extension(romfname);
695 cart.extension = path_extension(romfname);
686 } 696 }
687 //force system detection, value on command line is only for games not the menu 697 //force system detection, value on command line is only for games not the menu
688 stype = detect_system_type(&cart); 698 stype = detect_system_type(&cart);
689 cart.dir = path_dirname(romfname);
690 cart.name = basename_no_extension(romfname);
691 cart.extension = path_extension(romfname);
692 loaded = 1; 699 loaded = 1;
693 } 700 }
694 char *state_format = tern_find_path(config, "ui\0state_format\0", TVAL_PTR).ptrval; 701 char *state_format = tern_find_path(config, "ui\0state_format\0", TVAL_PTR).ptrval;
695 if (state_format && !strcmp(state_format, "gst")) { 702 if (state_format && !strcmp(state_format, "gst")) {
696 use_native_states = 0; 703 use_native_states = 0;
703 stype = detect_system_type(&cart); 710 stype = detect_system_type(&cart);
704 } 711 }
705 if (stype == SYSTEM_UNKNOWN) { 712 if (stype == SYSTEM_UNKNOWN) {
706 fatal_error("Failed to detect system type for %s\n", romfname); 713 fatal_error("Failed to detect system type for %s\n", romfname);
707 } 714 }
708 715
709 current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region); 716 current_system = alloc_config_system(stype, &cart, menu ? 0 : opts, force_region);
710 if (!current_system) { 717 if (!current_system) {
711 fatal_error("Failed to configure emulated machine for %s\n", romfname); 718 fatal_error("Failed to configure emulated machine for %s\n", romfname);
712 } 719 }
713 720
714 setup_saves(&cart, current_system); 721 setup_saves(&cart, current_system);
715 update_title(current_system->info.name); 722 update_title(current_system->info.name);
716 if (menu) { 723 if (menu) {
717 menu_system = current_system; 724 menu_system = current_system;
718 } else { 725 } else {
719 game_system = current_system; 726 game_system = current_system;
720 } 727 }
721 } 728 }
722 729
723 #ifndef DISABLE_NUKLEAR 730 #ifndef DISABLE_NUKLEAR
724 if (use_nuklear) { 731 if (use_nuklear) {
725 blastem_nuklear_init(!menu); 732 blastem_nuklear_init(!menu);
726 current_system = game_system; 733 current_system = game_system;
727 menu = 0; 734 menu = 0;
738 //free inflate stream as it was inflateCopied to an internal event reader in the player 745 //free inflate stream as it was inflateCopied to an internal event reader in the player
739 inflateEnd(&reader.input_stream); 746 inflateEnd(&reader.input_stream);
740 setup_saves(&cart, current_system); 747 setup_saves(&cart, current_system);
741 update_title(current_system->info.name); 748 update_title(current_system->info.name);
742 } 749 }
743 750
744 current_system->debugger_type = dtype; 751 current_system->debugger_type = dtype;
745 current_system->enter_debugger = start_in_debugger && menu == debug_target; 752 current_system->enter_debugger = start_in_debugger && menu == debug_target;
746 current_system->start_context(current_system, menu ? NULL : statefile); 753 current_system->start_context(current_system, menu ? NULL : statefile);
747 render_video_loop(); 754 render_video_loop();
748 for(;;) 755 for(;;)