mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-30 01:25:49 +00:00
183dca563d
- Added 'crosshairs' command line and config option. - Added 'vsync' command line and config option (so far only tested on NVidia cards on Windows 7 - other graphics drivers, O/Ss or driver settings may simply chose to ignore this). - Added fullscreen toggle within game using Alt+Enter key combination. - Added framework for lamp outputs and 'outputs' command line and config option. So far only the lamps for driving games are hooked up in the emulator (others to be added later). - Added an initial outputs implementation for Windows that sends MAMEHooker compatible messages (-outputs=win to enable) - Fixed fps calculation in Main.cpp that was producing incorrect results and so giving the impression that frame throttling wasn't working properly when in fact it was. - Fixed palette indexed colours as the index was always off by one, causing incorrect colours in various games, eg drivers' suits and flashing Start sign in Daytona 2. - Altered caching of models so that models with palette indexed colours use the dynamic cache rather than the static one. This is so that changes in palette indexed colours appear on screen, eg the flashing Start sign on the advanced course of Daytona 2 (although currently the START message itself is not visible due to other problems with texture decoding). - Fixed small bug in TileGen.cpp which meant both palettes were being completely recomputed pretty much with every frame. This was a significant performance hit, particularly as palette recomputation is currently being done in SyncSnapshots (it should be moved out of here at some point, although for now it's no big deal). - Made sure all OpenGL objects and resources are deleted in Render2D/3D destructors, in particular the deleting of the VBO buffer in DestroyModelCache. - Made sure that GLSL uniforms are always checked to see if they are bound before using them in order to stop unecessary (but harmless) GL errors. - Altered the default texture sheet handling to use a single large GL texture holding multiple Model3 texture sheets rather than multiple GL textures as before (if required, the old behaviour can still be selected with the mulisheet fragment shader). I believe this fixes the disappearing crosshairs/corrupt GL state problem which the multisheet fragment shader seemed to be triggering somehow. - Fixed a bug in debugger which meant memory watches were not triggering properly
386 lines
14 KiB
C
386 lines
14 KiB
C
/**
|
|
** Supermodel
|
|
** A Sega Model 3 Arcade Emulator.
|
|
** Copyright 2011 Bart Trzynadlowski, Nik Henson
|
|
**
|
|
** This file is part of Supermodel.
|
|
**
|
|
** Supermodel 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 3 of the License, or (at your option)
|
|
** any later version.
|
|
**
|
|
** Supermodel 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 Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
|
**/
|
|
|
|
/*
|
|
* ppc.h
|
|
*
|
|
* Header file for PowerPC emulator.
|
|
*/
|
|
|
|
#ifndef INCLUDED_PPC_H
|
|
#define INCLUDED_PPC_H
|
|
|
|
|
|
/******************************************************************************
|
|
Definitions
|
|
******************************************************************************/
|
|
|
|
#define SPR_XER 1 /* Fixed Point Exception Register Read / Write */
|
|
#define SPR_LR 8 /* Link Register Read / Write */
|
|
#define SPR_CTR 9 /* Count Register Read / Write */
|
|
#define SPR_SRR0 26 /* Save/Restore Register 0 Read / Write */
|
|
#define SPR_SRR1 27 /* Save/Restore Register 1 Read / Write */
|
|
#define SPR_SPRG0 272 /* SPR General 0 Read / Write */
|
|
#define SPR_SPRG1 273 /* SPR General 1 Read / Write */
|
|
#define SPR_SPRG2 274 /* SPR General 2 Read / Write */
|
|
#define SPR_SPRG3 275 /* SPR General 3 Read / Write */
|
|
#define SPR_PVR 287 /* Processor Version Number Read Only */
|
|
|
|
#define SPR403_ICDBDR 0x3D3 /* 406GA Instruction Cache Debug Data Register Rad Only */
|
|
#define SPR403_ESR 0x3D4 /* 406GA Exception Syndrome Register Read / Write */
|
|
#define SPR403_DEAR 0x3D5 /* 406GA Data Exception Address Register Read Only */
|
|
#define SPR403_EVPR 0x3D6 /* 406GA Exception Vector Prefix Register Read / Write */
|
|
#define SPR403_CDBCR 0x3D7 /* 406GA Cache Debug Control Register Read/Write */
|
|
#define SPR403_TSR 0x3D8 /* 406GA Timer Status Register Read / Clear */
|
|
#define SPR403_TCR 0x3DA /* 406GA Timer Control Register Read / Write */
|
|
#define SPR403_PIT 0x3DB /* 406GA Programmable Interval Timer Read / Write */
|
|
#define SPR403_TBHI 988 /* 406GA Time Base High Read / Write */
|
|
#define SPR403_TBLO 989 /* 406GA Time Base Low Read / Write */
|
|
#define SPR403_SRR2 0x3DE /* 406GA Save/Restore Register 2 Read / Write */
|
|
#define SPR403_SRR3 0x3DF /* 406GA Save/Restore Register 3 Read / Write */
|
|
#define SPR403_DBSR 0x3F0 /* 406GA Debug Status Register Read / Clear */
|
|
#define SPR403_DBCR 0x3F2 /* 406GA Debug Control Register Read / Write */
|
|
#define SPR403_IAC1 0x3F4 /* 406GA Instruction Address Compare 1 Read / Write */
|
|
#define SPR403_IAC2 0x3F5 /* 406GA Instruction Address Compare 2 Read / Write */
|
|
#define SPR403_DAC1 0x3F6 /* 406GA Data Address Compare 1 Read / Write */
|
|
#define SPR403_DAC2 0x3F7 /* 406GA Data Address Compare 2 Read / Write */
|
|
#define SPR403_DCCR 0x3FA /* 406GA Data Cache Cacheability Register Read / Write */
|
|
#define SPR403_ICCR 0x3FB /* 406GA I Cache Cacheability Registe Read / Write */
|
|
#define SPR403_PBL1 0x3FC /* 406GA Protection Bound Lower 1 Read / Write */
|
|
#define SPR403_PBU1 0x3FD /* 406GA Protection Bound Upper 1 Read / Write */
|
|
#define SPR403_PBL2 0x3FE /* 406GA Protection Bound Lower 2 Read / Write */
|
|
#define SPR403_PBU2 0x3FF /* 406GA Protection Bound Upper 2 Read / Write */
|
|
|
|
#define SPR403_SGR 0x3b9 /* 403GCX Storage Guarded Register */
|
|
#define SPR403_DCWR 0x3ba /* 403GCX Data Cache Write Through */
|
|
#define SPR403_PID 0x3b1 /* 403GCX Process ID */
|
|
#define SPR403_TBHU 0x3cc /* 403GCX Time Base High User-mode */
|
|
#define SPR403_TBLU 0x3cd /* 403GCX Time Base Low User-mode */
|
|
|
|
#define SPR603E_DSISR 18 /* 603E */
|
|
#define SPR603E_DAR 19 /* 603E */
|
|
#define SPR603E_DEC 22 /* 603E */
|
|
#define SPR603E_SDR1 25 /* 603E */
|
|
#define SPR603E_TBL_R 268 /* 603E Time Base Low (Read-only) */
|
|
#define SPR603E_TBU_R 269 /* 603E Time Base High (Read-only) */
|
|
#define SPR603E_TBL_W 284 /* 603E Time Base Low (Write-only) */
|
|
#define SPR603E_TBU_W 285 /* 603E Time Base Hight (Write-only) */
|
|
#define SPR603E_EAR 282 /* 603E */
|
|
#define SPR603E_IBAT0U 528 /* 603E */
|
|
#define SPR603E_IBAT0L 529 /* 603E */
|
|
#define SPR603E_IBAT1U 530 /* 603E */
|
|
#define SPR603E_IBAT1L 531 /* 603E */
|
|
#define SPR603E_IBAT2U 532 /* 603E */
|
|
#define SPR603E_IBAT2L 533 /* 603E */
|
|
#define SPR603E_IBAT3U 534 /* 603E */
|
|
#define SPR603E_IBAT3L 535 /* 603E */
|
|
#define SPR603E_DBAT0U 536 /* 603E */
|
|
#define SPR603E_DBAT0L 537 /* 603E */
|
|
#define SPR603E_DBAT1U 538 /* 603E */
|
|
#define SPR603E_DBAT1L 539 /* 603E */
|
|
#define SPR603E_DBAT2U 540 /* 603E */
|
|
#define SPR603E_DBAT2L 541 /* 603E */
|
|
#define SPR603E_DBAT3U 542 /* 603E */
|
|
#define SPR603E_DBAT3L 543 /* 603E */
|
|
#define SPR603E_DABR 1013 /* 603E */
|
|
#define SPR603E_DMISS 0x3d0 /* 603E */
|
|
#define SPR603E_DCMP 0x3d1 /* 603E */
|
|
#define SPR603E_HASH1 0x3d2 /* 603E */
|
|
#define SPR603E_HASH2 0x3d3 /* 603E */
|
|
#define SPR603E_IMISS 0x3d4 /* 603E */
|
|
#define SPR603E_ICMP 0x3d5 /* 603E */
|
|
#define SPR603E_RPA 0x3d6 /* 603E */
|
|
#define SPR603E_HID0 1008 /* 603E */
|
|
#define SPR603E_HID1 1009 /* 603E */
|
|
#define SPR603E_IABR 1010 /* 603E */
|
|
#define SPR603E_HID2 1011 /* 603E */
|
|
|
|
#define SPR602_TCR 984 /* 602 */
|
|
#define SPR602_IBR 986 /* 602 */
|
|
#define SPR602_SP 1021 /* 602 */
|
|
#define SPR602_LT 1022 /* 602 */
|
|
|
|
|
|
#define DCR_BEAR 0x90 /* bus error address */
|
|
#define DCR_BESR 0x91 /* bus error syndrome */
|
|
#define DCR_BR0 0x80 /* bank */
|
|
#define DCR_BR1 0x81 /* bank */
|
|
#define DCR_BR2 0x82 /* bank */
|
|
#define DCR_BR3 0x83 /* bank */
|
|
#define DCR_BR4 0x84 /* bank */
|
|
#define DCR_BR5 0x85 /* bank */
|
|
#define DCR_BR6 0x86 /* bank */
|
|
#define DCR_BR7 0x87 /* bank */
|
|
#define DCR_DMACC0 0xc4 /* dma chained count */
|
|
#define DCR_DMACC1 0xcc /* dma chained count */
|
|
#define DCR_DMACC2 0xd4 /* dma chained count */
|
|
#define DCR_DMACC3 0xdc /* dma chained count */
|
|
#define DCR_DMACR0 0xc0 /* dma channel control */
|
|
#define DCR_DMACR1 0xc8 /* dma channel control */
|
|
#define DCR_DMACR2 0xd0 /* dma channel control */
|
|
#define DCR_DMACR3 0xd8 /* dma channel control */
|
|
#define DCR_DMACT0 0xc1 /* dma destination address */
|
|
#define DCR_DMACT1 0xc9 /* dma destination address */
|
|
#define DCR_DMACT2 0xd1 /* dma destination address */
|
|
#define DCR_DMACT3 0xd9 /* dma destination address */
|
|
#define DCR_DMADA0 0xc2 /* dma destination address */
|
|
#define DCR_DMADA1 0xca /* dma destination address */
|
|
#define DCR_DMADA2 0xd2 /* dma source address */
|
|
#define DCR_DMADA3 0xda /* dma source address */
|
|
#define DCR_DMASA0 0xc3 /* dma source address */
|
|
#define DCR_DMASA1 0xcb /* dma source address */
|
|
#define DCR_DMASA2 0xd3 /* dma source address */
|
|
#define DCR_DMASA3 0xdb /* dma source address */
|
|
#define DCR_DMASR 0xe0 /* dma status */
|
|
#define DCR_EXIER 0x42 /* external interrupt enable */
|
|
#define DCR_EXISR 0x40 /* external interrupt status */
|
|
#define DCR_IOCR 0xa0 /* io configuration */
|
|
|
|
enum {
|
|
EXCEPTION_IRQ = 1,
|
|
EXCEPTION_DECREMENTER = 2,
|
|
EXCEPTION_TRAP = 3,
|
|
EXCEPTION_SYSTEM_CALL = 4,
|
|
EXCEPTION_SMI = 5,
|
|
EXCEPTION_DSI = 6,
|
|
EXCEPTION_ISI = 7,
|
|
EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER = 20,
|
|
EXCEPTION_FIXED_INTERVAL_TIMER = 21,
|
|
EXCEPTION_WATCHDOG_TIMER = 22,
|
|
EXCEPTION_CRITICAL_INTERRUPT = 23,
|
|
};
|
|
|
|
enum {
|
|
PPC_INPUT_LINE_SMI = 10,
|
|
PPC_INPUT_LINE_TLBISYNC
|
|
};
|
|
|
|
enum {
|
|
PPC_PC=1,
|
|
PPC_MSR,
|
|
PPC_CR,
|
|
PPC_LR,
|
|
PPC_CTR,
|
|
PPC_XER,
|
|
PPC_DEC,
|
|
PPC_SRR0,
|
|
PPC_SRR1,
|
|
PPC_R0,
|
|
PPC_R1,
|
|
PPC_R2,
|
|
PPC_R3,
|
|
PPC_R4,
|
|
PPC_R5,
|
|
PPC_R6,
|
|
PPC_R7,
|
|
PPC_R8,
|
|
PPC_R9,
|
|
PPC_R10,
|
|
PPC_R11,
|
|
PPC_R12,
|
|
PPC_R13,
|
|
PPC_R14,
|
|
PPC_R15,
|
|
PPC_R16,
|
|
PPC_R17,
|
|
PPC_R18,
|
|
PPC_R19,
|
|
PPC_R20,
|
|
PPC_R21,
|
|
PPC_R22,
|
|
PPC_R23,
|
|
PPC_R24,
|
|
PPC_R25,
|
|
PPC_R26,
|
|
PPC_R27,
|
|
PPC_R28,
|
|
PPC_R29,
|
|
PPC_R30,
|
|
PPC_R31
|
|
};
|
|
|
|
typedef enum {
|
|
PPC_MODEL_403GA = 0x00200000,
|
|
PPC_MODEL_403GB = 0x00200100,
|
|
PPC_MODEL_403GC = 0x00200200,
|
|
PPC_MODEL_403GCX = 0x00201400,
|
|
PPC_MODEL_405GP = 0x40110000,
|
|
PPC_MODEL_601 = 0x00010000,
|
|
PPC_MODEL_603 = 0x00030000, /* "Wart" */
|
|
PPC_MODEL_604 = 0x00040000, /* "Zephyr" */
|
|
PPC_MODEL_602 = 0x00050000, /* "Galahad" */
|
|
PPC_MODEL_603E = 0x00060103, /* "Stretch", version 1.3 */
|
|
PPC_MODEL_603EV = 0x00070000, /* "Valiant" */
|
|
PPC_MODEL_603R = 0x00071202, /* "Goldeneye", version 2.1 */
|
|
PPC_MODEL_740 = 0x00080301, /* "Arthur", version 3.1 */
|
|
PPC_MODEL_750 = PPC_MODEL_740,
|
|
PPC_MODEL_740P = 0x00080202, /* "Conan Doyle", version 1.2 */
|
|
PPC_MODEL_750P = PPC_MODEL_740P,
|
|
PPC_MODEL_755 = 0x00083203 /* "Goldfinger", version 2.3 */
|
|
} PPC_MODEL;
|
|
|
|
typedef enum {
|
|
BUS_FREQUENCY_16MHZ = 0,
|
|
BUS_FREQUENCY_20MHZ,
|
|
BUS_FREQUENCY_25MHZ,
|
|
BUS_FREQUENCY_33MHZ,
|
|
BUS_FREQUENCY_40MHZ,
|
|
BUS_FREQUENCY_50MHZ,
|
|
BUS_FREQUENCY_60MHZ,
|
|
BUS_FREQUENCY_66MHZ,
|
|
BUS_FREQUENCY_75MHZ,
|
|
} PPC_BUS_FREQUENCY;
|
|
|
|
// PLL Configuration based on the table in MPC603EUM page 7-31
|
|
static const int mpc603e_pll_config[12][9] =
|
|
{
|
|
// 16, 20, 25, 33, 40, 50, 60, 66, 75
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, -1, 0x0, -1 },
|
|
{ -1, -1, -1, -1, -1, 0xc, -1, 0xc, -1 },
|
|
{ 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, -1, -1, -1 },
|
|
{ -1, -1, -1, 0x6, 0x6, -1, -1, -1, -1 },
|
|
{ -1, -1, 0x8, 0x8, -1, -1, -1, -1, -1 },
|
|
{ -1, 0xe, 0xe, -1, -1, -1, -1, -1, -1 },
|
|
{ 0xa, 0xa, 0xa, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
};
|
|
|
|
// PLL Configuration based on the table in MPC603E7VEC page 29
|
|
static const int mpc603ev_pll_config[12][9] =
|
|
{
|
|
// 16, 20, 25, 33, 40, 50, 60, 66, 75
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
// 2:1
|
|
{ -1, -1, -1, -1, -1, -1, -1, 0x4, 0x4 },
|
|
// 2.5:1
|
|
{ -1, -1, -1, -1, -1, 0x6, 0x6, 0x6, 0x6 },
|
|
// 3:1
|
|
{ -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8, 0x8 },
|
|
// 3.5:1
|
|
{ -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe, -1 },
|
|
// 4:1
|
|
{ -1, -1, -1, 0xa, 0xa, 0xa, 0xa, -1, -1 },
|
|
// 4.5:1
|
|
{ -1, -1, -1, 0x7, 0x7, 0x7, -1, -1, -1 },
|
|
// 5:1
|
|
{ -1, -1, 0xb, 0xb, 0xb, -1, -1, -1, -1 },
|
|
// 5.5:1
|
|
{ -1, -1, 0x9, 0x9, 0x9, -1, -1, -1, -1 },
|
|
// 6:1
|
|
{ -1, -1, 0xd, 0xd, 0xd, -1, -1, -1, -1 }
|
|
};
|
|
|
|
// PLL Configuration based on the table in MPC603E7TEC page 23
|
|
static const int mpc603r_pll_config[12][9] =
|
|
{
|
|
// 16, 20, 25, 33, 40, 50, 60, 66, 75
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
{ -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
// 2:1
|
|
{ -1, -1, -1, -1, 0x5, 0x5, 0x5, 0x5, 0x5 },
|
|
// 2.5:1
|
|
{ -1, -1, -1, -1, -1, -1, 0x6, 0x6, 0x6 },
|
|
// 3:1
|
|
{ -1, -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8 },
|
|
// 3.5:1
|
|
{ -1, -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe },
|
|
// 4:1
|
|
{ -1, -1, -1, -1, 0xa, 0xa, 0xa, 0xa, 0xa },
|
|
// 4.5:1
|
|
{ -1, -1, -1, 0x7, 0x7, 0x7, 0x7, 0x7, -1 },
|
|
// 5:1
|
|
{ -1, -1, -1, 0xb, 0xb, 0xb, 0xb, -1, -1 },
|
|
// 5.5:1
|
|
{ -1, -1, -1, 0x9, 0x9, 0x9, -1, -1, -1 },
|
|
// 6:1
|
|
{ -1, -1, 0xd, 0xd, 0xd, 0xd, -1, -1, -1 },
|
|
};
|
|
|
|
|
|
/******************************************************************************
|
|
Configuration Data Structures
|
|
******************************************************************************/
|
|
|
|
typedef struct {
|
|
PPC_MODEL pvr;
|
|
int bus_frequency_multiplier;
|
|
PPC_BUS_FREQUENCY bus_frequency;
|
|
} PPC_CONFIG;
|
|
|
|
typedef struct
|
|
{
|
|
UINT32 start;
|
|
UINT32 end;
|
|
UINT32 * ptr;
|
|
|
|
} PPC_FETCH_REGION;
|
|
|
|
|
|
/******************************************************************************
|
|
Functions
|
|
******************************************************************************/
|
|
|
|
extern UINT32 ppc_get_pc(void);
|
|
extern void ppc_set_irq_line(int irqline);
|
|
extern int ppc_execute(int cycles);
|
|
extern void ppc_reset(void);
|
|
extern void ppc_shutdown(void);
|
|
extern void ppc_init(const PPC_CONFIG *config); // must be called second!
|
|
extern void ppc_set_fetch(PPC_FETCH_REGION * fetch);
|
|
extern UINT64 ppc_total_cycles(void);
|
|
extern int ppc_get_cycles_per_sec(void);
|
|
extern int ppc_get_bus_freq_multipler(void);
|
|
extern int ppc_get_timer_ratio(void);
|
|
extern void ppc_set_timer_ratio(int ratio);
|
|
|
|
// These have been added to support the new Supermodel
|
|
extern void ppc_attach_bus(class CBus *BusPtr); // must be called first!
|
|
extern void ppc_save_state(class CBlockFile *SaveState);
|
|
extern void ppc_load_state(class CBlockFile *SaveState);
|
|
extern UINT32 ppc_get_gpr(unsigned num);
|
|
extern double ppc_get_fpr(unsigned num);
|
|
extern UINT32 ppc_get_lr(void);
|
|
extern UINT32 ppc_read_spr(unsigned spr);
|
|
extern UINT32 ppc_read_sr(unsigned num);
|
|
|
|
#ifdef SUPERMODEL_DEBUGGER
|
|
// These have been added to support the Supermodel debugger
|
|
extern void ppc_attach_debugger(class Debugger::CPPCDebug *PPCDebugPtr);
|
|
extern void ppc_detach_debugger();
|
|
#endif // SUPERMODEL_DEBUGGER
|
|
extern void ppc_break();
|
|
extern void ppc_set_pc(UINT32 pc);
|
|
extern UINT8 ppc_get_cr(unsigned num);
|
|
extern void ppc_set_cr(unsigned num, UINT8 val);
|
|
extern void ppc_set_gpr(unsigned num, UINT32 val);
|
|
extern void ppc_set_fpr(unsigned num, double val);
|
|
extern void ppc_write_spr(unsigned spr, UINT32 val);
|
|
extern void ppc_write_sr(unsigned num, UINT32 val);
|
|
extern UINT32 ppc_read_msr();
|
|
#endif // INCLUDED_PPC_H
|