mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-11-04 01:45:08 +01:00
~optimized 68k execution/interruptions
~re-enabled Address Error emulation
This commit is contained in:
parent
7bddb27c2b
commit
aa970d66a6
@ -7,7 +7,7 @@ Genesis Plus GX 1.3.2 (??/??/????) (Eke-Eke)
|
||||
|
||||
* optimized SN76489 core
|
||||
* modified SN76489 cut-off frequency (thanks to Steve Snake)
|
||||
* added SN76489 linear interpolation using Blip Buffer (thanks to Blargg)
|
||||
* added SN76489 linear synthesis using Blip Buffer (thanks to Blargg)
|
||||
* added an option to boost SN76489 Noise Channel
|
||||
* removed now outdated Gens YM2612 core
|
||||
* improved YM2612 emulation accuracy (SSG-EG, CSM mode...) (thanks to Nemesis for his tests on real hardware)
|
||||
|
@ -26,10 +26,11 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "shared.h"
|
||||
#include "m68kcpu.h"
|
||||
|
||||
#define CART_CNT 26
|
||||
|
||||
extern int emulate_address_error;
|
||||
|
||||
/* Global Variables */
|
||||
T_CART_HW cart_hw;
|
||||
uint8 j_cart;
|
||||
|
@ -78,7 +78,7 @@ static inline void lightgun_update(int num)
|
||||
if (io_reg[5] & 0x80)
|
||||
{
|
||||
/* External Interrupt ? */
|
||||
if (reg[11] & 0x08) {irq_status &= 0xff; irq_status |= 0x12;}
|
||||
if (reg[11] & 0x08) irq_status = (irq_status & ~0x40) | 0x12;
|
||||
|
||||
/* HVC Latch:
|
||||
1) some games does not set HVC latch but instead use bigger X offset
|
||||
|
@ -157,7 +157,7 @@
|
||||
* access a word or longword at an odd address.
|
||||
* NOTE: This is only emulated properly for 68000 mode.
|
||||
*/
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
|
||||
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
|
||||
|
||||
|
||||
/* Turn ON to enable logging of illegal instruction calls.
|
||||
|
@ -75,7 +75,9 @@ const char *const m68ki_cpu_names[] =
|
||||
m68ki_cpu_core m68ki_cpu = {0};
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
#include <setjmp.h>
|
||||
jmp_buf m68ki_aerr_trap;
|
||||
int emulate_address_error = 0;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
uint m68ki_aerr_address;
|
||||
@ -505,13 +507,6 @@ static void default_instr_hook_callback(unsigned int pc)
|
||||
}
|
||||
|
||||
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
#include <setjmp.h>
|
||||
jmp_buf m68ki_aerr_trap;
|
||||
int emulate_address_error = 0;
|
||||
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= API ================================== */
|
||||
/* ======================================================================== */
|
||||
@ -781,64 +776,42 @@ void m68k_set_cpu_type(unsigned int cpu_type)
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute some instructions until we use up num_cycles clock cycles */
|
||||
/* ASG: removed per-instruction interrupt checks */
|
||||
INLINE int m68k_execute(int num_cycles)
|
||||
/* Execute a single instruction */
|
||||
INLINE int m68k_execute(void)
|
||||
{
|
||||
/* Make sure we're not stopped */
|
||||
if(!CPU_STOPPED)
|
||||
{
|
||||
/* Set our pool of clock cycles available */
|
||||
SET_CYCLES(num_cycles);
|
||||
m68ki_initial_cycles = num_cycles;
|
||||
SET_CYCLES(0);
|
||||
|
||||
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
||||
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Set the address space for reads */
|
||||
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Call external hook to peek at CPU */
|
||||
m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Record previous program counter */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
/* Read an instruction and call its handler */
|
||||
REG_IR = m68ki_read_imm_16();
|
||||
m68ki_instruction_jump_table[REG_IR]();
|
||||
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
|
||||
|
||||
/* Trace m68k_exception, if necessary */
|
||||
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* ASG: update cycles */
|
||||
USE_CYCLES(CPU_INT_CYCLES);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
/* Return point if we had an address error */
|
||||
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Main loop. Keep going until we run out of clock cycles */
|
||||
do
|
||||
{
|
||||
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
||||
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Set the address space for reads */
|
||||
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Call external hook to peek at CPU */
|
||||
m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
/* Record previous program counter */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
/* Read an instruction and call its handler */
|
||||
REG_IR = m68ki_read_imm_16();
|
||||
m68ki_instruction_jump_table[REG_IR]();
|
||||
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
|
||||
|
||||
/* Trace m68k_exception, if necessary */
|
||||
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||
} while(GET_CYCLES() > 0);
|
||||
|
||||
/* set previous PC to current PC for the next entry into the loop */
|
||||
REG_PPC = REG_PC;
|
||||
|
||||
/* ASG: update cycles */
|
||||
USE_CYCLES(CPU_INT_CYCLES);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
/* return how many clocks we used */
|
||||
return m68ki_initial_cycles - GET_CYCLES();
|
||||
}
|
||||
return - GET_CYCLES();
|
||||
|
||||
/* We get here if the CPU is stopped or halted */
|
||||
SET_CYCLES(0);
|
||||
CPU_INT_CYCLES = 0;
|
||||
|
||||
return num_cycles;
|
||||
}
|
||||
|
||||
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||
@ -858,12 +831,23 @@ INLINE void m68k_set_irq(unsigned int int_level)
|
||||
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||
}
|
||||
|
||||
extern uint16 irq_status;
|
||||
extern uint8 irq_status;
|
||||
extern uint32 count_m68k;
|
||||
|
||||
void m68k_run (int cyc)
|
||||
{
|
||||
/* Make sure we're not stopped */
|
||||
if(CPU_STOPPED)
|
||||
{
|
||||
count_m68k = cyc;
|
||||
return;
|
||||
}
|
||||
|
||||
int temp;
|
||||
|
||||
/* Return point if we had an address error */
|
||||
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
while (count_m68k < cyc)
|
||||
{
|
||||
/* check interrupt updates */
|
||||
@ -871,18 +855,23 @@ void m68k_run (int cyc)
|
||||
{
|
||||
irq_status &= ~0x10;
|
||||
|
||||
temp = irq_status & 6;
|
||||
|
||||
/* hardware latency */
|
||||
temp = irq_status >> 8;
|
||||
if (temp) count_m68k += m68k_execute(temp);
|
||||
if (irq_status & 0x40)
|
||||
count_m68k += m68k_execute();
|
||||
|
||||
/* interrupt level */
|
||||
temp = irq_status & 6;
|
||||
if (temp == 6) irq_status |= 0x20;
|
||||
m68k_set_irq(temp);
|
||||
|
||||
/* ASG: update cycles */
|
||||
count_m68k += CPU_INT_CYCLES;
|
||||
CPU_INT_CYCLES = 0;
|
||||
}
|
||||
|
||||
/* execute a single instruction */
|
||||
count_m68k += m68k_execute(1);
|
||||
count_m68k += m68k_execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -554,7 +554,7 @@
|
||||
#if M68K_EMULATE_ADDRESS_ERROR
|
||||
#include <setjmp.h>
|
||||
extern jmp_buf m68ki_aerr_trap;
|
||||
extern int emulate_address_error;
|
||||
extern int emulate_address_error;
|
||||
|
||||
#define m68ki_set_address_error_trap() \
|
||||
if(setjmp(m68ki_aerr_trap) != 0) \
|
||||
@ -564,7 +564,6 @@
|
||||
{ \
|
||||
SET_CYCLES(0); \
|
||||
CPU_INT_CYCLES = 0; \
|
||||
return m68ki_initial_cycles; \
|
||||
} \
|
||||
}
|
||||
|
||||
@ -1063,13 +1062,13 @@ INLINE uint m68ki_read_imm_16(void)
|
||||
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
|
||||
{
|
||||
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
|
||||
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
|
||||
CPU_PREF_DATA = m68k_read_immediate_32(CPU_PREF_ADDR);
|
||||
}
|
||||
REG_PC += 2;
|
||||
return MASK_OUT_ABOVE_16(CPU_PREF_DATA >> ((2-((REG_PC-2)&2))<<3));
|
||||
#else
|
||||
REG_PC += 2;
|
||||
return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2));
|
||||
return m68k_read_immediate_16(REG_PC-2);
|
||||
#endif /* M68K_EMULATE_PREFETCH */
|
||||
}
|
||||
INLINE uint m68ki_read_imm_32(void)
|
||||
@ -1082,14 +1081,14 @@ INLINE uint m68ki_read_imm_32(void)
|
||||
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
|
||||
{
|
||||
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
|
||||
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
|
||||
CPU_PREF_DATA = m68k_read_immediate_32(CPU_PREF_ADDR);
|
||||
}
|
||||
temp_val = CPU_PREF_DATA;
|
||||
REG_PC += 2;
|
||||
if(MASK_OUT_BELOW_2(REG_PC) != CPU_PREF_ADDR)
|
||||
{
|
||||
CPU_PREF_ADDR = MASK_OUT_BELOW_2(REG_PC);
|
||||
CPU_PREF_DATA = m68k_read_immediate_32(ADDRESS_68K(CPU_PREF_ADDR));
|
||||
CPU_PREF_DATA = m68k_read_immediate_32(CPU_PREF_ADDR);
|
||||
temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | (CPU_PREF_DATA >> 16));
|
||||
}
|
||||
REG_PC += 2;
|
||||
@ -1099,7 +1098,7 @@ INLINE uint m68ki_read_imm_32(void)
|
||||
m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */
|
||||
REG_PC += 4;
|
||||
return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4));
|
||||
return m68k_read_immediate_32(REG_PC-4);
|
||||
#endif /* M68K_EMULATE_PREFETCH */
|
||||
}
|
||||
|
||||
@ -1119,7 +1118,7 @@ INLINE uint m68ki_read_8_fc(uint address, uint fc)
|
||||
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
|
||||
if (temp->read8) return (*temp->read8)(address);
|
||||
if (temp->read8) return (*temp->read8)(ADDRESS_68K(address));
|
||||
else return READ_BYTE(temp->base, (address) & 0xffff);
|
||||
}
|
||||
INLINE uint m68ki_read_16_fc(uint address, uint fc)
|
||||
@ -1128,7 +1127,7 @@ INLINE uint m68ki_read_16_fc(uint address, uint fc)
|
||||
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->read16) return (*temp->read16)(address);
|
||||
if (temp->read16) return (*temp->read16)(ADDRESS_68K(address));
|
||||
else return *(uint16 *)(temp->base + ((address) & 0xffff));
|
||||
}
|
||||
INLINE uint m68ki_read_32_fc(uint address, uint fc)
|
||||
@ -1137,7 +1136,7 @@ INLINE uint m68ki_read_32_fc(uint address, uint fc)
|
||||
m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */
|
||||
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->read16) return ((*temp->read16)(address) << 16) | ((*temp->read16)(address + 2));
|
||||
if (temp->read16) return ((*temp->read16)(ADDRESS_68K(address)) << 16) | ((*temp->read16)(ADDRESS_68K(address + 2)));
|
||||
else return m68k_read_immediate_32(address);
|
||||
}
|
||||
|
||||
@ -1145,7 +1144,7 @@ INLINE void m68ki_write_8_fc(uint address, uint fc, uint value)
|
||||
{
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->write8) (*temp->write8)(address,value);
|
||||
if (temp->write8) (*temp->write8)(ADDRESS_68K(address),value);
|
||||
else WRITE_BYTE(temp->base, (address) & 0xffff, value);
|
||||
}
|
||||
INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
|
||||
@ -1153,7 +1152,7 @@ INLINE void m68ki_write_16_fc(uint address, uint fc, uint value)
|
||||
m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */
|
||||
m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->write16) (*temp->write16)(address,value);
|
||||
if (temp->write16) (*temp->write16)(ADDRESS_68K(address),value);
|
||||
else *(uint16 *)(temp->base + ((address) & 0xffff)) = value;
|
||||
}
|
||||
INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
|
||||
@ -1163,8 +1162,8 @@ INLINE void m68ki_write_32_fc(uint address, uint fc, uint value)
|
||||
_m68k_memory_map *temp = &m68k_memory_map[((address)>>16)&0xff];
|
||||
if (temp->write16)
|
||||
{
|
||||
(*temp->write16)(address,value>>16);
|
||||
(*temp->write16)(address+2,value&0xffff);
|
||||
(*temp->write16)(ADDRESS_68K(address),value>>16);
|
||||
(*temp->write16)(ADDRESS_68K(address+2),value&0xffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1958,7 +1957,6 @@ INLINE void m68ki_exception_address_error(void)
|
||||
*/
|
||||
if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET)
|
||||
{
|
||||
m68k_read_memory_8(0x00ffff01);
|
||||
CPU_STOPPED = STOP_LEVEL_HALT;
|
||||
return;
|
||||
}
|
||||
@ -1975,7 +1973,7 @@ INLINE void m68ki_exception_address_error(void)
|
||||
|
||||
|
||||
/* Service an interrupt request and start exception processing */
|
||||
void m68ki_exception_interrupt(uint int_level)
|
||||
INLINE void m68ki_exception_interrupt(uint int_level)
|
||||
{
|
||||
uint vector;
|
||||
uint sr;
|
||||
|
@ -7,20 +7,20 @@
|
||||
|
||||
#define READ_WORD(BASE, ADDR) (((BASE)[ADDR]<<8) | (BASE)[(ADDR)+1])
|
||||
|
||||
#define READ_WORD_LONG(BASE, ADDR) (((BASE)[ADDR]<<24) | \
|
||||
((BASE)[(ADDR)+1]<<16) | \
|
||||
((BASE)[(ADDR)+2]<<8) | \
|
||||
(BASE)[(ADDR)+3])
|
||||
#define READ_WORD_LONG(BASE, ADDR) (((BASE)[(ADDR)+1]<<24) | \
|
||||
((BASE)[(ADDR)]<<16) | \
|
||||
((BASE)[(ADDR)+3]<<8) | \
|
||||
(BASE)[(ADDR)+1])
|
||||
|
||||
#define WRITE_BYTE(BASE, ADDR, VAL) (BASE)[(ADDR)^1] = (VAL)&0xff
|
||||
|
||||
#define WRITE_WORD(BASE, ADDR, VAL) (BASE)[ADDR] = ((VAL)>>8) & 0xff; \
|
||||
(BASE)[(ADDR)+1] = (VAL)&0xff
|
||||
|
||||
#define WRITE_WORD_LONG(BASE, ADDR, VAL) (BASE)[(ADDR] = ((VAL)>>24) & 0xff; \
|
||||
(BASE)[(ADDR)+1] = ((VAL)>>16)&0xff; \
|
||||
(BASE)[(ADDR)+2] = ((VAL)>>8)&0xff; \
|
||||
(BASE)[(ADDR)+3] = (VAL)&0xff
|
||||
#define WRITE_WORD_LONG(BASE, ADDR, VAL) (BASE)[(ADDR+1)] = ((VAL)>>24) & 0xff; \
|
||||
(BASE)[(ADDR)] = ((VAL)>>16)&0xff; \
|
||||
(BASE)[(ADDR+3)] = ((VAL)>>8)&0xff; \
|
||||
(BASE)[(ADDR+2)] = (VAL)&0xff
|
||||
|
||||
#else
|
||||
|
||||
|
@ -388,7 +388,7 @@ int system_frame (int do_skip)
|
||||
{
|
||||
h_counter = reg[10];
|
||||
hint_pending = 1;
|
||||
if (reg[0] & 0x10) irq_status = (irq_status & 0xff) | 0x14;
|
||||
if (reg[0] & 0x10) irq_status = (irq_status & ~0x40) | 0x14;
|
||||
|
||||
/* adjust timings to take further decrement in account (see below) */
|
||||
if ((line != 0) || (h_counter == 0)) aim_m68k += 36;
|
||||
@ -430,10 +430,11 @@ int system_frame (int do_skip)
|
||||
|
||||
/* V Interrupt */
|
||||
status |= 0x80;
|
||||
vint_pending = 1;
|
||||
|
||||
/* 36 cycles latency after VINT occurence flag (Ex-Mutants, Tyrant) */
|
||||
if (reg[1] & 0x20) irq_status = (irq_status & 0xff) | 0x2416;
|
||||
m68k_run(line_m68k + 113);
|
||||
vint_pending = 1;
|
||||
if (reg[1] & 0x20) irq_status = (irq_status & ~0x40) | 0x16;
|
||||
}
|
||||
else if (!do_skip)
|
||||
{
|
||||
|
10
source/vdp.c
10
source/vdp.c
@ -50,7 +50,7 @@ uint16 status; /* VDP status flags */
|
||||
uint8 dmafill; /* next VDP Write is DMA Fill */
|
||||
uint8 hint_pending; /* 0= Line interrupt is pending */
|
||||
uint8 vint_pending; /* 1= Frame interrupt is pending */
|
||||
uint16 irq_status; /* Interrupt lines updated */
|
||||
uint8 irq_status; /* Interrupt lines updated */
|
||||
|
||||
/* Global variables */
|
||||
uint16 ntab; /* Name table A base address */
|
||||
@ -651,7 +651,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
{
|
||||
/* update IRQ status */
|
||||
irq_status &= 0x20;
|
||||
irq_status |= 0x10;
|
||||
irq_status |= 0x50;
|
||||
if (vint_pending && (reg[1] & 0x20)) irq_status |= 6;
|
||||
else if (d & 0x10) irq_status |= 4;
|
||||
}
|
||||
@ -677,7 +677,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
{
|
||||
/* update IRQ status */
|
||||
irq_status &= 0x20;
|
||||
irq_status |= 0x110;
|
||||
irq_status |= 0x50;
|
||||
if (d & 0x20) irq_status |= 6;
|
||||
else if (hint_pending && (reg[0] & 0x10)) irq_status |= 4;
|
||||
}
|
||||
@ -697,7 +697,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
}
|
||||
|
||||
/* Display activated/blanked during Horizontal Blanking */
|
||||
if (((d&0x40) != (reg[1]&0x40)) && (v_counter < bitmap.viewport.h))
|
||||
if (((d&0x40) != (reg[1]&0x40)) && !(status & 8))
|
||||
{
|
||||
if (count_m68k <= (hint_m68k + 120))
|
||||
{
|
||||
@ -748,7 +748,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
|
||||
color_update(0x00, *(uint16 *)&cram[(border << 1)]);
|
||||
|
||||
/* background color modified during Horizontal Blanking */
|
||||
if ((v_counter < bitmap.viewport.h) && (count_m68k <= (line_m68k + 84)))
|
||||
if (!(status & 8) && (count_m68k <= (line_m68k + 84)))
|
||||
{
|
||||
/* remap current line (see Road Rash I,II,III) */
|
||||
reg[7] = d;
|
||||
|
@ -38,7 +38,7 @@ extern uint16 status;
|
||||
extern uint8 dmafill;
|
||||
extern uint8 hint_pending;
|
||||
extern uint8 vint_pending;
|
||||
extern uint16 irq_status;
|
||||
extern uint8 irq_status;
|
||||
|
||||
/* Global variables */
|
||||
extern uint16 ntab;
|
||||
|
Loading…
Reference in New Issue
Block a user