Mercurial > repos > blastem
comparison genesis.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 | 8ee7ecbf3f21 |
children | bafb757e1cd2 |
comparison
equal
deleted
inserted
replaced
2052:3748a2a8a4b7 | 2072:cc13c100b027 |
---|---|
2 Copyright 2013-2016 Michael Pavone | 2 Copyright 2013-2016 Michael Pavone |
3 This file is part of BlastEm. | 3 This file is part of BlastEm. |
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. | 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. |
5 */ | 5 */ |
6 #include "genesis.h" | 6 #include "genesis.h" |
7 #include "segacd.h" | |
7 #include "blastem.h" | 8 #include "blastem.h" |
8 #include "nor.h" | 9 #include "nor.h" |
9 #include <stdlib.h> | 10 #include <stdlib.h> |
10 #include <ctype.h> | 11 #include <ctype.h> |
11 #include <time.h> | 12 #include <time.h> |
244 } | 245 } |
245 | 246 |
246 uint16_t read_dma_value(uint32_t address) | 247 uint16_t read_dma_value(uint32_t address) |
247 { | 248 { |
248 genesis_context *genesis = (genesis_context *)current_system; | 249 genesis_context *genesis = (genesis_context *)current_system; |
250 address *= 2; | |
249 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area | 251 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area |
250 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) { | 252 if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) { |
251 return 0; | 253 return 0; |
252 } | 254 } |
253 | 255 if (genesis->expansion) { |
254 //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2 | 256 segacd_context *cd = genesis->expansion; |
255 return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k); | 257 uint32_t word_ram = cd->base + 0x200000; |
258 uint32_t word_ram_end = cd->base + 0x240000; | |
259 if (address >= word_ram && address < word_ram_end) { | |
260 //FIXME: first word should just be garbage | |
261 address -= 2; | |
262 } | |
263 } | |
264 | |
265 return read_word(address, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k); | |
256 } | 266 } |
257 | 267 |
258 static uint16_t get_open_bus_value(system_header *system) | 268 static uint16_t get_open_bus_value(system_header *system) |
259 { | 269 { |
260 genesis_context *genesis = (genesis_context *)system; | 270 genesis_context *genesis = (genesis_context *)system; |
410 | 420 |
411 #include <limits.h> | 421 #include <limits.h> |
412 #define ADJUST_BUFFER (8*MCLKS_LINE*313) | 422 #define ADJUST_BUFFER (8*MCLKS_LINE*313) |
413 #define MAX_NO_ADJUST (UINT_MAX-ADJUST_BUFFER) | 423 #define MAX_NO_ADJUST (UINT_MAX-ADJUST_BUFFER) |
414 | 424 |
415 m68k_context * sync_components(m68k_context * context, uint32_t address) | 425 static m68k_context *sync_components(m68k_context * context, uint32_t address) |
416 { | 426 { |
417 genesis_context * gen = context->system; | 427 genesis_context * gen = context->system; |
418 vdp_context * v_context = gen->vdp; | 428 vdp_context * v_context = gen->vdp; |
419 z80_context * z_context = gen->z80; | 429 z80_context * z_context = gen->z80; |
420 #ifdef REFRESH_EMULATION | 430 #ifdef REFRESH_EMULATION |
431 sync_sound(gen, mclks); | 441 sync_sound(gen, mclks); |
432 vdp_run_context(v_context, mclks); | 442 vdp_run_context(v_context, mclks); |
433 io_run(gen->io.ports, mclks); | 443 io_run(gen->io.ports, mclks); |
434 io_run(gen->io.ports + 1, mclks); | 444 io_run(gen->io.ports + 1, mclks); |
435 io_run(gen->io.ports + 2, mclks); | 445 io_run(gen->io.ports + 2, mclks); |
446 if (gen->expansion) { | |
447 scd_run(gen->expansion, gen_cycle_to_scd(mclks, gen)); | |
448 } | |
436 if (mclks >= gen->reset_cycle) { | 449 if (mclks >= gen->reset_cycle) { |
437 gen->reset_requested = 1; | 450 gen->reset_requested = 1; |
438 context->should_return = 1; | 451 context->should_return = 1; |
439 gen->reset_cycle = CYCLE_NEVER; | 452 gen->reset_cycle = CYCLE_NEVER; |
440 } | 453 } |
468 gen->psg->cycles -= deduction; | 481 gen->psg->cycles -= deduction; |
469 if (gen->reset_cycle != CYCLE_NEVER) { | 482 if (gen->reset_cycle != CYCLE_NEVER) { |
470 gen->reset_cycle -= deduction; | 483 gen->reset_cycle -= deduction; |
471 } | 484 } |
472 event_cycle_adjust(mclks, deduction); | 485 event_cycle_adjust(mclks, deduction); |
486 if (gen->expansion) { | |
487 scd_adjust_cycle(gen->expansion, deduction); | |
488 } | |
473 gen->last_flush_cycle -= deduction; | 489 gen->last_flush_cycle -= deduction; |
474 } | 490 } |
475 } else if (mclks - gen->last_flush_cycle > gen->soft_flush_cycles) { | 491 } else if (mclks - gen->last_flush_cycle > gen->soft_flush_cycles) { |
476 event_soft_flush(mclks); | 492 event_soft_flush(mclks); |
477 gen->last_flush_cycle = mclks; | 493 gen->last_flush_cycle = mclks; |
1408 adjust_int_cycle(gen->m68k, gen->vdp); | 1424 adjust_int_cycle(gen->m68k, gen->vdp); |
1409 start_68k_context(gen->m68k, pc); | 1425 start_68k_context(gen->m68k, pc); |
1410 } else { | 1426 } else { |
1411 if (gen->header.enter_debugger) { | 1427 if (gen->header.enter_debugger) { |
1412 gen->header.enter_debugger = 0; | 1428 gen->header.enter_debugger = 0; |
1413 uint32_t address = gen->cart[2] << 16 | gen->cart[3]; | 1429 uint32_t address = read_word(4, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k) << 16 |
1430 | read_word(6, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen, gen->m68k); | |
1414 insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter); | 1431 insert_breakpoint(gen->m68k, address, gen->header.debugger_type == DEBUGGER_NATIVE ? debugger : gdb_debug_enter); |
1415 } | 1432 } |
1416 m68k_reset(gen->m68k); | 1433 m68k_reset(gen->m68k); |
1417 } | 1434 } |
1418 handle_reset_requests(gen); | 1435 handle_reset_requests(gen); |
1745 base[address] = value; | 1762 base[address] = value; |
1746 } | 1763 } |
1747 return context; | 1764 return context; |
1748 } | 1765 } |
1749 | 1766 |
1750 genesis_context *alloc_init_genesis(rom_info *rom, void *main_rom, void *lock_on, uint32_t system_opts, uint8_t force_region) | 1767 static genesis_context *shared_init(uint32_t system_opts, rom_info *rom, uint8_t force_region) |
1751 { | 1768 { |
1752 static memmap_chunk z80_map[] = { | 1769 static memmap_chunk z80_map[] = { |
1753 { 0x0000, 0x4000, 0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, NULL, NULL, NULL, NULL }, | 1770 { 0x0000, 0x4000, 0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, NULL, NULL, NULL, NULL }, |
1754 { 0x8000, 0x10000, 0x7FFF, 0, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, | 1771 { 0x8000, 0x10000, 0x7FFF, 0, 0, 0, NULL, NULL, NULL, z80_read_bank, z80_write_bank}, |
1755 { 0x4000, 0x6000, 0x0003, 0, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, | 1772 { 0x4000, 0x6000, 0x0003, 0, 0, 0, NULL, NULL, NULL, z80_read_ym, z80_write_ym}, |
1756 { 0x6000, 0x6100, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, | 1773 { 0x6000, 0x6100, 0xFFFF, 0, 0, 0, NULL, NULL, NULL, NULL, z80_write_bank_reg}, |
1757 { 0x7F00, 0x8000, 0x00FF, 0, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} | 1774 { 0x7F00, 0x8000, 0x00FF, 0, 0, 0, NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write} |
1758 }; | 1775 }; |
1776 | |
1777 char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval; | |
1778 if (!m68k_divider) { | |
1779 m68k_divider = "7"; | |
1780 } | |
1781 MCLKS_PER_68K = atoi(m68k_divider); | |
1782 if (!MCLKS_PER_68K) { | |
1783 MCLKS_PER_68K = 7; | |
1784 } | |
1785 | |
1759 genesis_context *gen = calloc(1, sizeof(genesis_context)); | 1786 genesis_context *gen = calloc(1, sizeof(genesis_context)); |
1760 gen->header.set_speed_percent = set_speed_percent; | 1787 gen->header.set_speed_percent = set_speed_percent; |
1761 gen->header.start_context = start_genesis; | 1788 gen->header.start_context = start_genesis; |
1762 gen->header.resume_context = resume_genesis; | 1789 gen->header.resume_context = resume_genesis; |
1763 gen->header.load_save = load_save; | 1790 gen->header.load_save = load_save; |
1829 gen->z80 = calloc(1, sizeof(z80_context)); | 1856 gen->z80 = calloc(1, sizeof(z80_context)); |
1830 #endif | 1857 #endif |
1831 | 1858 |
1832 gen->z80->system = gen; | 1859 gen->z80->system = gen; |
1833 gen->z80->mem_pointers[0] = gen->zram; | 1860 gen->z80->mem_pointers[0] = gen->zram; |
1834 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = (uint8_t *)main_rom; | 1861 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = NULL; |
1835 | 1862 |
1836 gen->cart = main_rom; | |
1837 gen->lock_on = lock_on; | |
1838 gen->work_ram = calloc(2, RAM_WORDS); | 1863 gen->work_ram = calloc(2, RAM_WORDS); |
1839 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) | 1864 if (!strcmp("random", tern_find_path_default(config, "system\0ram_init\0", (tern_val){.ptrval = "zero"}, TVAL_PTR).ptrval)) |
1840 { | 1865 { |
1841 srand(time(NULL)); | 1866 srand(time(NULL)); |
1842 for (int i = 0; i < RAM_WORDS; i++) | 1867 for (int i = 0; i < RAM_WORDS; i++) |
1862 for (int i = 0; i < gen->vdp->vsram_size; i++) | 1887 for (int i = 0; i < gen->vdp->vsram_size; i++) |
1863 { | 1888 { |
1864 gen->vdp->vsram[i] = rand(); | 1889 gen->vdp->vsram[i] = rand(); |
1865 } | 1890 } |
1866 } | 1891 } |
1867 setup_io_devices(config, rom, &gen->io); | 1892 |
1893 return gen; | |
1894 } | |
1895 | |
1896 static memmap_chunk base_map[] = { | |
1897 {0xE00000, 0x1000000, 0xFFFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, | |
1898 NULL, NULL, NULL, NULL}, | |
1899 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, 0, NULL, | |
1900 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, | |
1901 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, | |
1902 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, 0, NULL, | |
1903 (read_16_fun)io_read_w, (write_16_fun)io_write_w, | |
1904 (read_8_fun)io_read, (write_8_fun)io_write}, | |
1905 {0x000000, 0xFFFFFF, 0xFFFFFF, 0, 0, 0, NULL, | |
1906 (read_16_fun)unused_read, (write_16_fun)unused_write, | |
1907 (read_8_fun)unused_read_b, (write_8_fun)unused_write_b} | |
1908 }; | |
1909 const size_t base_chunks = sizeof(base_map)/sizeof(*base_map); | |
1910 | |
1911 genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region) | |
1912 { | |
1913 tern_node *rom_db = get_rom_db(); | |
1914 rom_info info = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, base_chunks); | |
1915 rom = info.rom; | |
1916 rom_size = info.rom_size; | |
1917 #ifndef BLASTEM_BIG_ENDIAN | |
1918 byteswap_rom(rom_size, rom); | |
1919 if (lock_on) { | |
1920 byteswap_rom(lock_on_size, lock_on); | |
1921 } | |
1922 #endif | |
1923 char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval; | |
1924 if (!m68k_divider) { | |
1925 m68k_divider = "7"; | |
1926 } | |
1927 MCLKS_PER_68K = atoi(m68k_divider); | |
1928 if (!MCLKS_PER_68K) { | |
1929 MCLKS_PER_68K = 7; | |
1930 } | |
1931 genesis_context *gen = shared_init(ym_opts, &info, force_region); | |
1932 gen->z80->mem_pointers[1] = gen->z80->mem_pointers[2] = rom; | |
1933 | |
1934 gen->cart = rom; | |
1935 gen->lock_on = lock_on; | |
1936 | |
1937 setup_io_devices(config, &info, &gen->io); | |
1868 gen->header.has_keyboard = io_has_keyboard(&gen->io); | 1938 gen->header.has_keyboard = io_has_keyboard(&gen->io); |
1869 | 1939 gen->mapper_type = info.mapper_type; |
1870 gen->mapper_type = rom->mapper_type; | 1940 gen->save_type = info.save_type; |
1871 gen->save_type = rom->save_type; | |
1872 if (gen->save_type != SAVE_NONE) { | 1941 if (gen->save_type != SAVE_NONE) { |
1873 gen->save_ram_mask = rom->save_mask; | 1942 gen->save_ram_mask = info.save_mask; |
1874 gen->save_size = rom->save_size; | 1943 gen->save_size = info.save_size; |
1875 gen->save_storage = rom->save_buffer; | 1944 gen->save_storage = info.save_buffer; |
1876 gen->eeprom_map = rom->eeprom_map; | 1945 gen->eeprom_map = info.eeprom_map; |
1877 gen->num_eeprom = rom->num_eeprom; | 1946 gen->num_eeprom = info.num_eeprom; |
1878 if (gen->save_type == SAVE_I2C) { | 1947 if (gen->save_type == SAVE_I2C) { |
1879 eeprom_init(&gen->eeprom, gen->save_storage, gen->save_size); | 1948 eeprom_init(&gen->eeprom, gen->save_storage, gen->save_size); |
1880 } else if (gen->save_type == SAVE_NOR) { | 1949 } else if (gen->save_type == SAVE_NOR) { |
1881 memcpy(&gen->nor, rom->nor, sizeof(gen->nor)); | 1950 memcpy(&gen->nor, info.nor, sizeof(gen->nor)); |
1882 //nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus); | 1951 //nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, info.save_page_size, info.save_product_id, info.save_bus); |
1883 } | 1952 } |
1884 } else { | 1953 } else { |
1885 gen->save_storage = NULL; | 1954 gen->save_storage = NULL; |
1886 } | 1955 } |
1887 | 1956 |
1888 gen->mapper_start_index = rom->mapper_start_index; | 1957 gen->mapper_start_index = info.mapper_start_index; |
1958 | |
1959 tern_node *model = get_model(config, SYSTEM_GENESIS); | |
1960 uint8_t tmss = !strcmp(tern_find_ptr_default(model, "tmss", "off"), "on"); | |
1889 | 1961 |
1890 //This must happen before we generate memory access functions in init_m68k_opts | 1962 //This must happen before we generate memory access functions in init_m68k_opts |
1891 uint8_t next_ptr_index = 0; | 1963 uint8_t next_ptr_index = 0; |
1892 uint32_t tmss_min_alloc = 16 * 1024; | 1964 uint32_t tmss_min_alloc = 16 * 1024; |
1893 for (int i = 0; i < rom->map_chunks; i++) | 1965 for (int i = 0; i < info.map_chunks; i++) |
1894 { | 1966 { |
1895 if (rom->map[i].start == 0xE00000) { | 1967 if (info.map[i].start == 0xE00000) { |
1896 rom->map[i].buffer = gen->work_ram; | 1968 info.map[i].buffer = gen->work_ram; |
1897 if (!tmss) { | 1969 if (!tmss) { |
1898 break; | 1970 break; |
1899 } | 1971 } |
1900 } | 1972 } |
1901 if (rom->map[i].flags & MMAP_PTR_IDX && rom->map[i].ptr_index >= next_ptr_index) { | 1973 if (info.map[i].flags & MMAP_PTR_IDX && info.map[i].ptr_index >= next_ptr_index) { |
1902 next_ptr_index = rom->map[i].ptr_index + 1; | 1974 next_ptr_index = info.map[i].ptr_index + 1; |
1903 } | 1975 } |
1904 if (rom->map[i].start < 0x400000 && rom->map[i].read_16 != unused_read) { | 1976 if (info.map[i].start < 0x400000 && info.map[i].read_16 != unused_read) { |
1905 uint32_t highest_offset = (rom->map[i].end & rom->map[i].mask) + 1; | 1977 uint32_t highest_offset = (info.map[i].end & info.map[i].mask) + 1; |
1906 if (highest_offset > tmss_min_alloc) { | 1978 if (highest_offset > tmss_min_alloc) { |
1907 tmss_min_alloc = highest_offset; | 1979 tmss_min_alloc = highest_offset; |
1908 } | 1980 } |
1909 } | 1981 } |
1910 } | 1982 } |
1939 { | 2011 { |
1940 memcpy(buffer + dst, buffer, dst + tmss_size > tmss_min_alloc ? tmss_min_alloc - dst : tmss_size); | 2012 memcpy(buffer + dst, buffer, dst + tmss_size > tmss_min_alloc ? tmss_min_alloc - dst : tmss_size); |
1941 } | 2013 } |
1942 //modify mappings for ROM space to point to the TMSS ROM and fixup flags to allow switching back and forth | 2014 //modify mappings for ROM space to point to the TMSS ROM and fixup flags to allow switching back and forth |
1943 //WARNING: This code makes some pretty big assumptions about the kinds of map chunks it will encounter | 2015 //WARNING: This code makes some pretty big assumptions about the kinds of map chunks it will encounter |
1944 for (int i = 0; i < rom->map_chunks; i++) | 2016 for (int i = 0; i < info.map_chunks; i++) |
1945 { | 2017 { |
1946 if (rom->map[i].start < 0x400000 && rom->map[i].read_16 != unused_read) { | 2018 if (info.map[i].start < 0x400000 && info.map[i].read_16 != unused_read) { |
1947 if (rom->map[i].flags == MMAP_READ) { | 2019 if (info.map[i].flags == MMAP_READ) { |
1948 //Normal ROM | 2020 //Normal ROM |
1949 rom->map[i].flags |= MMAP_PTR_IDX | MMAP_CODE; | 2021 info.map[i].flags |= MMAP_PTR_IDX | MMAP_CODE; |
1950 rom->map[i].ptr_index = next_ptr_index++; | 2022 info.map[i].ptr_index = next_ptr_index++; |
1951 if (rom->map[i].ptr_index >= NUM_MEM_AREAS) { | 2023 if (info.map[i].ptr_index >= NUM_MEM_AREAS) { |
1952 fatal_error("Too many memmap chunks with MMAP_PTR_IDX after TMSS remap\n"); | 2024 fatal_error("Too many memmap chunks with MMAP_PTR_IDX after TMSS remap\n"); |
1953 } | 2025 } |
1954 gen->tmss_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; | 2026 gen->tmss_pointers[info.map[i].ptr_index] = info.map[i].buffer; |
1955 rom->map[i].buffer = buffer + (rom->map[i].start & ~rom->map[i].mask & (tmss_size - 1)); | 2027 info.map[i].buffer = buffer + (info.map[i].start & ~info.map[i].mask & (tmss_size - 1)); |
1956 } else if (rom->map[i].flags & MMAP_PTR_IDX) { | 2028 } else if (info.map[i].flags & MMAP_PTR_IDX) { |
1957 //Sega mapper page or multi-game mapper | 2029 //Sega mapper page or multi-game mapper |
1958 gen->tmss_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; | 2030 gen->tmss_pointers[info.map[i].ptr_index] = info.map[i].buffer; |
1959 rom->map[i].buffer = buffer + (rom->map[i].start & ~rom->map[i].mask & (tmss_size - 1)); | 2031 info.map[i].buffer = buffer + (info.map[i].start & ~info.map[i].mask & (tmss_size - 1)); |
1960 if (rom->map[i].write_16) { | 2032 if (info.map[i].write_16) { |
1961 if (!gen->tmss_write_16) { | 2033 if (!gen->tmss_write_16) { |
1962 gen->tmss_write_16 = rom->map[i].write_16; | 2034 gen->tmss_write_16 = info.map[i].write_16; |
1963 gen->tmss_write_8 = rom->map[i].write_8; | 2035 gen->tmss_write_8 = info.map[i].write_8; |
1964 rom->map[i].write_16 = tmss_rom_write_16; | 2036 info.map[i].write_16 = tmss_rom_write_16; |
1965 rom->map[i].write_8 = tmss_rom_write_8; | 2037 info.map[i].write_8 = tmss_rom_write_8; |
1966 } else if (gen->tmss_write_16 == rom->map[i].write_16) { | 2038 } else if (gen->tmss_write_16 == info.map[i].write_16) { |
1967 rom->map[i].write_16 = tmss_rom_write_16; | 2039 info.map[i].write_16 = tmss_rom_write_16; |
1968 rom->map[i].write_8 = tmss_rom_write_8; | 2040 info.map[i].write_8 = tmss_rom_write_8; |
1969 } else { | 2041 } else { |
1970 warning("Chunk starting at %X has a write function, but we've already stored a different one for TMSS remap\n", rom->map[i].start); | 2042 warning("Chunk starting at %X has a write function, but we've already stored a different one for TMSS remap\n", info.map[i].start); |
1971 } | 2043 } |
1972 } | 2044 } |
1973 } else if ((rom->map[i].flags & (MMAP_READ | MMAP_WRITE)) == (MMAP_READ | MMAP_WRITE)) { | 2045 } else if ((info.map[i].flags & (MMAP_READ | MMAP_WRITE)) == (MMAP_READ | MMAP_WRITE)) { |
1974 //RAM or SRAM | 2046 //RAM or SRAM |
1975 rom->map[i].flags |= MMAP_PTR_IDX; | 2047 info.map[i].flags |= MMAP_PTR_IDX; |
1976 rom->map[i].ptr_index = next_ptr_index++; | 2048 info.map[i].ptr_index = next_ptr_index++; |
1977 gen->tmss_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; | 2049 gen->tmss_pointers[info.map[i].ptr_index] = info.map[i].buffer; |
1978 rom->map[i].buffer = buffer + (rom->map[i].start & ~rom->map[i].mask & (tmss_size - 1)); | 2050 info.map[i].buffer = buffer + (info.map[i].start & ~info.map[i].mask & (tmss_size - 1)); |
1979 if (!gen->tmss_write_offset || gen->tmss_write_offset == rom->map[i].start) { | 2051 if (!gen->tmss_write_offset || gen->tmss_write_offset == info.map[i].start) { |
1980 gen->tmss_write_offset = rom->map[i].start; | 2052 gen->tmss_write_offset = info.map[i].start; |
1981 rom->map[i].flags &= ~MMAP_WRITE; | 2053 info.map[i].flags &= ~MMAP_WRITE; |
1982 if (rom->map[i].flags & MMAP_ONLY_ODD) { | 2054 if (info.map[i].flags & MMAP_ONLY_ODD) { |
1983 rom->map[i].write_16 = tmss_odd_write_16; | 2055 info.map[i].write_16 = tmss_odd_write_16; |
1984 rom->map[i].write_8 = tmss_odd_write_8; | 2056 info.map[i].write_8 = tmss_odd_write_8; |
1985 } else if (rom->map[i].flags & MMAP_ONLY_EVEN) { | 2057 } else if (info.map[i].flags & MMAP_ONLY_EVEN) { |
1986 rom->map[i].write_16 = tmss_even_write_16; | 2058 info.map[i].write_16 = tmss_even_write_16; |
1987 rom->map[i].write_8 = tmss_even_write_8; | 2059 info.map[i].write_8 = tmss_even_write_8; |
1988 } else { | 2060 } else { |
1989 rom->map[i].write_16 = tmss_word_write_16; | 2061 info.map[i].write_16 = tmss_word_write_16; |
1990 rom->map[i].write_8 = tmss_word_write_8; | 2062 info.map[i].write_8 = tmss_word_write_8; |
1991 } | 2063 } |
1992 } else { | 2064 } else { |
1993 warning("Could not remap writes for chunk starting at %X for TMSS because write_offset is %X\n", rom->map[i].start, gen->tmss_write_offset); | 2065 warning("Could not remap writes for chunk starting at %X for TMSS because write_offset is %X\n", info.map[i].start, gen->tmss_write_offset); |
1994 } | 2066 } |
1995 } else if (rom->map[i].flags & MMAP_READ_CODE) { | 2067 } else if (info.map[i].flags & MMAP_READ_CODE) { |
1996 //NOR flash | 2068 //NOR flash |
1997 rom->map[i].flags |= MMAP_PTR_IDX; | 2069 info.map[i].flags |= MMAP_PTR_IDX; |
1998 rom->map[i].ptr_index = next_ptr_index++; | 2070 info.map[i].ptr_index = next_ptr_index++; |
1999 if (rom->map[i].ptr_index >= NUM_MEM_AREAS) { | 2071 if (info.map[i].ptr_index >= NUM_MEM_AREAS) { |
2000 fatal_error("Too many memmap chunks with MMAP_PTR_IDX after TMSS remap\n"); | 2072 fatal_error("Too many memmap chunks with MMAP_PTR_IDX after TMSS remap\n"); |
2001 } | 2073 } |
2002 gen->tmss_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; | 2074 gen->tmss_pointers[info.map[i].ptr_index] = info.map[i].buffer; |
2003 rom->map[i].buffer = buffer + (rom->map[i].start & ~rom->map[i].mask & (tmss_size - 1)); | 2075 info.map[i].buffer = buffer + (info.map[i].start & ~info.map[i].mask & (tmss_size - 1)); |
2004 if (!gen->tmss_write_16) { | 2076 if (!gen->tmss_write_16) { |
2005 gen->tmss_write_16 = rom->map[i].write_16; | 2077 gen->tmss_write_16 = info.map[i].write_16; |
2006 gen->tmss_write_8 = rom->map[i].write_8; | 2078 gen->tmss_write_8 = info.map[i].write_8; |
2007 gen->tmss_read_16 = rom->map[i].read_16; | 2079 gen->tmss_read_16 = info.map[i].read_16; |
2008 gen->tmss_read_8 = rom->map[i].read_8; | 2080 gen->tmss_read_8 = info.map[i].read_8; |
2009 rom->map[i].write_16 = tmss_rom_write_16; | 2081 info.map[i].write_16 = tmss_rom_write_16; |
2010 rom->map[i].write_8 = tmss_rom_write_8; | 2082 info.map[i].write_8 = tmss_rom_write_8; |
2011 rom->map[i].read_16 = tmss_rom_read_16; | 2083 info.map[i].read_16 = tmss_rom_read_16; |
2012 rom->map[i].read_8 = tmss_rom_read_8; | 2084 info.map[i].read_8 = tmss_rom_read_8; |
2013 } else if (gen->tmss_write_16 == rom->map[i].write_16) { | 2085 } else if (gen->tmss_write_16 == info.map[i].write_16) { |
2014 rom->map[i].write_16 = tmss_rom_write_16; | 2086 info.map[i].write_16 = tmss_rom_write_16; |
2015 rom->map[i].write_8 = tmss_rom_write_8; | 2087 info.map[i].write_8 = tmss_rom_write_8; |
2016 rom->map[i].read_16 = tmss_rom_read_16; | 2088 info.map[i].read_16 = tmss_rom_read_16; |
2017 rom->map[i].read_8 = tmss_rom_read_8; | 2089 info.map[i].read_8 = tmss_rom_read_8; |
2018 } else { | 2090 } else { |
2019 warning("Chunk starting at %X has a write function, but we've already stored a different one for TMSS remap\n", rom->map[i].start); | 2091 warning("Chunk starting at %X has a write function, but we've already stored a different one for TMSS remap\n", info.map[i].start); |
2020 } | 2092 } |
2021 } else { | 2093 } else { |
2022 warning("Didn't remap chunk starting at %X for TMSS because it has flags %X\n", rom->map[i].start, rom->map[i].flags); | 2094 warning("Didn't remap chunk starting at %X for TMSS because it has flags %X\n", info.map[i].start, info.map[i].flags); |
2023 } | 2095 } |
2024 } | 2096 } |
2025 } | 2097 } |
2026 gen->tmss_buffer = buffer; | 2098 gen->tmss_buffer = buffer; |
2027 } | 2099 } |
2100 memmap_chunk* map = info.map; | |
2101 uint32_t map_chunks = info.map_chunks; | |
2102 if (info.wants_cd) { | |
2103 segacd_context *cd = alloc_configure_segacd((system_media *)current_media(), 0, force_region, &info); | |
2104 gen->expansion = cd; | |
2105 gen->version_reg &= ~NO_DISK; | |
2106 cd->genesis = gen; | |
2107 uint32_t cd_chunks; | |
2108 memmap_chunk *cd_map = segacd_main_cpu_map(gen->expansion, 1, &cd_chunks); | |
2109 map_chunks = cd_chunks + info.map_chunks; | |
2110 map = calloc(map_chunks, sizeof(memmap_chunk)); | |
2111 memcpy(map, info.map, sizeof(memmap_chunk) * (info.map_chunks - 1)); | |
2112 memcpy(map + info.map_chunks - 1, cd_map, sizeof(memmap_chunk) * cd_chunks); | |
2113 memcpy(map + map_chunks - 1, info.map + info.map_chunks - 1, sizeof(memmap_chunk)); | |
2114 free(info.map); | |
2115 int max_ptr_index = -1; | |
2116 for (int i = 0; i < info.map_chunks - 1; i++) | |
2117 { | |
2118 if (map[i].flags & MMAP_PTR_IDX && map[i].ptr_index > max_ptr_index) { | |
2119 max_ptr_index = map[i].ptr_index; | |
2120 } | |
2121 } | |
2122 cd->memptr_start_index + max_ptr_index + 1; | |
2123 for (int i = info.map_chunks - 1; i < map_chunks - 1; i++) | |
2124 { | |
2125 if (map[i].flags & MMAP_PTR_IDX) { | |
2126 map[i].ptr_index += cd->memptr_start_index; | |
2127 } | |
2128 } | |
2129 cd->base = 0x400000; | |
2130 } | |
2028 | 2131 |
2029 m68k_options *opts = malloc(sizeof(m68k_options)); | 2132 m68k_options *opts = malloc(sizeof(m68k_options)); |
2030 init_m68k_opts(opts, rom->map, rom->map_chunks, MCLKS_PER_68K); | 2133 init_m68k_opts(opts, map, map_chunks, MCLKS_PER_68K, sync_components); |
2031 if (!strcmp(tern_find_ptr_default(model, "tas", "broken"), "broken")) { | 2134 if (!strcmp(tern_find_ptr_default(model, "tas", "broken"), "broken")) { |
2032 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; | 2135 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; |
2033 } | 2136 } |
2034 gen->m68k = init_68k_context(opts, NULL); | 2137 gen->m68k = init_68k_context(opts, NULL); |
2035 gen->m68k->system = gen; | 2138 gen->m68k->system = gen; |
2036 opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; | 2139 opts->address_log = (ym_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; |
2037 | 2140 |
2038 //This must happen after the 68K context has been allocated | 2141 //This must happen after the 68K context has been allocated |
2039 for (int i = 0; i < rom->map_chunks; i++) | 2142 for (int i = 0; i < map_chunks; i++) |
2040 { | 2143 { |
2041 if (rom->map[i].flags & MMAP_PTR_IDX) { | 2144 if (map[i].flags & MMAP_PTR_IDX) { |
2042 gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; | 2145 gen->m68k->mem_pointers[map[i].ptr_index] = map[i].buffer; |
2043 } | 2146 } |
2044 } | 2147 } |
2045 | 2148 |
2046 if (gen->mapper_type == MAPPER_SEGA) { | 2149 if (gen->mapper_type == MAPPER_SEGA) { |
2047 //initialize bank registers | 2150 //initialize bank registers |
2053 gen->reset_cycle = CYCLE_NEVER; | 2156 gen->reset_cycle = CYCLE_NEVER; |
2054 | 2157 |
2055 return gen; | 2158 return gen; |
2056 } | 2159 } |
2057 | 2160 |
2058 genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, uint32_t ym_opts, uint8_t force_region) | 2161 genesis_context *alloc_config_genesis_cdboot(system_media *media, uint32_t system_opts, uint8_t force_region) |
2059 { | 2162 { |
2060 static memmap_chunk base_map[] = { | 2163 tern_node *rom_db = get_rom_db(); |
2061 {0xE00000, 0x1000000, 0xFFFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, | 2164 rom_info info = configure_rom(rom_db, media->buffer, media->size, NULL, 0, base_map, base_chunks); |
2062 NULL, NULL, NULL, NULL}, | 2165 |
2063 {0xC00000, 0xE00000, 0x1FFFFF, 0, 0, 0, NULL, | 2166 segacd_context *cd = alloc_configure_segacd(media, system_opts, force_region, &info); |
2064 (read_16_fun)vdp_port_read, (write_16_fun)vdp_port_write, | 2167 genesis_context *gen = shared_init(system_opts, &info, force_region); |
2065 (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b}, | 2168 gen->cart = gen->lock_on = NULL; |
2066 {0xA00000, 0xA12000, 0x1FFFF, 0, 0, 0, NULL, | 2169 gen->save_storage = NULL; |
2067 (read_16_fun)io_read_w, (write_16_fun)io_write_w, | 2170 gen->save_type = SAVE_NONE; |
2068 (read_8_fun)io_read, (write_8_fun)io_write}, | 2171 gen->version_reg &= ~NO_DISK; |
2069 {0x000000, 0xFFFFFF, 0xFFFFFF, 0, 0, 0, NULL, | 2172 |
2070 (read_16_fun)unused_read, (write_16_fun)unused_write, | 2173 gen->expansion = cd; |
2071 (read_8_fun)unused_read_b, (write_8_fun)unused_write_b} | 2174 gen->version_reg &= ~NO_DISK; |
2072 }; | 2175 cd->genesis = gen; |
2073 static tern_node *rom_db; | 2176 setup_io_devices(config, &info, &gen->io); |
2074 if (!rom_db) { | 2177 |
2075 rom_db = load_rom_db(); | 2178 uint32_t cd_chunks; |
2076 } | 2179 memmap_chunk *cd_map = segacd_main_cpu_map(gen->expansion, 0, &cd_chunks); |
2077 rom_info info = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, sizeof(base_map)/sizeof(base_map[0])); | 2180 memmap_chunk *map = malloc(sizeof(memmap_chunk) * (cd_chunks + base_chunks)); |
2078 rom = info.rom; | 2181 memcpy(map, cd_map, sizeof(memmap_chunk) * cd_chunks); |
2079 rom_size = info.rom_size; | 2182 memcpy(map + cd_chunks, base_map, sizeof(memmap_chunk) * base_chunks); |
2080 #ifndef BLASTEM_BIG_ENDIAN | 2183 map[cd_chunks].buffer = gen->work_ram; |
2081 byteswap_rom(rom_size, rom); | 2184 uint32_t num_chunks = cd_chunks + base_chunks; |
2082 if (lock_on) { | 2185 |
2083 byteswap_rom(lock_on_size, lock_on); | 2186 m68k_options *opts = malloc(sizeof(m68k_options)); |
2084 } | 2187 init_m68k_opts(opts, map, num_chunks, MCLKS_PER_68K, sync_components); |
2085 #endif | 2188 //TODO: make this configurable |
2086 char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval; | 2189 opts->gen.flags |= M68K_OPT_BROKEN_READ_MODIFY; |
2087 if (!m68k_divider) { | 2190 gen->m68k = init_68k_context(opts, NULL); |
2088 m68k_divider = "7"; | 2191 gen->m68k->system = gen; |
2089 } | 2192 opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; |
2090 MCLKS_PER_68K = atoi(m68k_divider); | 2193 |
2091 if (!MCLKS_PER_68K) { | 2194 //This must happen after the 68K context has been allocated |
2092 MCLKS_PER_68K = 7; | 2195 for (int i = 0; i < num_chunks; i++) |
2093 } | 2196 { |
2094 return alloc_init_genesis(&info, rom, lock_on, ym_opts, force_region); | 2197 if (map[i].flags & MMAP_PTR_IDX) { |
2095 } | 2198 gen->m68k->mem_pointers[map[i].ptr_index] = map[i].buffer; |
2199 } | |
2200 } | |
2201 return gen; | |
2202 } |