mirror of
https://github.com/wavemotion-dave/NINTV-DS.git
synced 2025-06-18 13:55:33 -04:00
Version 4.5b with optimization to squeeze out better performance on the DS-Lite/Phat. Many more of the complex homebrews now run.
This commit is contained in:
parent
8bcbca5c27
commit
90d3e8ce8d
2
Makefile
2
Makefile
@ -14,7 +14,7 @@ include $(DEVKITARM)/ds_rules
|
||||
|
||||
export TARGET := NINTV-DS
|
||||
export TOPDIR := $(CURDIR)
|
||||
export VERSION := 4.5
|
||||
export VERSION := 4.5b
|
||||
|
||||
ICON := -b $(CURDIR)/logo.bmp "NINTV-DS $(VERSION);wavemotion-dave;https://github.com/wavemotion-dave/NINTV-DS"
|
||||
|
||||
|
BIN
NINTV-DS.nds
BIN
NINTV-DS.nds
Binary file not shown.
@ -26,7 +26,6 @@ GRAPHICS := gfx
|
||||
#ARCH := -mthumb -mthumb-interwork
|
||||
ARCH :=
|
||||
|
||||
#CFLAGS := -Wno-address-of-packed-member -Wno-multichar -O3 -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math $(ARCH)
|
||||
CFLAGS := -Ofast -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math $(ARCH) -falign-functions=16 -frename-registers
|
||||
|
||||
CFLAGS += $(INCLUDE) -DARM9
|
||||
|
@ -119,7 +119,8 @@ UINT16 __attribute__ ((aligned (4))) __attribute__((section(".dtcm"))) stretch[
|
||||
extern UINT8 bCP1610_PIN_IN_BUSRQ;
|
||||
extern UINT8 bCP1610_PIN_IN_INTRM;
|
||||
extern UINT8 bCP1610_PIN_OUT_BUSAK;
|
||||
|
||||
extern UINT8 bHandleInterrupts;
|
||||
extern UINT8 I;
|
||||
|
||||
AY38900::AY38900(MemoryBus* mb, GROM* go, GRAM* ga)
|
||||
: Processor("AY-3-8900"),
|
||||
@ -157,6 +158,8 @@ void AY38900::resetProcessor()
|
||||
bordersChanged = TRUE;
|
||||
colorStackChanged = TRUE;
|
||||
offsetsChanged = TRUE;
|
||||
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
|
||||
//local register data
|
||||
borderColor = 0;
|
||||
@ -195,7 +198,8 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
|
||||
//kick the irq line
|
||||
bCP1610_PIN_IN_INTRM = FALSE;
|
||||
bCP1610_PIN_IN_INTRM = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
|
||||
totalTicks += TICK_LENGTH_VBLANK;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -205,6 +209,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_START_ACTIVE_DISPLAY:
|
||||
bCP1610_PIN_IN_INTRM = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
|
||||
//if the display is not enabled, skip the rest of the modes
|
||||
if (!displayEnabled) {
|
||||
@ -221,6 +226,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
else {
|
||||
previousDisplayEnabled = TRUE;
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_START_ACTIVE_DISPLAY;
|
||||
if (totalTicks >= minimum) {
|
||||
mode = MODE_IDLE_ACTIVE_DISPLAY;
|
||||
@ -238,6 +244,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
//release SR2
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
|
||||
totalTicks += TICK_LENGTH_IDLE_ACTIVE_DISPLAY +
|
||||
(2*verticalOffset*TICK_LENGTH_SCANLINE);
|
||||
@ -248,6 +255,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_0:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(0);
|
||||
@ -257,6 +265,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_0:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -266,6 +275,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_1:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(1);
|
||||
@ -275,6 +285,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_1:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -284,6 +295,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_2:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(2);
|
||||
@ -293,6 +305,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_2:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -302,6 +315,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_3:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(3);
|
||||
@ -311,6 +325,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_3:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -320,6 +335,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_4:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(4);
|
||||
@ -329,6 +345,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_4:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -338,6 +355,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_5:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(5);
|
||||
@ -347,6 +365,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_5:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -356,6 +375,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_6:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(6);
|
||||
@ -365,6 +385,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_6:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -374,6 +395,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_7:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(7);
|
||||
@ -383,6 +405,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_7:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -392,6 +415,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_8:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(8);
|
||||
@ -401,6 +425,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_8:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -410,6 +435,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_9:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(9);
|
||||
@ -419,6 +445,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_9:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -428,6 +455,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_10:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(10);
|
||||
@ -437,6 +465,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_10:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
bCP1610_PIN_OUT_BUSAK = TRUE;
|
||||
totalTicks += TICK_LENGTH_RENDER_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
@ -446,6 +475,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_FETCH_ROW_11:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_FETCH_ROW;
|
||||
if (totalTicks >= minimum) {
|
||||
if (myConfig.bLatched) backtab.LatchRow(11);
|
||||
@ -455,6 +485,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
|
||||
case MODE_RENDER_ROW_11:
|
||||
bCP1610_PIN_IN_BUSRQ = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
|
||||
//this mode could be cut off in tick length if the vertical
|
||||
//offset is greater than 1
|
||||
@ -480,6 +511,7 @@ ITCM_CODE INT32 AY38900::tick(INT32 minimum) {
|
||||
case MODE_FETCH_ROW_12:
|
||||
default:
|
||||
bCP1610_PIN_IN_BUSRQ = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
totalTicks += TICK_LENGTH_SCANLINE;
|
||||
mode = MODE_VBLANK;
|
||||
break;
|
||||
|
@ -25,6 +25,9 @@ UINT16 amplitudes16Bit[16] __attribute__((section(".dtcm"))) =
|
||||
INT32 clockDivisor __attribute__((section(".dtcm")));
|
||||
INT32 clocksPerSample __attribute__((section(".dtcm")));
|
||||
|
||||
INT32 cachedTotalOutput __attribute__((section(".dtcm")));
|
||||
|
||||
|
||||
extern UINT8 bUseIVoice;
|
||||
|
||||
|
||||
@ -97,7 +100,7 @@ void AY38914::setClockDivisor(INT32 clockDivisor)
|
||||
clockDivisor = clockDivisor;
|
||||
}
|
||||
|
||||
ITCM_CODE INT32 AY38914::getClockDivisor() {
|
||||
INT32 AY38914::getClockDivisor() {
|
||||
return clockDivisor;
|
||||
}
|
||||
|
||||
@ -185,7 +188,9 @@ ITCM_CODE INT32 AY38914::tick(INT32 minimum)
|
||||
playSample1(cachedTotalOutput); // This is the ECS PSG on channel 1
|
||||
}
|
||||
else
|
||||
{
|
||||
playSample0(cachedTotalOutput); // This is the normal Intellivision console PSG
|
||||
}
|
||||
|
||||
totalTicks += clocksPerSample;
|
||||
|
||||
|
@ -77,16 +77,14 @@ class AY38914 : public Processor, public AudioProducer
|
||||
void setClockDivisor(INT32 clockDivisor);
|
||||
INT32 getClockDivisor();
|
||||
|
||||
//registers
|
||||
AY38914_Registers registers;
|
||||
AY38914_Registers registers;
|
||||
|
||||
struct Channel_t channel0;
|
||||
struct Channel_t channel1;
|
||||
struct Channel_t channel2;
|
||||
|
||||
struct Channel_t channel2;
|
||||
|
||||
//cached total output sample
|
||||
UINT8 cachedTotalOutputIsDirty;
|
||||
INT16 cachedTotalOutput;
|
||||
|
||||
//envelope data
|
||||
UINT8 envelopeIdle;
|
||||
|
@ -18,8 +18,8 @@ struct Channel_t
|
||||
{
|
||||
INT32 period;
|
||||
INT32 periodValue;
|
||||
INT32 volume;
|
||||
INT32 toneCounter;
|
||||
UINT8 volume;
|
||||
UINT8 tone;
|
||||
UINT8 envelope;
|
||||
UINT8 toneDisabled;
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
INT64 sampleBuffer[3] __attribute__((section(".dtcm")));
|
||||
INT32 commonClockCounter[3] __attribute__((section(".dtcm")));
|
||||
INT64 commonClocksPerSample[3] __attribute__((section(".dtcm")));
|
||||
INT32 commonClocksPerSample[3] __attribute__((section(".dtcm")));
|
||||
INT16 previousSample[3] __attribute__((section(".dtcm")));
|
||||
INT16 currentSample[3] __attribute__((section(".dtcm")));
|
||||
|
||||
@ -37,7 +37,7 @@ void audio_output_line_reset(void)
|
||||
// --------------------------------------------------------------------------------------
|
||||
ITCM_CODE void playSample0(INT16 sample) // Normal PSG
|
||||
{
|
||||
sampleBuffer[0] += currentSample[0] * commonClocksPerSample[0];
|
||||
sampleBuffer[0] += currentSample[0] * (INT64)commonClocksPerSample[0];
|
||||
commonClockCounter[0] += commonClocksPerSample[0];
|
||||
previousSample[0] = currentSample[0];
|
||||
currentSample[0] = sample;
|
||||
@ -45,7 +45,7 @@ ITCM_CODE void playSample0(INT16 sample) // Normal PSG
|
||||
|
||||
ITCM_CODE void playSample1(INT16 sample) // ECS PSG or Intellivoice SP0256
|
||||
{
|
||||
sampleBuffer[1] += currentSample[1] * commonClocksPerSample[1];
|
||||
sampleBuffer[1] += currentSample[1] * (INT64)commonClocksPerSample[1];
|
||||
commonClockCounter[1] += commonClocksPerSample[1];
|
||||
previousSample[1] = currentSample[1];
|
||||
currentSample[1] = sample;
|
||||
@ -54,7 +54,7 @@ ITCM_CODE void playSample1(INT16 sample) // ECS PSG or Intellivoice SP0256
|
||||
|
||||
ITCM_CODE void playSample2(INT16 sample) // ECS PSG or Intellivoice SP0256
|
||||
{
|
||||
sampleBuffer[2] += currentSample[2] * commonClocksPerSample[2];
|
||||
sampleBuffer[2] += currentSample[2] * (INT64)commonClocksPerSample[2];
|
||||
commonClockCounter[2] += commonClocksPerSample[2];
|
||||
previousSample[2] = currentSample[2];
|
||||
currentSample[2] = sample;
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
extern INT64 sampleBuffer[3];
|
||||
extern INT32 commonClockCounter[3];
|
||||
extern INT64 commonClocksPerSample[3];
|
||||
extern INT32 commonClocksPerSample[3];
|
||||
extern INT16 previousSample[3];
|
||||
extern INT16 currentSample[3];
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
// We store the "fast buffer" out in video RAM which is faster than main RAM if
|
||||
// there is a cache "miss". Experimentally, this buys us about 10% speed up.
|
||||
// ------------------------------------------------------------------------------
|
||||
#define PEEK_FAST(x) *((UINT16 *)0x06860000 + (x))
|
||||
#define PEEK_FAST(x) *((UINT16 *)(0x06860000 | ((x)<<1)))
|
||||
|
||||
//the eight registers available in the CP1610
|
||||
UINT16 r[8] __attribute__((section(".dtcm")));
|
||||
@ -40,8 +40,8 @@ UINT8 interruptible __attribute__((section(".dtcm")));
|
||||
UINT8 bCP1610_PIN_IN_BUSRQ __attribute__((section(".dtcm")));
|
||||
UINT8 bCP1610_PIN_IN_INTRM __attribute__((section(".dtcm")));
|
||||
UINT8 bCP1610_PIN_OUT_BUSAK __attribute__((section(".dtcm")));
|
||||
UINT8 bHandleInterrupts __attribute__((section(".dtcm"))) = 0;
|
||||
|
||||
//the four external lines
|
||||
INT8 ext __attribute__((section(".dtcm")));
|
||||
|
||||
CP1610::CP1610(MemoryBus* m, UINT16 resetAddress,
|
||||
@ -69,6 +69,7 @@ void CP1610::resetProcessor()
|
||||
for (INT32 i = 0; i < 7; i++)
|
||||
r[i] = 0;
|
||||
r[7] = resetAddress;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,28 +89,32 @@ ITCM_CODE INT32 CP1610::tick(INT32 minimum)
|
||||
|
||||
do {
|
||||
// This chunk of code doesn't happen very often (less than 10%) so we use the unlikely() gcc switch to help optmize
|
||||
if (unlikely(!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM)))
|
||||
if (unlikely(bHandleInterrupts))
|
||||
{
|
||||
if ((!bCP1610_PIN_IN_BUSRQ))
|
||||
if (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM))
|
||||
{
|
||||
if (interruptible)
|
||||
if ((!bCP1610_PIN_IN_BUSRQ))
|
||||
{
|
||||
bCP1610_PIN_OUT_BUSAK = bCP1610_PIN_IN_BUSRQ;
|
||||
return MAX((usedCycles<<2), minimum);
|
||||
if (interruptible)
|
||||
{
|
||||
bCP1610_PIN_OUT_BUSAK = bCP1610_PIN_IN_BUSRQ;
|
||||
return MAX((usedCycles<<2), minimum);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // if ((I && !bCP1610_PIN_IN_INTRM))
|
||||
{
|
||||
if (interruptible)
|
||||
else // if ((I && !bCP1610_PIN_IN_INTRM))
|
||||
{
|
||||
bCP1610_PIN_IN_INTRM = TRUE;
|
||||
interruptible = false;
|
||||
memoryBus->poke(r[6], r[7]);
|
||||
r[6]++;
|
||||
r[7] = interruptAddress;
|
||||
usedCycles += 7;
|
||||
if ((usedCycles << 2) >= minimum)
|
||||
return (usedCycles<<2);
|
||||
if (interruptible)
|
||||
{
|
||||
bCP1610_PIN_IN_INTRM = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
interruptible = false;
|
||||
memoryBus->poke(r[6], r[7]);
|
||||
r[6]++;
|
||||
r[7] = interruptAddress;
|
||||
usedCycles += 7;
|
||||
if ((usedCycles << 2) >= minimum)
|
||||
return (usedCycles<<2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,6 +177,7 @@ UINT16 CP1610::EIS() {
|
||||
interruptible = FALSE;
|
||||
|
||||
I = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
|
||||
D = FALSE;
|
||||
return 4;
|
||||
@ -182,6 +188,7 @@ UINT16 CP1610::DIS() {
|
||||
interruptible = FALSE;
|
||||
|
||||
I = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
|
||||
D = FALSE;
|
||||
return 4;
|
||||
@ -236,6 +243,7 @@ ITCM_CODE UINT16 CP1610::JSR(UINT16 registerNum, UINT16 target) {
|
||||
|
||||
UINT16 CP1610::JE(UINT16 target) {
|
||||
I = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
r[7] = target;
|
||||
interruptible = TRUE;
|
||||
D = FALSE;
|
||||
@ -244,6 +252,7 @@ UINT16 CP1610::JE(UINT16 target) {
|
||||
|
||||
UINT16 CP1610::JSRE(UINT16 registerNum, UINT16 target) {
|
||||
I = TRUE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
r[registerNum] = r[7]+3;
|
||||
r[7] = target;
|
||||
interruptible = TRUE;
|
||||
@ -254,6 +263,7 @@ UINT16 CP1610::JSRE(UINT16 registerNum, UINT16 target) {
|
||||
|
||||
UINT16 CP1610::JD(UINT16 target) {
|
||||
I = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
r[7] = target;
|
||||
interruptible = TRUE;
|
||||
|
||||
@ -263,6 +273,7 @@ UINT16 CP1610::JD(UINT16 target) {
|
||||
|
||||
UINT16 CP1610::JSRD(UINT16 registerNum, UINT16 target) {
|
||||
I = FALSE;
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
r[registerNum] = r[7]+3;
|
||||
r[7] = target;
|
||||
interruptible = TRUE;
|
||||
@ -275,10 +286,9 @@ ITCM_CODE UINT16 CP1610::INCR(UINT16 registerNum) {
|
||||
r[7]++;
|
||||
interruptible = TRUE;
|
||||
|
||||
UINT16 newValue = r[registerNum]+1;
|
||||
S = !!(newValue & 0x8000);
|
||||
Z = !newValue;
|
||||
r[registerNum] = newValue;
|
||||
r[registerNum]++;
|
||||
S = !!(r[registerNum] & 0x8000);
|
||||
Z = !r[registerNum];
|
||||
|
||||
D = FALSE;
|
||||
return 6;
|
||||
@ -288,10 +298,9 @@ ITCM_CODE UINT16 CP1610::DECR(UINT16 registerNum) {
|
||||
r[7]++;
|
||||
interruptible = TRUE;
|
||||
|
||||
UINT16 newValue = r[registerNum]-1;
|
||||
S = !!(newValue & 0x8000);
|
||||
Z = !newValue;
|
||||
r[registerNum] = newValue;
|
||||
r[registerNum]--;
|
||||
S = !!(r[registerNum] & 0x8000);
|
||||
Z = !r[registerNum];
|
||||
|
||||
D = FALSE;
|
||||
return 6;
|
||||
@ -944,7 +953,7 @@ UINT16 CP1610::BESC(INT16 displacement) {
|
||||
return 7;
|
||||
}
|
||||
|
||||
UINT16 CP1610::MVO(UINT16 registerNum, UINT16 address) {
|
||||
ITCM_CODE UINT16 CP1610::MVO(UINT16 registerNum, UINT16 address) {
|
||||
r[7] += 2;
|
||||
interruptible = FALSE;
|
||||
|
||||
@ -984,8 +993,9 @@ UINT16 CP1610::MVI_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
|
||||
r[registerToReceive] = getIndirect(registerWithAddress);
|
||||
|
||||
UINT8 cycles = (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
D = FALSE;
|
||||
return (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
return cycles;
|
||||
}
|
||||
|
||||
ITCM_CODE UINT16 CP1610::ADD(UINT16 address, UINT16 registerNum) {
|
||||
@ -1018,8 +1028,9 @@ UINT16 CP1610::ADD_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
Z = !(newValue & 0xFFFF);
|
||||
r[registerToReceive] = (UINT16)newValue;
|
||||
|
||||
UINT8 cycles = (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
D = FALSE;
|
||||
return (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
return cycles;
|
||||
}
|
||||
|
||||
ITCM_CODE UINT16 CP1610::SUB(UINT16 address, UINT16 registerNum) {
|
||||
@ -1052,8 +1063,9 @@ UINT16 CP1610::SUB_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
Z = !(newValue & 0xFFFF);
|
||||
r[registerToReceive] = (UINT16)newValue;
|
||||
|
||||
UINT8 cycles = (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
D = FALSE;
|
||||
return (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
return cycles;
|
||||
}
|
||||
|
||||
ITCM_CODE UINT16 CP1610::CMP(UINT16 address, UINT16 registerNum) {
|
||||
@ -1072,7 +1084,7 @@ ITCM_CODE UINT16 CP1610::CMP(UINT16 address, UINT16 registerNum) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
UINT16 CP1610::CMP_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
ITCM_CODE UINT16 CP1610::CMP_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
r[7]++;
|
||||
interruptible = TRUE;
|
||||
|
||||
@ -1084,8 +1096,9 @@ UINT16 CP1610::CMP_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
S = !!(newValue & 0x8000);
|
||||
Z = !(newValue & 0xFFFF);
|
||||
|
||||
UINT8 cycles = (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
D = FALSE;
|
||||
return (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
return cycles;
|
||||
}
|
||||
|
||||
ITCM_CODE UINT16 CP1610::AND(UINT16 address, UINT16 registerNum) {
|
||||
@ -1110,8 +1123,9 @@ UINT16 CP1610::AND_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
Z = !value;
|
||||
r[registerToReceive] = value;
|
||||
|
||||
UINT8 cycles = (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
D = FALSE;
|
||||
return (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
return cycles;
|
||||
}
|
||||
|
||||
UINT16 CP1610::XOR(UINT16 address, UINT16 registerNum) {
|
||||
@ -1136,8 +1150,9 @@ UINT16 CP1610::XOR_ind(UINT16 registerWithAddress, UINT16 registerToReceive) {
|
||||
Z = !value;
|
||||
r[registerToReceive] = value;
|
||||
|
||||
UINT8 cycles = (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
D = FALSE;
|
||||
return (D ? 10 : (registerWithAddress == 6 ? 11 : 8));
|
||||
return cycles;
|
||||
}
|
||||
|
||||
UINT16 CP1610::decode(void)
|
||||
@ -4280,4 +4295,6 @@ void CP1610::setState(CP1610State *state)
|
||||
interruptAddress = state->interruptAddress;
|
||||
resetAddress = state->resetAddress;
|
||||
for (int i=0; i<8; i++) r[i] = state->r[i];
|
||||
|
||||
bHandleInterrupts = (!bCP1610_PIN_IN_BUSRQ || (I && !bCP1610_PIN_IN_INTRM));
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ ITCM_CODE void GRAM::poke(UINT16 location, UINT16 value)
|
||||
{
|
||||
if (!enabled) return;
|
||||
location &= 0x01FF;
|
||||
|
||||
|
||||
gram_image[location] = (UINT8)value;
|
||||
dirtyCards[location>>3] = TRUE;
|
||||
dirtyRAM = TRUE;
|
||||
|
@ -125,7 +125,7 @@ void JLP::WriteFlashFile(void)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
dsPrintValue(2,0,0, (char*)"JLP FLASH");
|
||||
dsPrintValue(hud_x,hud_y,0, (char*)"JLP FLASH");
|
||||
GetFlashFilename();
|
||||
fp = fopen(flash_filename, "wb");
|
||||
if (fp != NULL)
|
||||
@ -133,7 +133,7 @@ void JLP::WriteFlashFile(void)
|
||||
fwrite(jlp_flash, 1, JLP_FLASH_SIZE, fp);
|
||||
fclose(fp);
|
||||
}
|
||||
dsPrintValue(2,0,0,(char*)" ");
|
||||
dsPrintValue(hud_x,hud_y,0,(char*)" ");
|
||||
}
|
||||
|
||||
void JLP::ScheduleWriteFlashFile(void)
|
||||
|
@ -1,10 +1,10 @@
|
||||
// =====================================================================================
|
||||
// Copyright (c) 2021-2024 Dave Bernazzani (wavemotion-dave)
|
||||
//
|
||||
// Copying and distribution of this emulator, its source code and associated
|
||||
// readme files, with or without modification, are permitted in any medium without
|
||||
// Copying and distribution of this emulator, its source code and associated
|
||||
// readme files, with or without modification, are permitted in any medium without
|
||||
// royalty provided the this copyright notice is used and wavemotion-dave (NINTV-DS)
|
||||
// and Kyle Davis (BLISS) are thanked profusely.
|
||||
// and Kyle Davis (BLISS) are thanked profusely.
|
||||
//
|
||||
// The NINTV-DS emulator is offered as-is, without any warranty.
|
||||
// =====================================================================================
|
||||
@ -18,7 +18,7 @@ UINT16 MAX_READ_OVERLAPPED_MEMORIES = 2;
|
||||
UINT16 MAX_WRITE_OVERLAPPED_MEMORIES = 3;
|
||||
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
// We use this class and single object to fill all unused memory locations in the memory map.
|
||||
// We use this class and single object to fill all unused memory locations in the memory map.
|
||||
// Returns 0xFFFF on all access as a real intellivision would with unused memory regions.
|
||||
// ----------------------------------------------------------------------------------------------
|
||||
class UnusedMemory : public Memory
|
||||
@ -47,9 +47,9 @@ public:
|
||||
// memories per address location which is sufficient provided we are only
|
||||
// loading normal ROMs into a stock intellivision with, at most, an intellivoice
|
||||
// or the JLP cart as the only peripherals... still, this is a strain on the
|
||||
// older DS-LITE/PHAT. The original BLISS core allowed 16 overlapping memory
|
||||
// regions (to handle page flipping) which will fit into the DSi but is too
|
||||
// large for the original DS-LITE/PHAT so for older hardware, we strip down
|
||||
// older DS-LITE/PHAT. The original BLISS core allowed 16 overlapping memory
|
||||
// regions (to handle page flipping) which will fit into the DSi but is too
|
||||
// large for the original DS-LITE/PHAT so for older hardware, we strip down
|
||||
// to the bare essentials. For the DSi we can allocate more memory and provide
|
||||
// the full 16 overlapped mapped memories.
|
||||
// -------------------------------------------------------------------------------
|
||||
@ -60,50 +60,49 @@ MemoryBus::MemoryBus()
|
||||
// -------------------------------------------------------------------------------------
|
||||
// We swap in a larger memory model for the DSi to handle really complex page flipping
|
||||
// -------------------------------------------------------------------------------------
|
||||
if (isDSiMode())
|
||||
if (isDSiMode())
|
||||
{
|
||||
MAX_READ_OVERLAPPED_MEMORIES = 16; // Good enough for any page-flipping game. This is massive!
|
||||
MAX_WRITE_OVERLAPPED_MEMORIES = 17; // Need one extra here to handle the GRAM mirrors up in odd places in ROM
|
||||
}
|
||||
else
|
||||
{
|
||||
MAX_READ_OVERLAPPED_MEMORIES = 2; // Good enough for almost all games except very large page-flipping games
|
||||
MAX_WRITE_OVERLAPPED_MEMORIES = 3; // Need one extra here to handle the GRAM mirrors up in odd places in ROM
|
||||
MAX_READ_OVERLAPPED_MEMORIES = 16; // Good enough for almost all games except very large page-flipping games
|
||||
MAX_WRITE_OVERLAPPED_MEMORIES = 17; // Need one extra here to handle the GRAM mirrors up in odd places in ROM
|
||||
}
|
||||
|
||||
UINT32 size = 1 << (sizeof(UINT16) << 3);
|
||||
UINT32 i;
|
||||
writeableMemoryCounts = new UINT8[size];
|
||||
memset(writeableMemoryCounts, 0, sizeof(UINT8) * size);
|
||||
writeableMemorySpace = new Memory**[size];
|
||||
|
||||
writeableMemorySpace = new Memory**[size>>4];
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------------------
|
||||
// We do this rather than allocate piecemeal so we avoid malloc overhead and extra bytes padded (saves almost 500K on DS)
|
||||
// On the DS with 3 overlapped memories (enough for most games), this is still 1.5MB of memory (out of the 3.5MB available)
|
||||
// On the DSi with a full 16 overlapped memories (enough for any game), this is a whopping 8MB (out of the 15.5MB available)
|
||||
// ---------------------------------------------------------------------------------------------------------------------------
|
||||
overlappedMemoryPool = new UINT32[size*(MAX_READ_OVERLAPPED_MEMORIES+MAX_WRITE_OVERLAPPED_MEMORIES)];
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
overlappedMemoryPool = new UINT32[(size*(MAX_READ_OVERLAPPED_MEMORIES+MAX_WRITE_OVERLAPPED_MEMORIES))>>4];
|
||||
UINT32 *memPoolPtr = (UINT32 *)overlappedMemoryPool;
|
||||
|
||||
for (i = 0; i < size>>4; i++)
|
||||
{
|
||||
writeableMemorySpace[i] = (Memory **)overlappedMemoryPool;
|
||||
writeableMemorySpace[i] = (Memory **)memPoolPtr;
|
||||
for (int j=0; j<MAX_WRITE_OVERLAPPED_MEMORIES; j++)
|
||||
{
|
||||
overlappedMemoryPool++;
|
||||
memPoolPtr++;
|
||||
writeableMemorySpace[i][j] = &MyUnusedMemory;
|
||||
}
|
||||
}
|
||||
readableMemoryCounts = (UINT16 *) 0x06820000; // Use video memory ... slightly faster and saves main RAM
|
||||
memset(readableMemoryCounts, 0, sizeof(UINT16) * size);
|
||||
readableMemorySpace = new Memory**[size];
|
||||
for (i = 0; i < size; i++)
|
||||
readableMemorySpace = new Memory**[size>>4];
|
||||
for (i = 0; i < size>>4; i++)
|
||||
{
|
||||
readableMemorySpace[i] = (Memory **)overlappedMemoryPool;
|
||||
readableMemorySpace[i] = (Memory **)memPoolPtr;
|
||||
for (int j=0; j<MAX_READ_OVERLAPPED_MEMORIES; j++)
|
||||
{
|
||||
overlappedMemoryPool++;
|
||||
memPoolPtr++;
|
||||
readableMemorySpace[i][j] = &MyUnusedMemory;
|
||||
}
|
||||
}
|
||||
}
|
||||
mappedMemoryCount = 0;
|
||||
}
|
||||
@ -141,7 +140,7 @@ void MemoryBus::addMemory(Memory* m)
|
||||
FatalError("GAME TOO COMPLEX - MAX MEMORIES");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//add all of the readable locations, if any
|
||||
if (readAddressMask != 0) {
|
||||
UINT8 zeroCount = 0;
|
||||
@ -151,7 +150,7 @@ void MemoryBus::addMemory(Memory* m)
|
||||
zeroCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UINT8 combinationCount = (1<<zeroCount);
|
||||
for (i = 0; i < combinationCount; i++) {
|
||||
UINT16 orMask = 0;
|
||||
@ -167,7 +166,7 @@ void MemoryBus::addMemory(Memory* m)
|
||||
FatalError("ERROR MAX READABLE MEM OVERLAP");
|
||||
return;
|
||||
}
|
||||
readableMemorySpace[k][memCount] = m;
|
||||
readableMemorySpace[k>>4][memCount] = m;
|
||||
readableMemoryCounts[k]++;
|
||||
}
|
||||
}
|
||||
@ -182,7 +181,7 @@ void MemoryBus::addMemory(Memory* m)
|
||||
zeroCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UINT8 combinationCount = (1<<zeroCount);
|
||||
for (i = 0; i < combinationCount; i++) {
|
||||
UINT16 orMask = 0;
|
||||
@ -197,8 +196,8 @@ void MemoryBus::addMemory(Memory* m)
|
||||
{
|
||||
FatalError("ERROR MAX WRITEABLE MEM OVERLAP");
|
||||
return;
|
||||
}
|
||||
writeableMemorySpace[k][memCount] = m;
|
||||
}
|
||||
writeableMemorySpace[k>>4][memCount] = m;
|
||||
writeableMemoryCounts[k]++;
|
||||
}
|
||||
}
|
||||
@ -232,7 +231,7 @@ void MemoryBus::removeMemory(Memory* m)
|
||||
zeroCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UINT8 combinationCount = (1<<zeroCount);
|
||||
for (i = 0; i < combinationCount; i++) {
|
||||
UINT16 orMask = 0;
|
||||
@ -241,18 +240,22 @@ void MemoryBus::removeMemory(Memory* m)
|
||||
UINT16 nextAddress = readAddress | orMask;
|
||||
UINT16 nextEnd = nextAddress + readSize - 1;
|
||||
|
||||
for (UINT32 k = nextAddress; k <= nextEnd; k++) {
|
||||
for (UINT32 k = nextAddress; k <= nextEnd; k++)
|
||||
{
|
||||
UINT16 memCount = readableMemoryCounts[k];
|
||||
for (UINT16 n = 0; n < memCount; n++) {
|
||||
if (readableMemorySpace[k][n] == m) {
|
||||
for (INT32 l = n; l < (memCount-1); l++) {
|
||||
readableMemorySpace[k][l] = readableMemorySpace[k][l+1];
|
||||
for (UINT16 n = 0; n < memCount; n++)
|
||||
{
|
||||
if (readableMemorySpace[k>>4][n] == m)
|
||||
{
|
||||
for (INT32 l = n; l < (memCount-1); l++)
|
||||
{
|
||||
readableMemorySpace[k>>4][l] = readableMemorySpace[k>>4][l+1];
|
||||
}
|
||||
readableMemorySpace[k][memCount-1] = &MyUnusedMemory;
|
||||
readableMemoryCounts[k]--;
|
||||
readableMemorySpace[k>>4][memCount-1] = &MyUnusedMemory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
readableMemoryCounts[k]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,7 +269,7 @@ void MemoryBus::removeMemory(Memory* m)
|
||||
zeroCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UINT8 combinationCount = (1<<zeroCount);
|
||||
for (i = 0; i < combinationCount; i++) {
|
||||
UINT16 orMask = 0;
|
||||
@ -277,17 +280,19 @@ void MemoryBus::removeMemory(Memory* m)
|
||||
|
||||
for (UINT32 k = nextAddress; k <= nextEnd; k++) {
|
||||
UINT16 memCount = writeableMemoryCounts[k];
|
||||
for (UINT16 n = 0; n < memCount; n++) {
|
||||
if (writeableMemorySpace[k][n] == m) {
|
||||
for (INT32 l = n; l < (memCount-1); l++) {
|
||||
writeableMemorySpace[k][l] =
|
||||
writeableMemorySpace[k][l+1];
|
||||
for (UINT16 n = 0; n < memCount; n++)
|
||||
{
|
||||
if (writeableMemorySpace[k>>4][n] == m)
|
||||
{
|
||||
for (INT32 l = n; l < (memCount-1); l++)
|
||||
{
|
||||
writeableMemorySpace[k>>4][l] = writeableMemorySpace[k>>4][l+1];
|
||||
}
|
||||
writeableMemorySpace[k][memCount-1] = &MyUnusedMemory;
|
||||
writeableMemoryCounts[k]--;
|
||||
writeableMemorySpace[k>>4][memCount-1] = &MyUnusedMemory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
writeableMemoryCounts[k]--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -310,7 +315,7 @@ void MemoryBus::removeAll()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// This only needs to be called if we are in a region that might have multiple things mapped to it...
|
||||
// This only needs to be called if we are in a region that might have multiple things mapped to it...
|
||||
// Most of the PC ROM access will go through the normal peek() handler which is significantly faster...
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
ITCM_CODE UINT16 MemoryBus::peek_slow(UINT16 location)
|
||||
@ -320,7 +325,7 @@ ITCM_CODE UINT16 MemoryBus::peek_slow(UINT16 location)
|
||||
UINT16 value = 0xFFFF;
|
||||
for (UINT16 i = 0; i < numMemories; i++)
|
||||
{
|
||||
value &= readableMemorySpace[location][i]->peek(location);
|
||||
value &= readableMemorySpace[location>>4][i]->peek(location);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -334,13 +339,13 @@ ITCM_CODE void MemoryBus::poke(UINT16 location, UINT16 value)
|
||||
|
||||
for (UINT16 i = 0; i < numMemories; i++)
|
||||
{
|
||||
writeableMemorySpace[location][i]->poke(location, value);
|
||||
writeableMemorySpace[location>>4][i]->poke(location, value);
|
||||
}
|
||||
|
||||
|
||||
// For the lower 4K ... keep the "fast memory" updated
|
||||
if (location < 0x1000)
|
||||
{
|
||||
*((UINT16 *)0x06860000 + location) = value;
|
||||
*((UINT16 *)(0x06860000 | (location<<1))) = value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,7 +353,7 @@ ITCM_CODE void MemoryBus::poke(UINT16 location, UINT16 value)
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Poke Cheat Codes does not need any optimization - only happens once after ROM load.
|
||||
// We allow poke to both readable and writable memory spaces - most of the time we are
|
||||
// modifying a ROM location to provide some special cheat effect. We don't need to
|
||||
// modifying a ROM location to provide some special cheat effect. We don't need to
|
||||
// update the "fast memory" as the cheats are applied post ROM load but pre "fast buffer".
|
||||
// ---------------------------------------------------------------------------------------
|
||||
void MemoryBus::poke_cheat(UINT16 location, UINT16 value)
|
||||
@ -357,13 +362,13 @@ void MemoryBus::poke_cheat(UINT16 location, UINT16 value)
|
||||
|
||||
for (UINT16 i = 0; i < numMemories; i++)
|
||||
{
|
||||
readableMemorySpace[location][i]->poke_cheat(location, value);
|
||||
readableMemorySpace[location>>4][i]->poke_cheat(location, value);
|
||||
}
|
||||
|
||||
numMemories = writeableMemoryCounts[location];
|
||||
|
||||
for (UINT16 i = 0; i < numMemories; i++)
|
||||
{
|
||||
writeableMemorySpace[location][i]->poke_cheat(location, value);
|
||||
writeableMemorySpace[location>>4][i]->poke_cheat(location, value);
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ class MemoryBus
|
||||
|
||||
void reset();
|
||||
|
||||
inline UINT16 peek(UINT16 location) {if (((UINT16 *) 0x06820000)[location] == 1) return readableMemorySpace[location][0]->peek(location); else return peek_slow(location);}
|
||||
inline UINT16 peek(UINT16 location) {if (((UINT16 *) 0x06820000)[location] == 1) return readableMemorySpace[location>>4][0]->peek(location); else return peek_slow(location);}
|
||||
UINT16 peek_slow(UINT16 location);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -51,9 +51,9 @@ class MemoryBus
|
||||
// ------------------------------------------------------
|
||||
UINT16 peek_slow_and_safe(UINT16 location)
|
||||
{
|
||||
if (readableMemorySpace[location])
|
||||
if (readableMemorySpace[location>>4])
|
||||
{
|
||||
if (readableMemorySpace[location][0])
|
||||
if (readableMemorySpace[location>>4][0])
|
||||
{
|
||||
return peek_slow(location);
|
||||
}
|
||||
@ -72,10 +72,10 @@ class MemoryBus
|
||||
private:
|
||||
Memory* mappedMemories[MAX_MAPPED_MEMORIES];
|
||||
UINT16 mappedMemoryCount;
|
||||
UINT8* writeableMemoryCounts;
|
||||
Memory*** writeableMemorySpace;
|
||||
UINT16* readableMemoryCounts;
|
||||
Memory*** readableMemorySpace;
|
||||
UINT16 *readableMemoryCounts;
|
||||
UINT8 *writeableMemoryCounts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -63,6 +63,12 @@ public:
|
||||
return ((UINT16*)image)[location];
|
||||
}
|
||||
|
||||
// Useful for when we are copying chunks of memory for bank-switching
|
||||
inline UINT8 *peek_image_address()
|
||||
{
|
||||
return image;
|
||||
}
|
||||
|
||||
UINT16 getWriteSize();
|
||||
UINT16 getWriteAddress();
|
||||
UINT16 getWriteAddressMask();
|
||||
|
@ -62,9 +62,12 @@ ITCM_CODE void ROMBanker::poke(UINT16 address, UINT16 value)
|
||||
if (bEnabled) // If we are enabling this bank, we can quickly refresh the fast_memory[]
|
||||
{
|
||||
UINT16 *fast_memory = (UINT16 *)0x06860000;
|
||||
for (int i=(address&0xF000); i<=((address&0xF000)|0xFFF); i++)
|
||||
UINT32 *ptr = (UINT32 *)rom->peek_image_address();
|
||||
UINT32 *dest = (UINT32 *) &fast_memory[(address&0xF000)];
|
||||
|
||||
for (int i=(address&0xF000); i<=((address&0xF000)|0xFFF); i+=2)
|
||||
{
|
||||
fast_memory[i] = rom->peek_fast(i&0xFFF);
|
||||
*dest++ = *ptr++; // Do this 32-bits at a time for a very slight speed improvement on moving the memory
|
||||
}
|
||||
}
|
||||
else if (gBankerIsMappedHere[address>>12][value&0xF] == 0) // Nothing is here... nothing will be swapped in... We need to check the main memory as there may be an unswapped bank in there...
|
||||
|
@ -800,7 +800,7 @@ void SP0256::PAUSE(INT32 immed4) {
|
||||
periodInterpolation = 0;
|
||||
}
|
||||
|
||||
ITCM_CODE void SP0256::decode() {
|
||||
void SP0256::decode() {
|
||||
INT32 immed4 = readBits(4);
|
||||
INT32 nextInstruction = readBitsReverse(4);
|
||||
switch (nextInstruction) {
|
||||
@ -858,7 +858,7 @@ ITCM_CODE void SP0256::decode() {
|
||||
}
|
||||
}
|
||||
|
||||
ITCM_CODE INT32 SP0256::flipEndian(INT32 value, INT32 bits) {
|
||||
INT32 SP0256::flipEndian(INT32 value, INT32 bits) {
|
||||
INT32 output = 0;
|
||||
INT32 bitMask = 1;
|
||||
for (INT32 i = 0; i < bits; i++) {
|
||||
|
@ -60,7 +60,7 @@ int main(int argc, char **argv)
|
||||
else
|
||||
{
|
||||
mySoundFrequency = 12000; // For the DS-LITE/PHAT we need more speed so we reduce the sound quality a bit...
|
||||
MAX_ROM_FILE_SIZE = (256 * 1024); // Bit enough for all original 125 commercial games and 98% of homebrews
|
||||
MAX_ROM_FILE_SIZE = (512 * 1024); // Bit enough for all original 125 commercial games and 98% of homebrews
|
||||
}
|
||||
|
||||
bin_image_buf = new UINT8[MAX_ROM_FILE_SIZE];
|
||||
|
@ -54,6 +54,9 @@ UINT8 bUseDiscOverlay __attribute__((section(".dtcm"))) = false;
|
||||
UINT8 bGameLoaded __attribute__((section(".dtcm"))) = false;
|
||||
UINT8 bMetaSpeedup __attribute__((section(".dtcm"))) = false;
|
||||
|
||||
UINT8 hud_x = 3;
|
||||
UINT8 hud_y = 0;
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// This one is accessed rather often so we'll put it in .dtcm
|
||||
// -------------------------------------------------------------
|
||||
@ -809,10 +812,10 @@ ITCM_CODE void pollInputs(void)
|
||||
// -------------------------------------------------------------------------------------
|
||||
if ((keys_pressed & KEY_L) && (keys_pressed & KEY_R))
|
||||
{
|
||||
dsPrintValue(3,0,0,(char*)"SNAP");
|
||||
dsPrintValue(hud_x+2,hud_y,0,(char*)"SNAP");
|
||||
screenshot();
|
||||
WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;WAITVBL;
|
||||
dsPrintValue(3,0,0,(char*)" ");
|
||||
dsPrintValue(hud_x+2,hud_y,0,(char*)" ");
|
||||
}
|
||||
else
|
||||
if ((keys_pressed & KEY_A) && (keys_pressed & KEY_X))
|
||||
@ -1201,6 +1204,10 @@ void dsShowScreenMain(bool bFull, bool bPlayJingle)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
hud_x = 3;
|
||||
hud_y = 0;
|
||||
|
||||
// Now show the bottom screen - usualy some form of overlay...
|
||||
#ifdef DEBUG_ENABLE
|
||||
show_debug_overlay();
|
||||
@ -1441,7 +1448,7 @@ ITCM_CODE void Run(char *initial_file)
|
||||
{
|
||||
sprintf(tmp,"%-6d %-6d %-5d %-5d", debug[0], debug[1], debug[2], debug[3]);
|
||||
//sprintf(tmp,"%04X %04X %04X %04X %02X %02X", debug[0], debug[1], debug[2], debug[3], debug[4], debug[5]);
|
||||
dsPrintValue(6,0,0,tmp);
|
||||
dsPrintValue(5,0,0,tmp);
|
||||
}
|
||||
|
||||
// If we are using the JLP, we call into the 1 second tick function in case there is a dirty flash that needs writing...
|
||||
|
@ -27,6 +27,7 @@ typedef enum _RunState
|
||||
extern UINT16 emu_frames;
|
||||
extern UINT16 frames_per_sec_calc;
|
||||
extern UINT8 oneSecTick;
|
||||
extern UINT8 hud_x, hud_y;
|
||||
|
||||
extern UINT8 b_dsi_mode;
|
||||
|
||||
|
@ -232,6 +232,22 @@ void load_custom_overlay(bool bCustomGeneric)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle HUD_x Line
|
||||
if (strstr(szName, ".hudx") != NULL)
|
||||
{
|
||||
char *ptr = strstr(szName, ".hudx");
|
||||
ptr += 6;
|
||||
hud_x = strtoul(ptr, &ptr, 10);
|
||||
}
|
||||
|
||||
// Handle HUD_y Line
|
||||
if (strstr(szName, ".hudy") != NULL)
|
||||
{
|
||||
char *ptr = strstr(szName, ".hudy");
|
||||
ptr += 6;
|
||||
hud_y = strtoul(ptr, &ptr, 10);
|
||||
}
|
||||
|
||||
// Handle Tile Line
|
||||
if (strstr(szName, ".tile") != NULL)
|
||||
{
|
||||
|
@ -25,7 +25,7 @@ extern Emulator *currentEmu;
|
||||
extern Rip *currentRip;
|
||||
extern UINT16 global_frames;
|
||||
|
||||
#define CURRENT_SAVE_FILE_VER 0x000A
|
||||
#define CURRENT_SAVE_FILE_VER 0x000B
|
||||
|
||||
// ------------------------------------------------------
|
||||
// We allow up to 3 saves per game. More than enough.
|
||||
|
Loading…
Reference in New Issue
Block a user