Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. // DGen/SDL v1.29+
  2. // Megadrive C++ module - misc memory
  3.  
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <stdint.h>
  7. #include <assert.h>
  8. #include "md.h"
  9. #include "mem.h"
  10.  
  11. /**
  12.  * Read one byte from the memory space.
  13.  * @param a Address to read
  14.  * @return byte or 0 if invalid.
  15.  */
  16. uint8_t md::z80_read(uint16_t a)
  17. {
  18.         /* 0x0000-0x3fff: Z80 RAM */
  19.         if (a <= Z80_RAM_END)
  20.                 return z80ram[(a & 0x1fff)];
  21.         /* 0x4000-0x5fff: YM2612 */
  22.         if (a <= YM2612_RAM_END)
  23.                 return myfm_read(a);
  24.         /* 0x6000-0x6fff: bank register */
  25.         if (a <= BANK_RAM_END)
  26.                 return 0; /* invalid address */
  27.         /* 0x7000-0x7fff: PSG/VDP */
  28.         if (a <= PSGVDP_RAM_END)
  29.                 return 0; /* invalid address */
  30.         /* 0x8000-0xffff: M68K bank */
  31.         return misc_readbyte(z80_bank68k + (a & 0x7fff));
  32. }
  33.  
  34. /**
  35.  * Write one byte to the memory
  36.  * @param a Address to read
  37.  * @param d Data (byte) to write.
  38.  */
  39. void md::z80_write(uint16_t a, uint8_t d)
  40. {
  41.         /* 0x0000-0x3fff: Z80 RAM */
  42.         if (a <= Z80_RAM_END) {
  43.                 z80ram[(a & 0x1fff)] = d;
  44.                 return;
  45.         }
  46.         /* 0x4000-0x5fff: YM2612 */
  47.         if (a <= YM2612_RAM_END) {
  48.                 myfm_write(a, d, 1);
  49.                 return;
  50.         }
  51.         /* 0x6000-0x6fff: bank register */
  52.         if (a <= BANK_RAM_END) {
  53.                 uint32_t tmp;
  54.  
  55.                 if (a > 0x60ff)
  56.                         return; /* invalid address */
  57.                 tmp = (z80_bank68k >> 1);
  58.                 tmp |= ((d & 1) << 23);
  59.                 z80_bank68k = (tmp & 0xff8000);
  60.                 return;
  61.         }
  62.         /* 0x7000-0x7fff: PSG */
  63.         if (a <= PSGVDP_RAM_END) {
  64.                 if (a == 0x7f11) {
  65.                         mysn_write(d);
  66.                         return;
  67.                 }
  68.                 return; /* invalid address */
  69.         }
  70.         /* 0x8000-0xffff: M68K bank */
  71.         misc_writebyte((z80_bank68k + (a & 0x7fff)), d);
  72. }
  73.  
  74. /**
  75.  * Port read to Z80.
  76.  * This is a NOP
  77.  * @param a address (ignored)
  78.  * @return always returns 0xff
  79.  */
  80. uint8_t md::z80_port_read(uint16_t a)
  81. {
  82.         (void)a;
  83.         return 0xff;
  84. }
  85.  
  86. /**
  87.  * Port write to z80
  88.  * This is a Nop
  89.  * @param a address (ignored)
  90.  * @param d data (ignored)
  91.  */
  92. void md::z80_port_write(uint16_t a, uint8_t d)
  93. {
  94.         (void)a;
  95.         (void)d;
  96. }
  97.  
  98. uint8_t md::m68k_ROM_read(uint32_t a)
  99. {
  100.         /* save RAM */
  101.         if ((save_active) && (save_len) &&
  102.             (a >= save_start) && ((a - save_start) < save_len))
  103.                 return saveram[((a ^ 1) - save_start)];
  104.         /* ROM */
  105.         if (ROM_ADDR(a) < romlen)
  106.                 return rom[ROM_ADDR(a)];
  107.         /* empty area */
  108.         return 0;
  109. }
  110.  
  111. uint8_t md::m68k_IO_read(uint32_t a)
  112. {
  113.         /* Z80 */
  114.         if (a < 0xa10000) {
  115.                 if ((!z80_st_busreq) && (a < 0xa04000))
  116.                         return 0;
  117.                 return z80_read(a & 0xffff);
  118.         }
  119.         /* version */
  120.         if (a == 0xa10000)
  121.                 return 0;
  122.         if (a == 0xa10001) {
  123.                 uint8_t c = region;
  124.  
  125.                 /* If region hasn't been defined, guess it. */
  126.                 if (c == '\0')
  127.                         c = region_guess();
  128.                 region_info(c, 0, 0, 0, 0, &c);
  129.                 /* Remove PAL flag if we're not in PAL mode. */
  130.                 if (!pal)
  131.                         c &= ~0x40;
  132.                 return c;
  133.         }
  134.         /* data 1 (pad 0) */
  135.         if (a == 0xa10002)
  136.                 return 0;
  137.         if (a == 0xa10003) {
  138.                 if (aoo3_six == 3) {
  139.                         /* extended pad info */
  140.                         if (aoo3_toggle == 0)
  141.                                 return (((pad[0] >> 8) & 0x30) + 0x00);
  142.                         return ((pad[0] & 0x30) + 0x40 +
  143.                                 ((pad[0] >> 16) & 0x0f));
  144.                 }
  145.                 if (aoo3_toggle == 0) {
  146.                         if (aoo3_six == 4)
  147.                                 return (((pad[0] >> 8) & 0x30) +
  148.                                         0x00 + 0x0f);
  149.                         return (((pad[0] >> 8) & 0x30) +
  150.                                 0x00 + (pad[0] & 0x03));
  151.                 }
  152.                 return ((pad[0] & 0x30) + 0x40 + (pad[0] & 0x0f));
  153.         }
  154.         /* data 2 (pad 1) */
  155.         if (a == 0xa10004)
  156.                 return 0;
  157.         if (a == 0xa10005) {
  158.                 if (aoo5_six == 3) {
  159.                         /* extended pad info */
  160.                         if (aoo5_toggle == 0)
  161.                                 return (((pad[1] >> 8) & 0x30) + 0x00);
  162.                         return ((pad[1] & 0x30) + 0x40 +
  163.                                 ((pad[1] >> 16) & 0x0f));
  164.                 }
  165.                 if (aoo5_toggle == 0) {
  166.                         if (aoo5_six == 4)
  167.                                 return (((pad[1] >> 8) & 0x30) +
  168.                                         0x00 + 0x0f);
  169.                         return (((pad[1] >> 8) & 0x30) +
  170.                                 0x00 + (pad[1] & 0x03));
  171.                 }
  172.                 return ((pad[1] & 0x30) + 0x40 + (pad[1] & 0x0f));
  173.         }
  174.         /* data 3 (exp) */
  175.         if (a == 0xa10006)
  176.                 return 0;
  177.         if (a == 0xa10007)
  178.                 return 0xff;
  179.         /* ctrl 1 */
  180.         if (a == 0xa10008)
  181.                 return 0;
  182.         if (a == 0xa10009)
  183.                 return pad_com[0];
  184.         /* ctrl 2 */
  185.         if (a == 0xa1000a)
  186.                 return 0;
  187.         if (a == 0xa1000b)
  188.                 return pad_com[1];
  189.         /* ctrl 3 */
  190.         if ((a & 0xa1000c) == 0xa1000c)
  191.                 return 0;
  192.         /* memory mode */
  193.         if ((a & 0xfffffe) == 0xa11000)
  194.                 return 0xff;
  195.         /* Z80 BUSREQ */
  196.         if ((a & 0xffff01) == 0xa11100)
  197.                 return (!z80_st_busreq | ((m68k_read_pc() >> 8) & 0xfe));
  198.         if ((a & 0xffff01) == 0xa11101)
  199.                 return (m68k_read_pc() & 0xff);
  200.         /* Z80 RESET */
  201.         if ((a & 0xffff01) == 0xa11200)
  202.                 return (m68k_read_pc() >> 8);
  203.         if ((a & 0xffff01) == 0xa11201)
  204.                 return (m68k_read_pc() & 0xff);
  205.         return 0; /* invalid address */
  206. }
  207.  
  208. uint8_t md::m68k_VDP_read(uint32_t a)
  209. {
  210.         a &= 0xe700ff;
  211.         /* data */
  212.         if (a < 0xc00004) {
  213.                 if (a & 0x01)
  214.                         return 0;
  215.                 vdp.cmd_pending = false;
  216.                 return vdp.readbyte();
  217.         }
  218.         /* control */
  219.         if (a < 0xc00008) {
  220.                 vdp.cmd_pending = false;
  221.                 if ((a & 0x01) == 0)
  222.                         return coo4;
  223.                 return coo5;
  224.         }
  225.         /* HV counters */
  226.         if (a == 0xc00008)
  227.                 return calculate_coo8();
  228.         if (a == 0xc00009)
  229.                 return calculate_coo9();
  230.         /* PSG */
  231.         if (a == 0xc00011)
  232.                 return (0);
  233.         return 0; /* invalid address */
  234. }
  235.  
  236. /**
  237.  * Read a byte from the m68Ks ram.
  238.  * @param a Address to read.
  239.  */
  240. uint8_t md::misc_readbyte(uint32_t a)
  241. {
  242.         /* clip to 24-bit */
  243.         a &= 0x00ffffff;
  244.         /* 0x000000-0x7fffff: ROM */
  245.         if (a <= M68K_ROM_END) {
  246.                 return m68k_ROM_read(a);
  247.         }
  248. #ifdef WITH_PICO
  249.         /* 0x800000-0x80001f: Sega Pico I/O area */
  250.         if ((pico_enabled) &&
  251.             ((a >= 0x800000) && (a <= 0x80001f))) {
  252.                 a &= 0x1f;
  253.                 switch(a) {
  254.                 case 1: // Version register
  255.                         switch (region) {
  256.                         case 'J': // Japan
  257.                                 return 0;
  258.                         case 'E': // Europe
  259.                                 return 32;
  260.                         case 'U': // USA
  261.                                 return 64;
  262.                         }
  263.                         return 0;
  264.                 case 3: // Pico pad
  265.                         return pad[0];
  266.                 case 5: // MSB of X coordinate for pen
  267.                         return pico_pen_coords[0] >> 8;
  268.                 case 7: // LSB of X coordinate for pen
  269.                         return pico_pen_coords[0] & 0xff;
  270.                 case 9: // MSB of Y coordinate for pen
  271.                         return pico_pen_coords[1] >> 8;
  272.                 case 0xB: // LSB of Y coordinate for pen
  273.                         return pico_pen_coords[1] & 0xff;
  274.                 }
  275.         }
  276.         /* 0x800020-0xafffff: Sega Pico empty area */
  277.         if ((pico_enabled) &&
  278.             (a <= M68K_IO_END))
  279.                 return 0;
  280. #endif
  281.         /* 0x800000-0x9fffff: empty area */
  282.         if (a <= M68K_EMPTY1_END) {
  283.                 /*
  284.                  * http://cgfm2.emuviews.com/txt/gen-hw.txt
  285.                  * see section 1 point 3 for what these addresses do.
  286.                  */
  287.                 return 0;
  288.         }
  289.         /* 0xa00000-0xafffff: system I/O and control */
  290.         if (a <= M68K_IO_END) {
  291.                 return m68k_IO_read(a);
  292.         }
  293.         /* 0xb00000-0xbfffff: empty area */
  294.         if (a <= M68K_EMPTY2_END)
  295.                 return 0;
  296.         /* 0xc00000-0xdfffff: VDP/PSG */
  297.         if (a <= M68K_VDP_END) {
  298.                 return m68k_VDP_read(a);
  299.         }
  300.         /* 0xe00000-0xfeffff: invalid addresses, mirror RAM */
  301.         /* 0xff0000-0xffffff: RAM */
  302.         return ram[((a ^ 1) & 0xffff)];
  303. }
  304.  
  305. void md::m68k_ROM_write(uint32_t a, uint8_t d)
  306. {
  307.         /* save RAM */
  308.         if ((!save_prot) && (save_len) &&
  309.             (a >= save_start) && ((a - save_start) < save_len))
  310.                 saveram[((a ^ 1) - save_start)] = d;
  311. #ifdef WITH_DEBUGGER
  312.         /* Allow debugger to write to the ROM. */
  313.         if ((debug_trap) && (ROM_ADDR(a) < romlen))
  314.                 rom[ROM_ADDR(a)] = d;
  315. #endif
  316. }
  317.  
  318. void md::m68k_IO_write(uint32_t a, uint8_t d)
  319. {
  320.         /* Z80 */
  321.         if (a < 0xa10000) {
  322.                 if ((!z80_st_busreq) && (a < 0xa04000))
  323.                         return;
  324.                 z80_write((a & 0xffff), d);
  325.                 return;
  326.         }
  327.         if (a == 0xa11100) {
  328.                 /* Z80 BUSREQ */
  329.                 if (d & 0x01)
  330.                         m68k_busreq_request();
  331.                 else
  332.                         m68k_busreq_cancel();
  333.                 return;
  334.         }
  335.         if (a == 0xa11101)
  336.                 return;
  337.         /* Z80 RESET */
  338.         if (a == 0xa11200) {
  339.                 /* cancel RESET state if nonzero */
  340.                 if (d)
  341.                         z80_st_reset = 0;
  342.                 else if (z80_st_reset == 0) {
  343.                         if (z80_st_busreq == 0)
  344.                                 z80_sync(0);
  345.                         z80_st_reset = 1;
  346.                         z80_reset();
  347.                         fm_reset();
  348.                 }
  349.                 return;
  350.         }
  351.         if (a == 0xa11201)
  352.                 return;
  353.         /* I/O port access */
  354.         if (a < 0xa1000d) {
  355.                 if (a == 0xa10003) {
  356.                         if ((aoo3_six >= 0) && ((d & 0x40) == 0) &&
  357.                             (aoo3_toggle))
  358.                                 ++aoo3_six;
  359.                         if (aoo3_six > 0xc00000)
  360.                                 aoo3_six &= ~0x400000;
  361.                         /* keep it circling around a high value */
  362.                         if (d & 0x40)
  363.                                 aoo3_toggle = 1;
  364.                         else
  365.                                 aoo3_toggle = 0;
  366.                         aoo3_six_timeout = 0;
  367.                         return;
  368.                 }
  369.                 if (a == 0xa10005) {
  370.                         if ((aoo5_six >= 0) && ((d & 0x40) == 0) &&
  371.                             (aoo5_toggle))
  372.                                 ++aoo5_six;
  373.                         if (aoo5_six > 0xc00000)
  374.                                 aoo5_six &= ~0x400000;
  375.                         /* keep it circling around a high value */
  376.                         if (d & 0x40)
  377.                                 aoo5_toggle = 1;
  378.                         else
  379.                                 aoo5_toggle = 0;
  380.                         aoo5_six_timeout = 0;
  381.                         return;
  382.                 }
  383.                 return;
  384.         }
  385.         /* save RAM status */
  386.         if (a == 0xa130f1) {
  387.                 /*
  388.                   Bit 0: 0 = ROM active, 1 = SRAM active
  389.                   Bit 1: 0 = writable protect
  390.                 */
  391.                 save_active = (d & 1);
  392.                 save_prot = (d & 2);
  393.                 return;
  394.         }
  395.         return;
  396. }
  397.  
  398. /**
  399.  * write a byte to the m68Ks ram.
  400.  * @param a Address to write.
  401.  * @param d Date (byte) two write.
  402.  */
  403. void md::misc_writebyte(uint32_t a, uint8_t d)
  404. {
  405.         /* clip to 24-bit */
  406.         a &= 0x00ffffff;
  407.         /* 0x000000-0x7fffff: ROM */
  408.         if (a <= M68K_ROM_END) {
  409.                 m68k_ROM_write(a, d);
  410.                 return;
  411.         }
  412.         /* 0x800000-0x9fffff: empty area */
  413.         if (a <= M68K_EMPTY1_END)
  414.                 return;
  415.         /* 0xa00000-0xafffff: system I/O and control */
  416.         if (a <= M68K_IO_END) {
  417.                 m68k_IO_write(a, d);
  418.                 return;
  419.         }
  420.         /* 0xb00000-0xbfffff: empty area */
  421.         if (a <= M68K_EMPTY2_END)
  422.                 return;
  423.         /* 0xc00000-0xdfffff: VDP/PSG */
  424.         if (a < M68K_VDP_END) {
  425.                 a &= 0xe700ff;
  426.                 if (a < 0xc00008) {
  427.                         misc_writeword(a, (d | (d << 8)));
  428.                         return;
  429.                 }
  430.                 /* PSG */
  431.                 if (a == 0xc00011)
  432.                         mysn_write(d);
  433.                 return;
  434.         }
  435.         /* 0xe00000-0xfeffff: invalid addresses, mirror RAM */
  436.         /* 0xff0000-0xffffff: RAM */
  437.         ram[((a ^ 1) & 0xffff)] = d;
  438. }
  439.  
  440.  
  441. /**
  442.  * Read a word from the m68k memory.
  443.  * There are quirks with word wide reads see section 1.2 of
  444.  * http://cgfm2.emuviews.com/txt/gen-hw.txt
  445.  * @param a Address to read
  446.  * @return word from memory.
  447.  */
  448. uint16_t md::misc_readword(uint32_t a)
  449. {
  450.         uint16_t ret;
  451.  
  452.         a &= 0x00ffffff;
  453.         /* BUSREQ */
  454.         if ((a & 0xffff00) == 0xa11100)
  455.                 return ((!z80_st_busreq << 8) | (m68k_read_pc() & 0xfeff));
  456.         /* RESET */
  457.         if ((a & 0xffff00) == 0xa11200)
  458.                 return m68k_read_pc();
  459.         /* VDP */
  460.         if ((a >= 0xc00000) && (a < 0xe00000)) {
  461.                 a &= 0xe700ff;
  462.                 if (a < 0xc00004) {
  463.                         if (a & 0x01)
  464.                                 return 0;
  465.                         vdp.cmd_pending = false;
  466.                         return vdp.readword();
  467.                 }
  468.                 if (a < 0xc00008) {
  469.                         if (a & 0x01)
  470.                                 return 0;
  471.                         return (((coo4 & 0xff) << 8) | (coo5 & 0xff));
  472.                 }
  473.                 if (a == 0xc00008) {
  474.                         if (a & 0x01)
  475.                                 return 0;
  476.                         return ((calculate_coo8() << 8) |
  477.                                 (calculate_coo9() & 0xff));
  478.                 }
  479.         }
  480.         /* else pass onto readbyte */
  481.         ret = (misc_readbyte(a) << 8);
  482.         ret |= misc_readbyte(a + 1);
  483.         return ret;
  484. }
  485.  
  486. /**
  487.  * Write a word to m68k memory
  488.  * @param a Address to write to.
  489.  * @param d Data to write.
  490.  */
  491. void md::misc_writeword(uint32_t a, uint16_t d)
  492. {
  493.         a &= 0x00ffffff;
  494.         /* Z80 */
  495.         if ((a >= 0xa00000) && (a < 0xa10000)) {
  496.                 if ((!z80_st_busreq) && (a < 0xa04000))
  497.                         return;
  498.                 z80_write((a & 0xffff), (d >> 8));
  499.                 return;
  500.         }
  501.         /* BUSREQ and RESET */
  502.         if ((a == 0xa11100) ||
  503.             (a == 0xa11200)) {
  504.                 misc_writebyte(a, (d >> 8));
  505.                 return;
  506.         }
  507.         /* VDP */
  508.         if ((a >= 0xc00000) && (a < 0xe00000)) {
  509.                 a &= 0xe700ff;
  510.                 if (a < 0xc00004) {
  511.                         if (a & 0x01)
  512.                                 return;
  513.                         vdp.writeword(d);
  514.                         vdp.cmd_pending = false;
  515.                         return;
  516.                 }
  517.                 if (a < 0xc00008) {
  518.                         if (a & 0x01)
  519.                                 return;
  520.                         /* second half of a command */
  521.                         if (vdp.cmd_pending) {
  522.                                 vdp.command(d);
  523.                                 return;
  524.                         }
  525.                         /* register write */
  526.                         if ((d & 0xc000) == 0x8000) {
  527.                                 uint8_t addr = ((d >> 8) & 0x1f);
  528.                                 vdp.write_reg(addr, d);
  529.                                 return;
  530.                         }
  531.                         /* first half of a command */
  532.                         vdp.command(d);
  533.                         vdp.cmd_pending = true;
  534.                         return;
  535.                 }
  536.         }
  537.         /* else pass onto writebyte */
  538.         misc_writebyte(a, (d >> 8));
  539.         misc_writebyte((a + 1), (d & 0xff));
  540. }
  541.  
  542. #ifdef WITH_MUSA
  543.  
  544. // read/write functions called by the CPU to access memory.
  545. // while values used are 32 bits, only the appropriate number
  546. // of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
  547. // of value should be written to memory).
  548. // address will be a 24-bit value.
  549.  
  550. /* Read from anywhere */
  551. extern "C" unsigned int m68k_read_memory_8(unsigned int address)
  552. {
  553.         return md::md_musa->misc_readbyte(address);
  554. }
  555.  
  556. extern "C" unsigned int m68k_read_memory_16(unsigned int address)
  557. {
  558.         return md::md_musa->misc_readword(address);
  559. }
  560.  
  561. extern "C" unsigned int m68k_read_memory_32(unsigned int address)
  562. {
  563.         return ((md::md_musa->misc_readword(address) << 16) |
  564.                 (md::md_musa->misc_readword(address + 2) & 0xffff));
  565. }
  566.  
  567. /* Read data immediately following the PC */
  568. extern "C" unsigned int m68k_read_immediate_8(unsigned int address)
  569. {
  570.         return m68k_read_memory_8(address);
  571. }
  572.  
  573. extern "C" unsigned int m68k_read_immediate_16(unsigned int address)
  574. {
  575.         return m68k_read_memory_16(address);
  576. }
  577.  
  578. extern "C" unsigned int m68k_read_immediate_32(unsigned int address)
  579. {
  580.         return m68k_read_memory_32(address);
  581. }
  582.  
  583. /* Read an instruction (16-bit word immeditately after PC) */
  584. extern "C" unsigned int m68k_read_instruction(unsigned int address)
  585. {
  586.         return m68k_read_memory_16(address);
  587. }
  588.  
  589. /* Write to anywhere */
  590. extern "C" void m68k_write_memory_8(unsigned int address, unsigned int value)
  591. {
  592.         md::md_musa->misc_writebyte(address, value);
  593. }
  594.  
  595. extern "C" void m68k_write_memory_16(unsigned int address, unsigned int value)
  596. {
  597.         md::md_musa->misc_writeword(address, value);
  598. }
  599.  
  600. extern "C" void m68k_write_memory_32(unsigned int address, unsigned int value)
  601. {
  602.         md::md_musa->misc_writeword(address, ((value >> 16) & 0xffff));
  603.         md::md_musa->misc_writeword((address + 2), (value & 0xffff));
  604. }
  605.  
  606. #endif // WITH_MUSA
  607.  
  608. #ifdef WITH_CYCLONE
  609.  
  610. /* Read from anywhere */
  611. extern "C" uint32_t cyclone_read_memory_8(uint32_t address)
  612. {
  613.         return md::md_cyclone->misc_readbyte(address);
  614. }
  615.  
  616. extern "C" uint32_t cyclone_read_memory_16(uint32_t address)
  617. {
  618.         return md::md_cyclone->misc_readword(address);
  619. }
  620.  
  621. extern "C" uint32_t cyclone_read_memory_32(uint32_t address)
  622. {
  623.         return ((md::md_cyclone->misc_readword(address) << 16) |
  624.                 (md::md_cyclone->misc_readword(address + 2) & 0xffff));
  625. }
  626.  
  627. /* Write to anywhere */
  628. extern "C" void cyclone_write_memory_8(uint32_t address, uint8_t value)
  629. {
  630.         md::md_cyclone->misc_writebyte(address, value);
  631. }
  632.  
  633. extern "C" void cyclone_write_memory_16(uint32_t address, uint16_t value)
  634. {
  635.         md::md_cyclone->misc_writeword(address, value);
  636. }
  637.  
  638. extern "C" void cyclone_write_memory_32(uint32_t address, uint32_t value)
  639. {
  640.         md::md_cyclone->misc_writeword(address, ((value >> 16) & 0xffff));
  641.         md::md_cyclone->misc_writeword((address + 2), (value & 0xffff));
  642. }
  643.  
  644. uintptr_t md::checkpc(uintptr_t pc)
  645. {
  646.         static uint8_t zero[(M68K_EMPTY1_END + 1)];
  647.  
  648.         pc -= cyclonecpu.membase; // Get the real program counter.
  649.  
  650.         pc &= 0x00ffffff; // Clip to 24-bit.
  651.         if ((save_active) && (save_len) &&
  652.             (pc >= save_start) && ((pc - save_start) < save_len)) {
  653.                 cyclonecpu.membase = (uintptr_t)saveram;
  654.                 pc -= save_start;
  655.         }
  656.         if (pc <= romlen)
  657.                 cyclonecpu.membase = (uintptr_t)rom; // Jump to ROM.
  658.         else if (pc <= M68K_EMPTY1_END)
  659.                 cyclonecpu.membase = (uintptr_t)zero; // Scratch area.
  660.         else if (pc >= 0xe00000) {
  661.                 pc &= 0xffff;
  662.                 cyclonecpu.membase = (uintptr_t)ram; // Jump to RAM.
  663.         }
  664.         else {
  665.                 DEBUG(("PC out of bounds: %06x", pc));
  666.                 // Freeze, avoid crashing the emulator.
  667.                 cyclonecpu.membase = (uintptr_t)no_rom;
  668.                 pc = 0;
  669.         }
  670.         return (cyclonecpu.membase + pc); // New program counter.
  671. }
  672.  
  673. extern "C" uintptr_t cyclone_checkpc(uintptr_t pc)
  674. {
  675.         return md::md_cyclone->checkpc(pc);
  676. }
  677.  
  678. #endif // WITH_CYCLONE
  679.  
  680. #ifdef WITH_STAR
  681.  
  682. extern "C" unsigned star_readbyte(unsigned a, unsigned d)
  683. {
  684.         (void)d;
  685.         return md::md_star->misc_readbyte(a);
  686. }
  687.  
  688. extern "C" unsigned star_readword(unsigned a, unsigned d)
  689. {
  690.         (void)d;
  691.         return md::md_star->misc_readword(a);
  692. }
  693.  
  694. extern "C" unsigned star_writebyte(unsigned a, unsigned d)
  695. {
  696.         md::md_star->misc_writebyte(a, d);
  697.         return 0;
  698. }
  699.  
  700. extern "C" unsigned star_writeword(unsigned a, unsigned d)
  701. {
  702.         md::md_star->misc_writeword(a, d);
  703.         return 0;
  704. }
  705.  
  706. #endif // WITH_STAR
  707.  
  708. #ifdef WITH_MZ80
  709.  
  710. /*
  711.   In case the assembly version of MZ80 is used (WITH_X86_MZ80), prevent
  712.   GCC from optimizing sibling calls (-foptimize-sibling-calls, enabled
  713.   by default at -O2 and above). The ASM code doesn't expect this and
  714.   crashes otherwise.
  715. */
  716.  
  717. #ifdef WITH_X86_MZ80
  718. #define MZ80_NOSIBCALL(t, w) *((volatile t *)&(w))
  719. #else
  720. #define MZ80_NOSIBCALL(t, w) (w)
  721. #endif
  722.  
  723. extern "C" UINT8 mz80_read(UINT32 a, struct MemoryReadByte *unused)
  724. {
  725.         (void)unused;
  726.         return md::md_mz80->z80_read(MZ80_NOSIBCALL(UINT32, a));
  727. }
  728.  
  729. extern "C" void mz80_write(UINT32 a, UINT8 d, struct MemoryWriteByte *unused)
  730. {
  731.         (void)unused;
  732.         md::md_mz80->z80_write(MZ80_NOSIBCALL(UINT32, a), d);
  733. }
  734.  
  735. extern "C" UINT16 mz80_ioread(UINT16 a, struct z80PortRead *unused)
  736. {
  737.         (void)unused;
  738.         return md::md_mz80->z80_port_read(MZ80_NOSIBCALL(UINT16, a));
  739. }
  740.  
  741. extern "C" void mz80_iowrite(UINT16 a, UINT8 d, struct z80PortWrite *unused)
  742. {
  743.         (void)unused;
  744.         return md::md_mz80->z80_port_write(MZ80_NOSIBCALL(UINT16, a), d);
  745. }
  746.  
  747. #endif // WITH_MZ80
  748.  
  749. #ifdef WITH_CZ80
  750.  
  751. extern "C" uint8_t cz80_memread(void *ctx, uint16_t a)
  752. {
  753.         class md* md = (class md*)ctx;
  754.  
  755.         return md->z80_read(a);
  756. }
  757.  
  758. extern "C" void cz80_memwrite(void *ctx, uint16_t a, uint8_t d)
  759. {
  760.         class md* md = (class md*)ctx;
  761.  
  762.         md->z80_write(a, d);
  763. }
  764.  
  765. extern "C" uint16_t cz80_memread16(void *ctx, uint16_t a)
  766. {
  767.         class md* md = (class md*)ctx;
  768.  
  769.         return ((uint16_t)md->z80_read(a) |
  770.                 ((uint16_t)md->z80_read(a + 1) << 8));
  771. }
  772.  
  773. extern "C" void cz80_memwrite16(void *ctx, uint16_t a, uint16_t d)
  774. {
  775.         class md* md = (class md*)ctx;
  776.  
  777.         md->z80_write(a, (uint8_t)d);
  778.         md->z80_write((a + 1), (uint8_t)(d >> 8));
  779. }
  780.  
  781. extern "C" uint8_t cz80_ioread(void *ctx, uint16_t a)
  782. {
  783.         class md* md = (class md*)ctx;
  784.  
  785.         return md->z80_port_read(a);
  786. }
  787.  
  788. extern "C" void cz80_iowrite(void *ctx, uint16_t a, uint8_t d)
  789. {
  790.         class md* md = (class md*)ctx;
  791.  
  792.         md->z80_port_write(a, d);
  793. }
  794.  
  795. #endif // WITH_CZ80
  796.  
  797. #ifdef WITH_DRZ80
  798.  
  799. uintptr_t md::drz80_rebase_pc(uint16_t address)
  800. {
  801.         // PC in memory - rebase PC into memory.
  802.         drz80.Z80PC_BASE = (uintptr_t)z80ram;
  803.         return (drz80.Z80PC_BASE + address);
  804. }
  805.  
  806. uintptr_t md::drz80_rebase_sp(uint16_t address)
  807. {
  808.         // SP in memory - rebase SP into memory.
  809.         drz80.Z80SP_BASE = (uintptr_t)z80ram;
  810.         return (drz80.Z80SP_BASE + address);
  811. }
  812.  
  813. uintptr_t drz80_rebaseSP(uint16_t new_sp)
  814. {
  815.         return md::md_drz80->drz80_rebase_sp(new_sp);
  816. }
  817.  
  818. uintptr_t drz80_rebasePC(uint16_t new_pc)
  819. {
  820.         return md::md_drz80->drz80_rebase_pc(new_pc);
  821. }
  822.  
  823. uint8_t drz80_read8(uint16_t a)
  824. {
  825.         return md::md_drz80->z80_read(a);
  826. }
  827.  
  828. uint16_t drz80_read16(uint16_t a)
  829. {
  830.         return ((uint16_t)md::md_drz80->z80_read(a) |
  831.                 ((uint16_t)md::md_drz80->z80_read(a + 1) << 8));
  832. }
  833.  
  834. void drz80_write8(uint8_t d, uint16_t a)
  835. {
  836.         md::md_drz80->z80_write(a, d);
  837. }
  838.  
  839. void drz80_write16(uint16_t d, uint16_t a)
  840. {
  841.         md::md_drz80->z80_write(a, (uint8_t)d);
  842.         md::md_drz80->z80_write((a + 1), (uint8_t)(d >> 8));
  843. }
  844.  
  845. uint8_t drz80_in(uint16_t p)
  846. {
  847.         (void)p;
  848.         return 0xff;
  849. }
  850.  
  851. void drz80_out(uint16_t p, uint8_t d)
  852. {
  853.         (void)p;
  854.         (void)d;
  855. }
  856.  
  857. #endif // WITH_DRZ80
  858.