diff --git a/src/GBA.cpp b/src/GBA.cpp index 7ccdb4b5..8207366f 100644 --- a/src/GBA.cpp +++ b/src/GBA.cpp @@ -90,6 +90,7 @@ u32 busPrefetchCount = 0; int cpuDmaTicksToUpdate = 0; int cpuDmaCount = 0; bool cpuDmaHack = false; +bool cpuDmaHack2 = false; u32 cpuDmaLast = 0; int dummyAddress = 0; @@ -2313,11 +2314,15 @@ void doDMA(u32 &s, u32 &d, u32 si, u32 di, u32 c, int transfer32) } -void CPUCheckDMA(int reason, int dmamask) +bool CPUCheckDMA(int reason, int dmamask) { + bool res = false; + cpuDmaHack = 0; + // DMA 0 if((DM0CNT_H & 0x8000) && (dmamask & 1)) { if(((DM0CNT_H >> 12) & 3) == reason) { + res = true; u32 sourceIncrement = 4; u32 destIncrement = 4; switch((DM0CNT_H >> 7) & 3) { @@ -2375,6 +2380,8 @@ void CPUCheckDMA(int reason, int dmamask) // DMA 1 if((DM1CNT_H & 0x8000) && (dmamask & 2)) { if(((DM1CNT_H >> 12) & 3) == reason) { + res = true; + u32 sourceIncrement = 4; u32 destIncrement = 4; switch((DM1CNT_H >> 7) & 3) { @@ -2444,6 +2451,7 @@ void CPUCheckDMA(int reason, int dmamask) // DMA 2 if((DM2CNT_H & 0x8000) && (dmamask & 4)) { if(((DM2CNT_H >> 12) & 3) == reason) { + res = true; u32 sourceIncrement = 4; u32 destIncrement = 4; switch((DM2CNT_H >> 7) & 3) { @@ -2514,6 +2522,7 @@ void CPUCheckDMA(int reason, int dmamask) // DMA 3 if((DM3CNT_H & 0x8000) && (dmamask & 8)) { if(((DM3CNT_H >> 12) & 3) == reason) { + res = true; u32 sourceIncrement = 4; u32 destIncrement = 4; switch((DM3CNT_H >> 7) & 3) { @@ -2565,6 +2574,8 @@ void CPUCheckDMA(int reason, int dmamask) } } } + cpuDmaHack = false; + return res; } void CPUUpdateRegister(u32 address, u16 value) @@ -3846,6 +3857,8 @@ void CPULoop(int ticks) int timerOverflow = 0; // variable used by the CPU core cpuTotalTicks = 0; + if(cpuDmaHack2) + cpuNextEvent = 1; cpuBreakLoop = false; cpuNextEvent = CPUUpdateTicks(); if(cpuNextEvent > ticks) @@ -4044,7 +4057,7 @@ void CPULoop(int ticks) IF |= 1; UPDATE_REG(0x202, IF); } - CPUCheckDMA(1, 0x0f); + cpuDmaHack2 = CPUCheckDMA(1, 0x0f); if(frameCount >= framesToSkip) { systemDrawScreen(); frameCount = 0; @@ -4164,7 +4177,7 @@ void CPULoop(int ticks) DISPSTAT |= 2; UPDATE_REG(0x04, DISPSTAT); lcdTicks += 224; - CPUCheckDMA(2, 0x0f); + cpuDmaHack2 = CPUCheckDMA(2, 0x0f); if(DISPSTAT & 16) { IF |= 2; UPDATE_REG(0x202, IF); @@ -4328,6 +4341,9 @@ void CPULoop(int ticks) goto updateLoop; } +// if(cpuDmaHack2) + // cpuNextEvent = 1; + if(IF && (IME & 1) && armIrqEnable) { int res = IF & IE; if(stopState) diff --git a/src/GBA.h b/src/GBA.h index a79603b2..3595500e 100644 --- a/src/GBA.h +++ b/src/GBA.h @@ -116,7 +116,7 @@ extern void CPUWriteByte(u32, u8); extern void CPUInit(const char *,bool); extern void CPUReset(); extern void CPULoop(int); -extern void CPUCheckDMA(int,int); +extern bool CPUCheckDMA(int,int); extern bool CPUIsGBAImage(const char *); extern bool CPUIsZipFile(const char *); #ifdef PROFILING diff --git a/src/GBAinline.h b/src/GBAinline.h index e1ea5f13..b268c6e5 100644 --- a/src/GBAinline.h +++ b/src/GBAinline.h @@ -1,499 +1,498 @@ -// -*- C++ -*- -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2005 Forgotten and the VBA development team - -// 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, 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. - -#ifndef VBA_GBAinline_H -#define VBA_GBAinline_H - -#include "System.h" -#include "Port.h" -#include "RTC.h" - -extern bool cpuSramEnabled; -extern bool cpuFlashEnabled; -extern bool cpuEEPROMEnabled; -extern bool cpuEEPROMSensorEnabled; +// -*- C++ -*- +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2005 Forgotten and the VBA development team + +// 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, 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. + +#ifndef VBA_GBAinline_H +#define VBA_GBAinline_H + +#include "System.h" +#include "Port.h" +#include "RTC.h" +#include "Sound.h" + +extern bool cpuSramEnabled; +extern bool cpuFlashEnabled; +extern bool cpuEEPROMEnabled; +extern bool cpuEEPROMSensorEnabled; extern int lspeed; -extern void LinkSStop(void); -extern bool cpuDmaHack; -extern u32 cpuDmaLast; -extern bool timer0On; -extern int timer0Ticks; -extern int timer0ClockReload; -extern bool timer1On; -extern int timer1Ticks; -extern int timer1ClockReload; -extern bool timer2On; -extern int timer2Ticks; -extern int timer2ClockReload; -extern bool timer3On; -extern int timer3Ticks; -extern int timer3ClockReload; -extern int cpuTotalTicks; - -#define CPUReadByteQuick(addr) \ - map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] - -#define CPUReadHalfWordQuick(addr) \ - READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) - -#define CPUReadMemoryQuick(addr) \ - READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) - -static inline u32 CPUReadMemory(u32 address) -{ - -#ifdef DEV_VERSION - if(address & 3) { - if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } - } -#endif - - u32 value; - switch(address >> 24) { - case 0: - if(reg[15].I >> 24) { - if(address < 0x4000) { -#ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - - value = READ32LE(((u32 *)&biosProtected)); - } - else goto unreadable; - } else - value = READ32LE(((u32 *)&bios[address & 0x3FFC])); - break; - case 2: - value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC])); - break; - case 3: - value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); - break; - case 4: - if((address>=0x4000120||address<=0x4000126)&&lspeed) +extern void LinkSStop(void); +extern bool cpuDmaHack; +extern bool cpuDmaHack2; +extern u32 cpuDmaLast; +extern bool timer0On; +extern int timer0Ticks; +extern int timer0ClockReload; +extern bool timer1On; +extern int timer1Ticks; +extern int timer1ClockReload; +extern bool timer2On; +extern int timer2Ticks; +extern int timer2ClockReload; +extern bool timer3On; +extern int timer3Ticks; +extern int timer3ClockReload; +extern int cpuTotalTicks; + +#define CPUReadByteQuick(addr) \ + map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] + +#define CPUReadHalfWordQuick(addr) \ + READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +#define CPUReadMemoryQuick(addr) \ + READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask])) + +static inline u32 CPUReadMemory(u32 address) +{ + +#ifdef DEV_VERSION + if(address & 3) { + if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { + log("Unaligned word read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } + } +#endif + + u32 value; + switch(address >> 24) { + case 0: + if(reg[15].I >> 24) { + if(address < 0x4000) { +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal word read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } +#endif + + value = READ32LE(((u32 *)&biosProtected)); + } + else goto unreadable; + } else + value = READ32LE(((u32 *)&bios[address & 0x3FFC])); + break; + case 2: + value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC])); + break; + case 3: + value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC])); + break; + case 4: + if((address>=0x4000120||address<=0x4000126)&&lspeed) LinkSStop(); - - if((address < 0x4000400) && ioReadable[address & 0x3fc]) { - if(ioReadable[(address & 0x3fc) + 2]) - value = READ32LE(((u32 *)&ioMem[address & 0x3fC])); - else - value = READ16LE(((u16 *)&ioMem[address & 0x3fc])); - } else goto unreadable; - break; - case 5: - value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); - break; - case 6: - address = (address & 0x1fffc); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - { - value = 0; - break; - } - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - value = READ32LE(((u32 *)&vram[address])); - break; - case 7: - value = READ32LE(((u32 *)&oam[address & 0x3FC])); - break; - case 8: - case 9: - case 10: - case 11: - case 12: - value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); - break; - case 13: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; - case 14: - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); - // default - default: - unreadable: -#ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal word read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - - if(cpuDmaHack) { - value = cpuDmaLast; - } else { - if(armState) { - value = CPUReadMemoryQuick(reg[15].I); - } else { - value = CPUReadHalfWordQuick(reg[15].I) | - CPUReadHalfWordQuick(reg[15].I) << 16; - } - } - } - - if(address & 3) { -#ifdef C_CORE - int shift = (address & 3) << 3; - value = (value >> shift) | (value << (32 - shift)); -#else -#ifdef __GNUC__ - asm("and $3, %%ecx;" - "shl $3 ,%%ecx;" - "ror %%cl, %0" - : "=r" (value) - : "r" (value), "c" (address)); -#else - __asm { - mov ecx, address; - and ecx, 3; - shl ecx, 3; - ror [dword ptr value], cl; - } -#endif -#endif - } - return value; -} - -extern u32 myROM[]; - -static inline u32 CPUReadHalfWord(u32 address) -{ -#ifdef DEV_VERSION - if(address & 1) { - if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } - } -#endif - - u32 value; - - switch(address >> 24) { - case 0: - if (reg[15].I >> 24) { - if(address < 0x4000) { -#ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - value = READ16LE(((u16 *)&biosProtected[address&2])); - } else goto unreadable; - } else - value = READ16LE(((u16 *)&bios[address & 0x3FFE])); - break; - case 2: - value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE])); - break; - case 3: - value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe])); - break; - case 4: - if((address>=0x4000120||address<=0x4000126)&&lspeed) + if((address < 0x4000400) && ioReadable[address & 0x3fc]) { + if(ioReadable[(address & 0x3fc) + 2]) + value = soundRead32(address & 0x3fC); + else + value = soundRead16(address & 0x3fc); + } else goto unreadable; + break; + case 5: + value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC])); + break; + case 6: + address = (address & 0x1fffc); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + { + value = 0; + break; + } + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + value = READ32LE(((u32 *)&vram[address])); + break; + case 7: + value = READ32LE(((u32 *)&oam[address & 0x3FC])); + break; + case 8: + case 9: + case 10: + case 11: + case 12: + value = READ32LE(((u32 *)&rom[address&0x1FFFFFC])); + break; + case 13: + if(cpuEEPROMEnabled) + // no need to swap this + return eepromRead(address); + goto unreadable; + case 14: + if(cpuFlashEnabled | cpuSramEnabled) + // no need to swap this + return flashRead(address); + // default + default: + unreadable: +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal word read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } +#endif + + if(cpuDmaHack || cpuDmaHack2) { + value = cpuDmaLast; + } else { + if(armState) { + value = CPUReadMemoryQuick(reg[15].I); + } else { + value = CPUReadHalfWordQuick(reg[15].I) | + CPUReadHalfWordQuick(reg[15].I) << 16; + } + } + } + + if(address & 3) { +#ifdef C_CORE + int shift = (address & 3) << 3; + value = (value >> shift) | (value << (32 - shift)); +#else +#ifdef __GNUC__ + asm("and $3, %%ecx;" + "shl $3 ,%%ecx;" + "ror %%cl, %0" + : "=r" (value) + : "r" (value), "c" (address)); +#else + __asm { + mov ecx, address; + and ecx, 3; + shl ecx, 3; + ror [dword ptr value], cl; + } +#endif +#endif + } + return value; +} + +extern u32 myROM[]; + +static inline u32 CPUReadHalfWord(u32 address) +{ +#ifdef DEV_VERSION + if(address & 1) { + if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { + log("Unaligned halfword read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } + } +#endif + + u32 value; + + switch(address >> 24) { + case 0: + if (reg[15].I >> 24) { + if(address < 0x4000) { +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal halfword read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } +#endif + value = READ16LE(((u16 *)&biosProtected[address&2])); + } else goto unreadable; + } else + value = READ16LE(((u16 *)&bios[address & 0x3FFE])); + break; + case 2: + value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE])); + break; + case 3: + value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe])); + break; + case 4: +if((address>=0x4000120||address<=0x4000126)&&lspeed) LinkSStop(); - - if((address < 0x4000400) && ioReadable[address & 0x3fe]) - { - value = READ16LE(((u16 *)&ioMem[address & 0x3fe])); - if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E)) - { - if (((address & 0x3fe) == 0x100) && timer0On) - value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload); - else - if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4)) - value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); - else - if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4)) - value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); - else - if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4)) - value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); - } - } - else goto unreadable; - break; - case 5: - value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe])); - break; - case 6: - address = (address & 0x1fffe); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - { - value = 0; - break; - } - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - value = READ16LE(((u16 *)&vram[address])); - break; - case 7: - value = READ16LE(((u16 *)&oam[address & 0x3fe])); - break; - case 8: - case 9: - case 10: - case 11: - case 12: - if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) - value = rtcRead(address); - else - value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); - break; - case 13: - if(cpuEEPROMEnabled) - // no need to swap this - return eepromRead(address); - goto unreadable; - case 14: - if(cpuFlashEnabled | cpuSramEnabled) - // no need to swap this - return flashRead(address); - // default - default: - unreadable: -#ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal halfword read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - if(cpuDmaHack) { - value = cpuDmaLast & 0xFFFF; - } else { - if(armState) { - value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); - } else { - value = CPUReadHalfWordQuick(reg[15].I); - } - } - break; - } - - if(address & 1) { - value = (value >> 8) | (value << 24); - } - - return value; -} - -static inline u16 CPUReadHalfWordSigned(u32 address) -{ - u16 value = CPUReadHalfWord(address); - if((address & 1)) - value = (s8)value; - return value; -} - -static inline u8 CPUReadByte(u32 address) -{ - switch(address >> 24) { - case 0: - if (reg[15].I >> 24) { - if(address < 0x4000) { -#ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - return biosProtected[address & 3]; - } else goto unreadable; - } - return bios[address & 0x3FFF]; - case 2: - return workRAM[address & 0x3FFFF]; - case 3: - return internalRAM[address & 0x7fff]; - case 4: - if((address>=0x4000120||address<=0x4000126)&&lspeed) + if((address < 0x4000400) && ioReadable[address & 0x3fe]) + { + value = soundRead16(address & 0x3fe); + if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E)) + { + if (((address & 0x3fe) == 0x100) && timer0On) + value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload); + else + if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4)) + value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload); + else + if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4)) + value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload); + else + if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4)) + value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload); + } + } + else goto unreadable; + break; + case 5: + value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe])); + break; + case 6: + address = (address & 0x1fffe); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + { + value = 0; + break; + } + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + value = READ16LE(((u16 *)&vram[address])); + break; + case 7: + value = READ16LE(((u16 *)&oam[address & 0x3fe])); + break; + case 8: + case 9: + case 10: + case 11: + case 12: + if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) + value = rtcRead(address); + else + value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE])); + break; + case 13: + if(cpuEEPROMEnabled) + // no need to swap this + return eepromRead(address); + goto unreadable; + case 14: + if(cpuFlashEnabled | cpuSramEnabled) + // no need to swap this + return flashRead(address); + // default + default: + unreadable: +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal halfword read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } +#endif + if(cpuDmaHack2 || cpuDmaHack) { + value = cpuDmaLast & 0xFFFF; + } else { + if(armState) { + value = CPUReadHalfWordQuick(reg[15].I + (address & 2)); + } else { + value = CPUReadHalfWordQuick(reg[15].I); + } + } + break; + } + + if(address & 1) { + value = (value >> 8) | (value << 24); + } + + return value; +} + +static inline u16 CPUReadHalfWordSigned(u32 address) +{ + u16 value = CPUReadHalfWord(address); + if((address & 1)) + value = (s8)value; + return value; +} + +static inline u8 CPUReadByte(u32 address) +{ + switch(address >> 24) { + case 0: + if (reg[15].I >> 24) { + if(address < 0x4000) { +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal byte read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } +#endif + return biosProtected[address & 3]; + } else goto unreadable; + } + return bios[address & 0x3FFF]; + case 2: + return workRAM[address & 0x3FFFF]; + case 3: + return internalRAM[address & 0x7fff]; + case 4: + if((address>=0x4000120||address<=0x4000126)&&lspeed) LinkSStop(); - - if((address < 0x4000400) && ioReadable[address & 0x3ff]) - return ioMem[address & 0x3ff]; - else goto unreadable; - case 5: - return paletteRAM[address & 0x3ff]; - case 6: - address = (address & 0x1ffff); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return 0; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - return vram[address]; - case 7: - return oam[address & 0x3ff]; - case 8: - case 9: - case 10: - case 11: - case 12: - return rom[address & 0x1FFFFFF]; - case 13: - if(cpuEEPROMEnabled) - return eepromRead(address); - goto unreadable; - case 14: - if(cpuSramEnabled | cpuFlashEnabled) - return flashRead(address); - if(cpuEEPROMSensorEnabled) { - switch(address & 0x00008f00) { - case 0x8200: - return systemGetSensorX() & 255; - case 0x8300: - return (systemGetSensorX() >> 8)|0x80; - case 0x8400: - return systemGetSensorY() & 255; - case 0x8500: - return systemGetSensorY() >> 8; - } - } - // default - default: - unreadable: -#ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_READ) { - log("Illegal byte read: %08x at %08x\n", address, armMode ? - armNextPC - 4 : armNextPC - 2); - } -#endif - if(cpuDmaHack) { - return cpuDmaLast & 0xFF; - } else { - if(armState) { - return CPUReadByteQuick(reg[15].I+(address & 3)); - } else { - return CPUReadByteQuick(reg[15].I+(address & 1)); - } - } - break; - } -} - -static inline void CPUWriteMemory(u32 address, u32 value) -{ - -#ifdef DEV_VERSION - if(address & 3) { - if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { - log("Unaligned word write: %08x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); - } - } -#endif - - switch(address >> 24) { - case 0x02: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC])) - cheatsWriteMemory(address & 0x203FFFC, - value); - else -#endif - WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); - break; - case 0x03: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeInternalRAM[address & 0x7ffc])) - cheatsWriteMemory(address & 0x3007FFC, - value); - else -#endif - WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); - break; - case 0x04: - if(address < 0x4000400) { - CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); - CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); - } else goto unwritable; - break; - case 0x05: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezePRAM[address & 0x3fc])) - cheatsWriteMemory(address & 0x70003FC, - value); - else -#endif - WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); - break; - case 0x06: - address = (address & 0x1fffc); - if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) - return; - if ((address & 0x18000) == 0x18000) - address &= 0x17fff; - -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeVRAM[address])) - cheatsWriteMemory(address + 0x06000000, value); - else -#endif - - WRITE32LE(((u32 *)&vram[address]), value); - break; - case 0x07: -#ifdef BKPT_SUPPORT - if(*((u32 *)&freezeOAM[address & 0x3fc])) - cheatsWriteMemory(address & 0x70003FC, - value); - else -#endif - WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); - break; - case 0x0D: - if(cpuEEPROMEnabled) { - eepromWrite(address, value); - break; - } - goto unwritable; - case 0x0E: - if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) { - (*cpuSaveGameFunc)(address, (u8)value); - break; - } - // default - default: - unwritable: -#ifdef DEV_VERSION - if(systemVerbose & VERBOSE_ILLEGAL_WRITE) { - log("Illegal word write: %08x to %08x from %08x\n", - value, - address, - armMode ? armNextPC - 4 : armNextPC - 2); - } -#endif - break; - } -} - -#endif //VBA_GBAinline_H + if((address < 0x4000400) && ioReadable[address & 0x3ff]) + return soundRead(address & 0x3ff); + else goto unreadable; + case 5: + return paletteRAM[address & 0x3ff]; + case 6: + address = (address & 0x1ffff); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return 0; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + return vram[address]; + case 7: + return oam[address & 0x3ff]; + case 8: + case 9: + case 10: + case 11: + case 12: + return rom[address & 0x1FFFFFF]; + case 13: + if(cpuEEPROMEnabled) + return eepromRead(address); + goto unreadable; + case 14: + if(cpuSramEnabled | cpuFlashEnabled) + return flashRead(address); + if(cpuEEPROMSensorEnabled) { + switch(address & 0x00008f00) { + case 0x8200: + return systemGetSensorX() & 255; + case 0x8300: + return (systemGetSensorX() >> 8)|0x80; + case 0x8400: + return systemGetSensorY() & 255; + case 0x8500: + return systemGetSensorY() >> 8; + } + } + // default + default: + unreadable: +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_ILLEGAL_READ) { + log("Illegal byte read: %08x at %08x\n", address, armMode ? + armNextPC - 4 : armNextPC - 2); + } +#endif + if(cpuDmaHack || cpuDmaHack2) { + return cpuDmaLast & 0xFF; + } else { + if(armState) { + return CPUReadByteQuick(reg[15].I+(address & 3)); + } else { + return CPUReadByteQuick(reg[15].I+(address & 1)); + } + } + break; + } +} + +static inline void CPUWriteMemory(u32 address, u32 value) +{ + +#ifdef DEV_VERSION + if(address & 3) { + if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) { + log("Unaligned word write: %08x to %08x from %08x\n", + value, + address, + armMode ? armNextPC - 4 : armNextPC - 2); + } + } +#endif + + switch(address >> 24) { + case 0x02: +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC])) + cheatsWriteMemory(address & 0x203FFFC, + value); + else +#endif + WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value); + break; + case 0x03: +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezeInternalRAM[address & 0x7ffc])) + cheatsWriteMemory(address & 0x3007FFC, + value); + else +#endif + WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value); + break; + case 0x04: + if(address < 0x4000400) { + CPUUpdateRegister((address & 0x3FC), value & 0xFFFF); + CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16)); + } else goto unwritable; + break; + case 0x05: +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezePRAM[address & 0x3fc])) + cheatsWriteMemory(address & 0x70003FC, + value); + else +#endif + WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value); + break; + case 0x06: + address = (address & 0x1fffc); + if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000)) + return; + if ((address & 0x18000) == 0x18000) + address &= 0x17fff; + +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezeVRAM[address])) + cheatsWriteMemory(address + 0x06000000, value); + else +#endif + + WRITE32LE(((u32 *)&vram[address]), value); + break; + case 0x07: +#ifdef BKPT_SUPPORT + if(*((u32 *)&freezeOAM[address & 0x3fc])) + cheatsWriteMemory(address & 0x70003FC, + value); + else +#endif + WRITE32LE(((u32 *)&oam[address & 0x3fc]), value); + break; + case 0x0D: + if(cpuEEPROMEnabled) { + eepromWrite(address, value); + break; + } + goto unwritable; + case 0x0E: + if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) { + (*cpuSaveGameFunc)(address, (u8)value); + break; + } + // default + default: + unwritable: +#ifdef DEV_VERSION + if(systemVerbose & VERBOSE_ILLEGAL_WRITE) { + log("Illegal word write: %08x to %08x from %08x\n", + value, + address, + armMode ? armNextPC - 4 : armNextPC - 2); + } +#endif + break; + } +} + +#endif //VBA_GBAinline_H diff --git a/src/Gb_Apu/Blip_Buffer.cpp b/src/Gb_Apu/Blip_Buffer.cpp index 81da8362..4e106ed8 100644 --- a/src/Gb_Apu/Blip_Buffer.cpp +++ b/src/Gb_Apu/Blip_Buffer.cpp @@ -320,7 +320,7 @@ void Blip_Synth_::volume_unit( double new_unit ) factor *= 2.0; } - if ( shift ) + // if ( shift ) { kernel_unit >>= shift; assert( kernel_unit > 0 ); // fails if volume unit is too low diff --git a/src/Gb_Apu/Gb_Apu.cpp b/src/Gb_Apu/Gb_Apu.cpp index 0dfd32ce..c7513299 100644 --- a/src/Gb_Apu/Gb_Apu.cpp +++ b/src/Gb_Apu/Gb_Apu.cpp @@ -107,7 +107,7 @@ void Gb_Apu::reset(bool igba) square1.reset(); square2.reset(); wave.reset(gba = igba); - noise.reset(); + noise.reset(igba); noise.bits = 1; wave.wave_pos = 0; diff --git a/src/Gb_Apu/Gb_Oscs.cpp b/src/Gb_Apu/Gb_Oscs.cpp index 674c039a..4bf97407 100644 --- a/src/Gb_Apu/Gb_Oscs.cpp +++ b/src/Gb_Apu/Gb_Oscs.cpp @@ -172,6 +172,7 @@ void Gb_Square::run( gb_time_t time, gb_time_t end_time, int playing ) void Gb_Noise::run( gb_time_t time, gb_time_t end_time, int playing ) { int amp = volume & playing; + int tap = 13 - (regs [3] & 8); if ( bits >> tap & 2 ) amp = -amp; @@ -197,7 +198,7 @@ void Gb_Noise::run( gb_time_t time, gb_time_t end_time, int playing ) const blip_resampled_time_t resampled_period = output->resampled_duration( period ); blip_resampled_time_t resampled_time = output->resampled_time( time ); - unsigned bits = this->bits; +// unsigned bits = this->bits; int delta = amp * 2; do @@ -215,7 +216,7 @@ void Gb_Noise::run( gb_time_t time, gb_time_t end_time, int playing ) } while ( time < end_time ); - this->bits = bits; + //this->bits = bits; last_amp = delta >> 1; } delay = time - end_time; @@ -227,7 +228,7 @@ void Gb_Wave::reset(bool gba) { volume_forced = 0; wave_pos = 0; - wave_mode = gba; + wave_mode = (gba ? 1 : 0); wave_size = 32; wave_bank = 0; memset( wave, 0, sizeof wave ); @@ -270,6 +271,33 @@ inline void Gb_Wave::write_register( int reg, int data ) } } +bool Gb_Noise::write_register( int reg, int data ) +{ + switch ( reg ) + { + case 1: + length = 64 - (regs [1] & 0x3f); + break; + + case 2: + if ( !(data >> 4) ) + enabled = false; + break; + + case 4: + if ( data & trigger ) + { + env_delay = regs [2] & 7; + volume = regs [2] >> (4 + (gba ? 1 : 0)); + enabled = true; + if ( length == 0 ) + length = 64; + return true; + } + } + return false; +} + void Gb_Wave::run( gb_time_t time, gb_time_t end_time, int playing ) { int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7 diff --git a/src/Gb_Apu/Gb_Oscs.h b/src/Gb_Apu/Gb_Oscs.h index 40aa0d1a..00b66d11 100644 --- a/src/Gb_Apu/Gb_Oscs.h +++ b/src/Gb_Apu/Gb_Oscs.h @@ -57,10 +57,17 @@ struct Gb_Square : Gb_Env struct Gb_Noise : Gb_Env { + bool gba; typedef Blip_Synth Synth; Synth const* synth; unsigned bits; + bool write_register( int, int ); + void reset(bool igba) + { + gba = igba; + Gb_Env::reset(); + } void run( gb_time_t, gb_time_t, int playing ); }; diff --git a/src/Link.cpp b/src/Link.cpp index d20ebbd5..f209335d 100644 --- a/src/Link.cpp +++ b/src/Link.cpp @@ -53,7 +53,7 @@ int lspeed = 0; lserver ls; lclient lc; bool oncewait = false, after = false; -bool adapter = true; +bool adapter = false; u8 rfu_cmd, rfu_qsend, rfu_qrecv; int rfu_state, rfu_polarity, linktime2, counter, rfu_masterq; int transferend, numtransfers = 0; diff --git a/src/Sound.cpp b/src/Sound.cpp index a7ab5f0d..498ff286 100644 --- a/src/Sound.cpp +++ b/src/Sound.cpp @@ -670,7 +670,7 @@ void soundDirectSoundATimer() { if(soundDSAEnabled) { if(soundDSFifoACount <= 16) { - CPUCheckDMA(3, 2); + cpuDmaHack2 = CPUCheckDMA(3, 2); if(soundDSFifoACount <= 16) { soundEvent(FIFOA_L, (u16)0); soundEvent(FIFOA_H, (u16)0); @@ -699,8 +699,7 @@ void soundDirectSoundBTimer() { if(soundDSBEnabled) { if(soundDSFifoBCount <= 16) { - //cpuDmaHack2 = - CPUCheckDMA(3, 4); + cpuDmaHack2 = CPUCheckDMA(3, 4); if(soundDSFifoBCount <= 16) { soundEvent(FIFOB_L, (u16)0); soundEvent(FIFOB_H, (u16)0); diff --git a/src/gb/GB.cpp b/src/gb/GB.cpp index 4536c2db..b81d332a 100644 --- a/src/gb/GB.cpp +++ b/src/gb/GB.cpp @@ -998,7 +998,7 @@ void gbWriteMemory(register u16 address, register u8 value) case 0x3d: case 0x3e: case 0x3f: { - gbMemory[address] = value; + SOUND_EVENT(address,value); return; } @@ -1783,6 +1783,11 @@ u8 gbReadMemory(register u16 address) } if(address >= 0xff00) { + + if (address >= 0xFF10 && address <= 0xFF3F) { + return gbSoundRead(address); + } + switch(address & 0x00ff) { case 0x00: { @@ -3527,6 +3532,8 @@ static bool gbWriteSaveState(gzFile gzFile) utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01)); utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16)); + + for (int i = 0xFF10; i <= 0xFF3F; i++) gbMemory[i] = gbReadMemory(i); utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000); @@ -3718,6 +3725,8 @@ static bool gbReadSaveState(gzFile gzFile) utilGzRead(gzFile, &gbMemory[0x8000], 0x8000); + for (int i = 0xFF10; i <= 0xFF3F; i++) gbSoundEvent(i, gbMemory[i]); + if(gbRamSize && gbRam) { if (version < 11) utilGzRead(gzFile, gbRam, gbRamSize); diff --git a/src/gb/gbSound.cpp b/src/gb/gbSound.cpp index 0a0685b4..6e981fc6 100644 --- a/src/gb/gbSound.cpp +++ b/src/gb/gbSound.cpp @@ -23,6 +23,9 @@ #include "gbGlobals.h" #include "gbSound.h" +#include "../Gb_Apu/Multi_Buffer.h" +#include "../Gb_Apu/Gb_Apu.h" + extern u8 soundBuffer[6][735]; extern u16 soundFinalWave[1470]; extern int soundVolume; @@ -56,6 +59,9 @@ extern int soundBufferIndex; int soundVIN = 0; extern int soundDebug; +extern Multi_Buffer * apu_out; +extern Gb_Apu * apu; + extern int sound1On; extern int sound1ATL; int sound1ATLreload; @@ -132,7 +138,45 @@ extern bool soundLowPass; extern bool soundReverse; extern bool soundOffFlag; -bool gbDigitalSound = false; +u8 gbSoundRead(u16 address) +{ + if (address < NR10 || address > 0xFF3F || !apu) return gbMemory[address]; + if (address == NR51) return soundBalance; + + int clock = (SOUND_CLOCK_TICKS - soundTicks) * 95 / (24 * (gbSpeed ? 2 : 1)); + + int ret = apu->read_register(clock, address); + + switch ( address ) + { + case NR10: + ret |= 0x80; break; + + case NR11: + case NR21: + ret |= 0x3F; break; + + case NR13: + case NR23: + case NR31: + case NR33: + ret = 0xFF; break; + + case NR14: + case NR24: + case NR34: + case NR44: + ret |= 0xBF; break; + + case NR30: + ret |= 0x7F; break; + + case NR32: + ret |= 0x9F; break; + } + + return ret; +} void gbSoundEvent(register u16 address, register int data) { @@ -146,481 +190,58 @@ void gbSoundEvent(register u16 address, register int data) log("Sound event: %08lx %02x\n", address, data); } #endif - switch(address) { - case NR10: - gbMemory[address] = data | 0x80; - sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7); - sound1SweepSteps = data & 7; - sound1SweepUpDown = data & 0x08; - sound1SweepStep = 0; - break; - case NR11: - gbMemory[address] = data | 0x3f; - sound1Wave = soundWavePattern[data >> 6]; - sound1ATL = sound1ATLreload = 172 * (64 - (data & 0x3f)); - break; - case NR12: - sound1EnvelopeVolume = data >> 4; - sound1EnvelopeUpDown = data & 0x08; - sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (data & 7); - break; - case NR13: - gbMemory[address] = 0xff; - freq1low = data; - freq = ((((int)(freq1high & 7)) << 8) | freq1low); - sound1ATL = sound1ATLreload; - freq = 2048 - freq; - if(freq) { - sound1Skip = SOUND_MAGIC / freq; - } else - sound1Skip = 0; - break; - case NR14: - gbMemory[address] = data | 0xbf; - freq1high = data; - freq = ((((int)(freq1high & 7)) << 8) | freq1low); - freq = 2048 - freq; - sound1ATL = sound1ATLreload; - sound1Continue = data & 0x40; - if(freq) { - sound1Skip = SOUND_MAGIC / freq; - } else - sound1Skip = 0; - if(data & 0x80) { - gbMemory[NR52] |= 1; - sound1EnvelopeVolume = gbMemory[NR12] >> 4; - sound1EnvelopeUpDown = gbMemory[NR12] & 0x08; - sound1EnvelopeATLReload = sound1EnvelopeATL = 689 * (gbMemory[NR12] & 7); - sound1SweepATL = sound1SweepATLReload = 344 * ((gbMemory[NR10] >> 4) & 7); - sound1SweepSteps = gbMemory[NR10] & 7; - sound1SweepUpDown = gbMemory[NR10] & 0x08; - sound1SweepStep = 0; - - sound1Index = 0; - sound1On = 1; + if (apu && address >= NR10 && address <= 0xFF3F) + { + int clock = (SOUND_CLOCK_TICKS - soundTicks) * 95 / (24 * (gbSpeed ? 2 : 1)); + if (address == NR50) + { + apu->write_register(clock, address, data); } - break; - case NR21: - gbMemory[address] = data | 0x3f; - sound2Wave = soundWavePattern[data >> 6]; - sound2ATL = sound2ATLreload = 172 * (64 - (data & 0x3f)); - break; - case NR22: - sound2EnvelopeVolume = data >> 4; - sound2EnvelopeUpDown = data & 0x08; - sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (data & 7); - break; - case NR23: - gbMemory[address] = 0xff; - freq2low = data; - freq = (((int)(freq2high & 7)) << 8) | freq2low; - sound2ATL = sound2ATLreload; - freq = 2048 - freq; - if(freq) { - sound2Skip = SOUND_MAGIC / freq; - } else - sound2Skip = 0; - break; - case NR24: - gbMemory[address] = data | 0xbf; - freq2high = data; - freq = (((int)(freq2high & 7)) << 8) | freq2low; - freq = 2048 - freq; - sound2ATL = sound2ATLreload; - sound2Continue = data & 0x40; - if(freq) { - sound2Skip = SOUND_MAGIC / freq; - } else - sound2Skip = 0; - if(data & 0x80) { - gbMemory[NR52] |= 2; - sound2EnvelopeVolume = gbMemory[NR22] >> 4; - sound2EnvelopeUpDown = gbMemory[NR22] & 0x08; - sound2ATL = sound2ATLreload; - sound2EnvelopeATLReload = sound2EnvelopeATL = 689 * (gbMemory[NR22] & 7); - - sound2Index = 0; - sound2On = 1; + else if (address == NR51) + { + soundBalance = data; + apu->write_register(clock, address, data & soundEnableFlag); } - break; - case NR30: - gbMemory[address] = data | 0x7f; - if(!(data & 0x80)) { - gbMemory[NR52] &= 0xfb; - sound3On = 0; - } - break; - case NR31: - gbMemory[address] = 0xff; - sound3ATL = sound3ATLreload = 172 * (256-data); - break; - case NR32: - gbMemory[address] = data | 0x9f; - sound3OutputLevel = (data >> 5) & 3; - break; - case NR33: - gbMemory[address] = 0xff; - freq3low = data; - freq = 2048 - (((int)(freq3high&7) << 8) | freq3low); - if(freq) { - sound3Skip = SOUND_MAGIC_2 / freq; - } else - sound3Skip = 0; - break; - case NR34: - gbMemory[address] = data | 0xbf; - freq3high = data; - freq = 2048 - (((int)(freq3high&7) << 8) | freq3low); - if(freq) { - sound3Skip = SOUND_MAGIC_2 / freq; - } else { - sound3Skip = 0; - } - sound3Continue = data & 0x40; - if((data & 0x80) && (gbMemory[NR30] & 0x80)) { - gbMemory[NR52] |= 4; - sound3ATL = sound3ATLreload; - sound3Index = 0; - sound3On = 1; - } - break; - case NR41: - sound4ATL = sound4ATLreload = 172 * (64 - (data & 0x3f)); - break; - case NR42: - sound4EnvelopeVolume = data >> 4; - sound4EnvelopeUpDown = data & 0x08; - sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (data & 7); - break; - case NR43: - freq = freq4 = soundFreqRatio[data & 7]; - sound4NSteps = data & 0x08; - - sound4Skip = (freq << 8) / NOISE_MAGIC; - - sound4Clock = data >> 4; - - freq = freq / soundShiftClock[sound4Clock]; - - sound4ShiftSkip = (freq << 8) / NOISE_MAGIC; - - break; - case NR44: - gbMemory[address] = data | 0xbf; - sound4Continue = data & 0x40; - if(data & 0x80) { - gbMemory[NR52] |= 8; - sound4EnvelopeVolume = gbMemory[NR42] >> 4; - sound4EnvelopeUpDown = gbMemory[NR42] & 0x08; - sound4ATL = sound4ATLreload; - sound4EnvelopeATLReload = sound4EnvelopeATL = 689 * (gbMemory[NR42] & 7); - - sound4On = 1; - - sound4Index = 0; - sound4ShiftIndex = 0; - - if(sound4NSteps) - sound4ShiftRight = 0x7fff; - else - sound4ShiftRight = 0x7f; - } - break; - case NR50: - soundVIN = data & 0x88; - soundLevel1 = data & 7; - soundLevel2 = (data >> 4) & 7; - break; - case NR51: - soundBalance = (data & soundEnableFlag); - break; - case NR52: - soundMasterOn = data & 0x80; - if(!(data & 0x80)) { - sound1On = 0; - sound2On = 0; - sound3On = 0; - sound4On = 0; - gbMemory[address] &= 0xf0; - } - gbMemory[address] = data & 0x80 | 0x70 | (gbMemory[address] & 0xf); - break; + else + apu->write_register(clock, address, data); } - - gbDigitalSound = true; - - if(sound1On && sound1EnvelopeVolume != 0) - gbDigitalSound = false; - if(sound2On && sound2EnvelopeVolume != 0) - gbDigitalSound = false; - if(sound3On && sound3OutputLevel != 0) - gbDigitalSound = false; - if(sound4On && sound4EnvelopeVolume != 0) - gbDigitalSound = false; } void gbSoundChannel1() { - int vol = sound1EnvelopeVolume; - - int freq = 0; - - int value = 0; - - if(sound1On && (sound1ATL || !sound1Continue)) { - sound1Index += soundQuality*sound1Skip; - sound1Index &= 0x1fffffff; - - value = ((s8)sound1Wave[sound1Index>>24]) * vol; - } - - soundBuffer[0][soundIndex] = value; - - - if(sound1On) { - if(sound1ATL) { - sound1ATL-=soundQuality; - - if(sound1ATL <=0 && sound1Continue) { - gbMemory[NR52] &= 0xfe; - sound1On = 0; - } - } - - if(sound1EnvelopeATL) { - sound1EnvelopeATL-=soundQuality; - - if(sound1EnvelopeATL<=0) { - if(sound1EnvelopeUpDown) { - if(sound1EnvelopeVolume < 15) - sound1EnvelopeVolume++; - } else { - if(sound1EnvelopeVolume) - sound1EnvelopeVolume--; - } - - sound1EnvelopeATL += sound1EnvelopeATLReload; - } - } - - if(sound1SweepATL) { - sound1SweepATL-=soundQuality; - - if(sound1SweepATL<=0) { - freq = (((int)(freq1high & 7)) << 8) | freq1low; - - int updown = 1; - - if(sound1SweepUpDown) - updown = -1; - - int newfreq = 0; - if(sound1SweepSteps) { - newfreq = freq + updown * freq / (1 << sound1SweepSteps); - if(newfreq == freq) - newfreq = 0; - } else - newfreq = freq; - - if(newfreq < 0) { - sound1SweepATL += sound1SweepATLReload; - } else if(newfreq > 2047) { - sound1SweepATL = 0; - sound1On = 0; - gbMemory[NR52] &= 0xfe; - } else { - sound1SweepATL += sound1SweepATLReload; - sound1Skip = SOUND_MAGIC/(2048 - newfreq); - - freq1low = newfreq & 0xff; - freq1high = (freq1high & 0xf8) |((newfreq >> 8) & 7); - } - } - } - } } void gbSoundChannel2() { - // int freq = 0; - int vol = sound2EnvelopeVolume; - - int value = 0; - - if(sound2On && (sound2ATL || !sound2Continue)) { - sound2Index += soundQuality*sound2Skip; - sound2Index &= 0x1fffffff; - - value = ((s8)sound2Wave[sound2Index>>24]) * vol; - } - - soundBuffer[1][soundIndex] = value; - - if(sound2On) { - if(sound2ATL) { - sound2ATL-=soundQuality; - - if(sound2ATL <= 0 && sound2Continue) { - gbMemory[NR52] &= 0xfd; - sound2On = 0; - } - } - - if(sound2EnvelopeATL) { - sound2EnvelopeATL-=soundQuality; - - if(sound2EnvelopeATL <= 0) { - if(sound2EnvelopeUpDown) { - if(sound2EnvelopeVolume < 15) - sound2EnvelopeVolume++; - } else { - if(sound2EnvelopeVolume) - sound2EnvelopeVolume--; - } - sound2EnvelopeATL += sound2EnvelopeATLReload; - } - } - } } void gbSoundChannel3() { - int value = 0; - - if(sound3On && (sound3ATL || !sound3Continue)) { - - value = sound3Last; - - sound3Index += soundQuality*sound3Skip; - sound3Index &= 0x1fffffff; - - value = gbMemory[0xff30 + (sound3Index>>25)]; - - if( (sound3Index & 0x01000000)) { - value &= 0x0f; - } else { - value >>= 4; - } - - value -= 8; - - switch(sound3OutputLevel) { - case 0: - value = 0; - break; - case 1: - break; - case 2: - value = (value >> 1); - break; - case 3: - value = (value >> 2); - break; - } - sound3Last = value; - } - - soundBuffer[2][soundIndex] = value; - - if(sound3On) { - if(sound3ATL) { - sound3ATL-=soundQuality; - - if(sound3ATL <= 0 && sound3Continue) { - gbMemory[NR52] &= 0xfb; - sound3On = 0; - } - } - } } void gbSoundChannel4() { - int vol = sound4EnvelopeVolume; - - int value = 0; - - if(sound4Clock <= 0x0c) { - if(sound4On && (sound4ATL || !sound4Continue)) { - sound4Index += soundQuality*sound4Skip; - sound4ShiftIndex += soundQuality*sound4ShiftSkip; - - if(sound4NSteps) { - while(sound4ShiftIndex > 0x1fffff) { - sound4ShiftRight = (((sound4ShiftRight << 6) ^ - (sound4ShiftRight << 5)) & 0x40) | - (sound4ShiftRight >> 1); - sound4ShiftIndex -= 0x200000; - } - } else { - while(sound4ShiftIndex > 0x1fffff) { - sound4ShiftRight = (((sound4ShiftRight << 14) ^ - (sound4ShiftRight << 13)) & 0x4000) | - (sound4ShiftRight >> 1); - - sound4ShiftIndex -= 0x200000; - } - } - - sound4Index &= 0x1fffff; - sound4ShiftIndex &= 0x1fffff; - - value = ((sound4ShiftRight & 1)*2-1) * vol; - } else { - value = 0; - } - } - - soundBuffer[3][soundIndex] = value; - - if(sound4On) { - if(sound4ATL) { - sound4ATL-=soundQuality; - - if(sound4ATL <= 0 && sound4Continue) { - gbMemory[NR52] &= 0xf7; - sound4On = 0; - } - } - - if(sound4EnvelopeATL) { - sound4EnvelopeATL-=soundQuality; - - if(sound4EnvelopeATL <= 0) { - if(sound4EnvelopeUpDown) { - if(sound4EnvelopeVolume < 15) - sound4EnvelopeVolume++; - } else { - if(sound4EnvelopeVolume) - sound4EnvelopeVolume--; - } - sound4EnvelopeATL += sound4EnvelopeATLReload; - } - } - } } void gbSoundMix() { int res = 0; - if(soundBalance & 16) { - res += ((s8)soundBuffer[0][soundIndex]); - } - if(soundBalance & 32) { - res += ((s8)soundBuffer[1][soundIndex]); - } - if(soundBalance & 64) { - res += ((s8)soundBuffer[2][soundIndex]); - } - if(soundBalance & 128) { - res += ((s8)soundBuffer[3][soundIndex]); + + blip_sample_t out[2] = {0, 0}; + + if ( ! apu_out ) return; + + while (!apu_out->read_samples(&out[0], 2)) + { + int ticks = SOUND_CLOCK_TICKS * 95 / (24 * (gbSpeed ? 2 : 1)); + bool was_stereo = apu->end_frame( ticks ); + apu_out->end_frame( ticks, was_stereo ); } - if(gbDigitalSound) - res *= soundLevel1*256; - else - res *= soundLevel1*60; + res = out[0]; + + //res = (res * 7 * 60) >> 8; if(soundEcho) { res *= 2; @@ -664,25 +285,7 @@ void gbSoundMix() else soundFinalWave[soundBufferIndex++] = res; - res = 0; - - if(soundBalance & 1) { - res += ((s8)soundBuffer[0][soundIndex]); - } - if(soundBalance & 2) { - res += ((s8)soundBuffer[1][soundIndex]); - } - if(soundBalance & 4) { - res += ((s8)soundBuffer[2][soundIndex]); - } - if(soundBalance & 8) { - res += ((s8)soundBuffer[3][soundIndex]); - } - - if(gbDigitalSound) - res *= soundLevel2*256; - else - res *= soundLevel2*60; + res = out[1]; if(soundEcho) { res *= 2; @@ -734,10 +337,10 @@ void gbSoundTick() { if(systemSoundOn) { if(soundMasterOn) { - gbSoundChannel1(); + /*gbSoundChannel1(); gbSoundChannel2(); gbSoundChannel3(); - gbSoundChannel4(); + gbSoundChannel4();*/ gbSoundMix(); } else { @@ -775,7 +378,7 @@ void gbSoundReset() soundLevel2 = 7; soundVIN = 0; - sound1On = 0; + /*sound1On = 0; sound1ATL = 0; sound1Skip = 0; sound1Index = 0; @@ -821,53 +424,48 @@ void gbSoundReset() sound4EnvelopeVolume = 0; sound4EnvelopeATL = 0; sound4EnvelopeUpDown = 0; - sound4EnvelopeATLReload = 0; + sound4EnvelopeATLReload = 0;*/ // don't translate if(soundDebug) { log("*** Sound Init ***\n"); } - - gbSoundEvent(0xff10, 0x80); - gbSoundEvent(0xff11, 0xbf); - gbSoundEvent(0xff12, 0xf3); - gbSoundEvent(0xff14, 0xbf); - gbSoundEvent(0xff16, 0x3f); - gbSoundEvent(0xff17, 0x00); - gbSoundEvent(0xff19, 0xbf); - gbSoundEvent(0xff1a, 0x7f); - gbSoundEvent(0xff1b, 0xff); - gbSoundEvent(0xff1c, 0xbf); - gbSoundEvent(0xff1e, 0xbf); + if (apu_out) + { + apu_out->clear(); + apu->reset(false); - gbSoundEvent(0xff20, 0xff); - gbSoundEvent(0xff21, 0x00); - gbSoundEvent(0xff22, 0x00); - gbSoundEvent(0xff23, 0xbf); - gbSoundEvent(0xff24, 0x77); - gbSoundEvent(0xff25, 0xf3); + extern const BOOST::uint8_t sound_data[Gb_Apu::end_addr - Gb_Apu::start_addr + 1]; - if (gbHardware & 0x4) - gbSoundEvent(0xff26, 0xf0); - else - gbSoundEvent(0xff26, 0xf1); + int addr = 0; + + while (addr < 0x30) { + apu->write_register( 0, 0xFF10 + addr, sound_data [ addr ] ); + addr++; + } + } // don't translate if(soundDebug) { log("*** Sound Init Complete ***\n"); } - sound1On = 0; + /*sound1On = 0; sound2On = 0; sound3On = 0; - sound4On = 0; + sound4On = 0;*/ - int addr = 0xff30; + if (apu) + { + int addr = 0xff30; - while(addr < 0xff40) { - gbMemory[addr++] = 0x00; - gbMemory[addr++] = 0xff; + while(addr < 0xff40) { + /*gbMemory[addr++] = 0x00; + gbMemory[addr++] = 0xff;*/ + gbSoundEvent(addr++, 0x00); + gbSoundEvent(addr++, 0xFF); + } } memset(soundFinalWave, 0x00, soundBufferLen); diff --git a/src/gb/gbSound.h b/src/gb/gbSound.h index 50658b24..27dd0a5b 100644 --- a/src/gb/gbSound.h +++ b/src/gb/gbSound.h @@ -22,6 +22,7 @@ #define NR12 0xff12 #define NR13 0xff13 #define NR14 0xff14 +#define NR20 0xff15 #define NR21 0xff16 #define NR22 0xff17 #define NR23 0xff18 @@ -31,6 +32,7 @@ #define NR32 0xff1c #define NR33 0xff1d #define NR34 0xff1e +#define NR40 0xff1f #define NR41 0xff20 #define NR42 0xff21 #define NR43 0xff22 @@ -54,6 +56,8 @@ extern void gbSoundReadGame(int,gzFile); extern void gbSoundEvent(register u16, register int); extern void gbSoundSetQuality(int); +extern u8 gbSoundRead(u16 address); + extern int soundTicks; extern int soundQuality; extern int SOUND_CLOCK_TICKS; diff --git a/src/win32/OpenGL.cpp b/src/win32/OpenGL.cpp index adc588b2..70058095 100644 --- a/src/win32/OpenGL.cpp +++ b/src/win32/OpenGL.cpp @@ -32,7 +32,10 @@ // OpenGL #include // main include file +#ifdef HAS_GLEXT #include +#endif + typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int ); extern int Init_2xSaI(u32);