mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-13 22:35:10 +01:00
170 lines
4.4 KiB
C
170 lines
4.4 KiB
C
|
/*
|
||
|
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*/
|
||
|
|
||
|
#include "shared.h"
|
||
|
|
||
|
uint8 *cart_rom; /* cart_rom NEED to be previously dynamically allocated */
|
||
|
uint8 work_ram[0x10000]; /* 68K work RAM */
|
||
|
uint8 zram[0x2000]; /* Z80 work RAM */
|
||
|
uint8 zbusreq; /* /BUSREQ from Z80 */
|
||
|
uint8 zreset; /* /RESET to Z80 */
|
||
|
uint8 zbusack; /* /BUSACK to Z80 */
|
||
|
uint8 zirq; /* /IRQ to Z80 */
|
||
|
uint32 zbank; /* Address of Z80 bank window */
|
||
|
uint8 gen_running;
|
||
|
uint32 lastbusreqcnt;
|
||
|
uint8 lastbusack;
|
||
|
uint32 genromsize;
|
||
|
|
||
|
static int cpu_sync[512]; /* Z80-68K cycles synchronization table */
|
||
|
|
||
|
#ifdef LSB_FIRST
|
||
|
void bswap(uint8 *mem, int length)
|
||
|
{
|
||
|
int i;
|
||
|
for(i = 0; i < length; i += 2)
|
||
|
{
|
||
|
uint8 temp = mem[i+0];
|
||
|
mem[i+0] = mem[i+1];
|
||
|
mem[i+1] = temp;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
/* Init, reset, shutdown functions */
|
||
|
/*--------------------------------------------------------------------------*/
|
||
|
|
||
|
void gen_init (void)
|
||
|
{
|
||
|
int i;
|
||
|
#ifdef LSB_FIRST
|
||
|
bswap(cart_rom, genromsize);
|
||
|
#endif
|
||
|
#ifdef NGC
|
||
|
ShadowROM ();
|
||
|
#else
|
||
|
memcpy(shadow_rom,cart_rom,genromsize);
|
||
|
#endif
|
||
|
m68k_set_cpu_type (M68K_CPU_TYPE_68000);
|
||
|
m68k_pulse_reset ();
|
||
|
gen_running = 1;
|
||
|
for (i=0; i<512; i++) cpu_sync[i] = (int)(((double)i * 7.0) / 15.0);
|
||
|
}
|
||
|
|
||
|
void gen_reset (void)
|
||
|
{
|
||
|
/* Clear RAM */
|
||
|
memset (work_ram, 0, sizeof (work_ram));
|
||
|
memset (zram, 0, sizeof (zram));
|
||
|
gen_running = 1;
|
||
|
zreset = 0; /* Z80 is reset */
|
||
|
zbusreq = 0; /* Z80 has control of the Z bus */
|
||
|
zbusack = 1; /* Z80 is busy using the Z bus */
|
||
|
zbank = 0; /* Assume default bank is 000000-007FFF */
|
||
|
zirq = 0; /* No interrupts occuring */
|
||
|
lastbusreqcnt = 0;
|
||
|
lastbusack = 1;
|
||
|
|
||
|
/* Reset the 68000 emulator */
|
||
|
m68k_pulse_reset ();
|
||
|
z80_reset (0);
|
||
|
z80_set_irq_callback (z80_irq_callback);
|
||
|
}
|
||
|
|
||
|
void gen_shutdown (void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------------------------------
|
||
|
Bus controller chip functions
|
||
|
-----------------------------------------------------------------------*/
|
||
|
int gen_busack_r (void)
|
||
|
{
|
||
|
if (zbusack == 0)
|
||
|
{
|
||
|
if ((count_m68k + m68k_cycles_run() - lastbusreqcnt) > 16)
|
||
|
return 0; /* bus taken */
|
||
|
else return (lastbusack&1);
|
||
|
}
|
||
|
else return 1;
|
||
|
}
|
||
|
|
||
|
void gen_busreq_w (int state)
|
||
|
{
|
||
|
int z80_cycles_to_run;
|
||
|
|
||
|
input_raz ();
|
||
|
|
||
|
if (state == 1)
|
||
|
{
|
||
|
/* Bus Request */
|
||
|
lastbusreqcnt = count_m68k + m68k_cycles_run();
|
||
|
lastbusack = zbusack;
|
||
|
if (zbusreq == 0)
|
||
|
{
|
||
|
/* Z80 stopped */
|
||
|
/* z80 was ON during the last 68k cycles */
|
||
|
/* we execute the appropriate number of z80 cycles */
|
||
|
z80_cycles_to_run = aim_z80 - cpu_sync[aim_m68k - count_m68k -m68k_cycles_run()];
|
||
|
if (z80_cycles_to_run > 0) z80_run(z80_cycles_to_run);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* Bus released */
|
||
|
if (zbusreq == 1)
|
||
|
{
|
||
|
/* Z80 started */
|
||
|
/* z80 was OFF during the last 68k cycles */
|
||
|
/* we burn the appropriate number of z80 cycles */
|
||
|
z80_cycles_to_run = aim_z80 - cpu_sync[aim_m68k - count_m68k - m68k_cycles_run()];
|
||
|
if (z80_cycles_to_run > 0) count_z80 = z80_cycles_to_run;
|
||
|
}
|
||
|
}
|
||
|
zbusreq = (state & 1);
|
||
|
zbusack = 1 ^ (zbusreq & zreset);
|
||
|
}
|
||
|
|
||
|
void gen_reset_w (int state)
|
||
|
{
|
||
|
zreset = (state & 1);
|
||
|
zbusack = 1 ^ (zbusreq & zreset);
|
||
|
|
||
|
if (zreset == 0)
|
||
|
{
|
||
|
lastbusreqcnt = 0;
|
||
|
lastbusack = 1;
|
||
|
fm_reset();
|
||
|
z80_reset (0);
|
||
|
z80_set_irq_callback (z80_irq_callback);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void gen_bank_w (int state)
|
||
|
{
|
||
|
zbank = ((zbank >> 1) | ((state & 1) << 23)) & 0xFF8000;
|
||
|
}
|
||
|
|
||
|
int z80_irq_callback (int param)
|
||
|
{
|
||
|
zirq = 0;
|
||
|
z80_set_irq_line (0, CLEAR_LINE);
|
||
|
return 0xFF;
|
||
|
}
|