GB use blargg's audio core correctly
Noise channel seems to be buggy in GBA mode (probably using uninitialized data somewhere). Suddenly became very LOUD. Changed volume setting for now. OpenGL is looking for glext which is not part of a standard windows build. Probably should incldue it in dependencies if we are going to use it
This commit is contained in:
parent
17e8800d18
commit
6b947e0353
22
src/GBA.cpp
22
src/GBA.cpp
|
@ -90,6 +90,7 @@ u32 busPrefetchCount = 0;
|
||||||
int cpuDmaTicksToUpdate = 0;
|
int cpuDmaTicksToUpdate = 0;
|
||||||
int cpuDmaCount = 0;
|
int cpuDmaCount = 0;
|
||||||
bool cpuDmaHack = false;
|
bool cpuDmaHack = false;
|
||||||
|
bool cpuDmaHack2 = false;
|
||||||
u32 cpuDmaLast = 0;
|
u32 cpuDmaLast = 0;
|
||||||
int dummyAddress = 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
|
// DMA 0
|
||||||
if((DM0CNT_H & 0x8000) && (dmamask & 1)) {
|
if((DM0CNT_H & 0x8000) && (dmamask & 1)) {
|
||||||
if(((DM0CNT_H >> 12) & 3) == reason) {
|
if(((DM0CNT_H >> 12) & 3) == reason) {
|
||||||
|
res = true;
|
||||||
u32 sourceIncrement = 4;
|
u32 sourceIncrement = 4;
|
||||||
u32 destIncrement = 4;
|
u32 destIncrement = 4;
|
||||||
switch((DM0CNT_H >> 7) & 3) {
|
switch((DM0CNT_H >> 7) & 3) {
|
||||||
|
@ -2375,6 +2380,8 @@ void CPUCheckDMA(int reason, int dmamask)
|
||||||
// DMA 1
|
// DMA 1
|
||||||
if((DM1CNT_H & 0x8000) && (dmamask & 2)) {
|
if((DM1CNT_H & 0x8000) && (dmamask & 2)) {
|
||||||
if(((DM1CNT_H >> 12) & 3) == reason) {
|
if(((DM1CNT_H >> 12) & 3) == reason) {
|
||||||
|
res = true;
|
||||||
|
|
||||||
u32 sourceIncrement = 4;
|
u32 sourceIncrement = 4;
|
||||||
u32 destIncrement = 4;
|
u32 destIncrement = 4;
|
||||||
switch((DM1CNT_H >> 7) & 3) {
|
switch((DM1CNT_H >> 7) & 3) {
|
||||||
|
@ -2444,6 +2451,7 @@ void CPUCheckDMA(int reason, int dmamask)
|
||||||
// DMA 2
|
// DMA 2
|
||||||
if((DM2CNT_H & 0x8000) && (dmamask & 4)) {
|
if((DM2CNT_H & 0x8000) && (dmamask & 4)) {
|
||||||
if(((DM2CNT_H >> 12) & 3) == reason) {
|
if(((DM2CNT_H >> 12) & 3) == reason) {
|
||||||
|
res = true;
|
||||||
u32 sourceIncrement = 4;
|
u32 sourceIncrement = 4;
|
||||||
u32 destIncrement = 4;
|
u32 destIncrement = 4;
|
||||||
switch((DM2CNT_H >> 7) & 3) {
|
switch((DM2CNT_H >> 7) & 3) {
|
||||||
|
@ -2514,6 +2522,7 @@ void CPUCheckDMA(int reason, int dmamask)
|
||||||
// DMA 3
|
// DMA 3
|
||||||
if((DM3CNT_H & 0x8000) && (dmamask & 8)) {
|
if((DM3CNT_H & 0x8000) && (dmamask & 8)) {
|
||||||
if(((DM3CNT_H >> 12) & 3) == reason) {
|
if(((DM3CNT_H >> 12) & 3) == reason) {
|
||||||
|
res = true;
|
||||||
u32 sourceIncrement = 4;
|
u32 sourceIncrement = 4;
|
||||||
u32 destIncrement = 4;
|
u32 destIncrement = 4;
|
||||||
switch((DM3CNT_H >> 7) & 3) {
|
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)
|
void CPUUpdateRegister(u32 address, u16 value)
|
||||||
|
@ -3846,6 +3857,8 @@ void CPULoop(int ticks)
|
||||||
int timerOverflow = 0;
|
int timerOverflow = 0;
|
||||||
// variable used by the CPU core
|
// variable used by the CPU core
|
||||||
cpuTotalTicks = 0;
|
cpuTotalTicks = 0;
|
||||||
|
if(cpuDmaHack2)
|
||||||
|
cpuNextEvent = 1;
|
||||||
cpuBreakLoop = false;
|
cpuBreakLoop = false;
|
||||||
cpuNextEvent = CPUUpdateTicks();
|
cpuNextEvent = CPUUpdateTicks();
|
||||||
if(cpuNextEvent > ticks)
|
if(cpuNextEvent > ticks)
|
||||||
|
@ -4044,7 +4057,7 @@ void CPULoop(int ticks)
|
||||||
IF |= 1;
|
IF |= 1;
|
||||||
UPDATE_REG(0x202, IF);
|
UPDATE_REG(0x202, IF);
|
||||||
}
|
}
|
||||||
CPUCheckDMA(1, 0x0f);
|
cpuDmaHack2 = CPUCheckDMA(1, 0x0f);
|
||||||
if(frameCount >= framesToSkip) {
|
if(frameCount >= framesToSkip) {
|
||||||
systemDrawScreen();
|
systemDrawScreen();
|
||||||
frameCount = 0;
|
frameCount = 0;
|
||||||
|
@ -4164,7 +4177,7 @@ void CPULoop(int ticks)
|
||||||
DISPSTAT |= 2;
|
DISPSTAT |= 2;
|
||||||
UPDATE_REG(0x04, DISPSTAT);
|
UPDATE_REG(0x04, DISPSTAT);
|
||||||
lcdTicks += 224;
|
lcdTicks += 224;
|
||||||
CPUCheckDMA(2, 0x0f);
|
cpuDmaHack2 = CPUCheckDMA(2, 0x0f);
|
||||||
if(DISPSTAT & 16) {
|
if(DISPSTAT & 16) {
|
||||||
IF |= 2;
|
IF |= 2;
|
||||||
UPDATE_REG(0x202, IF);
|
UPDATE_REG(0x202, IF);
|
||||||
|
@ -4328,6 +4341,9 @@ void CPULoop(int ticks)
|
||||||
goto updateLoop;
|
goto updateLoop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if(cpuDmaHack2)
|
||||||
|
// cpuNextEvent = 1;
|
||||||
|
|
||||||
if(IF && (IME & 1) && armIrqEnable) {
|
if(IF && (IME & 1) && armIrqEnable) {
|
||||||
int res = IF & IE;
|
int res = IF & IE;
|
||||||
if(stopState)
|
if(stopState)
|
||||||
|
|
|
@ -116,7 +116,7 @@ extern void CPUWriteByte(u32, u8);
|
||||||
extern void CPUInit(const char *,bool);
|
extern void CPUInit(const char *,bool);
|
||||||
extern void CPUReset();
|
extern void CPUReset();
|
||||||
extern void CPULoop(int);
|
extern void CPULoop(int);
|
||||||
extern void CPUCheckDMA(int,int);
|
extern bool CPUCheckDMA(int,int);
|
||||||
extern bool CPUIsGBAImage(const char *);
|
extern bool CPUIsGBAImage(const char *);
|
||||||
extern bool CPUIsZipFile(const char *);
|
extern bool CPUIsZipFile(const char *);
|
||||||
#ifdef PROFILING
|
#ifdef PROFILING
|
||||||
|
|
989
src/GBAinline.h
989
src/GBAinline.h
|
@ -1,499 +1,498 @@
|
||||||
// -*- C++ -*-
|
// -*- C++ -*-
|
||||||
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
||||||
// Copyright (C) 1999-2003 Forgotten
|
// Copyright (C) 1999-2003 Forgotten
|
||||||
// Copyright (C) 2005 Forgotten and the VBA development team
|
// Copyright (C) 2005 Forgotten and the VBA development team
|
||||||
|
|
||||||
// This program is free software; you can redistribute it and/or modify
|
// 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
|
// it under the terms of the GNU General Public License as published by
|
||||||
// the Free Software Foundation; either version 2, or(at your option)
|
// the Free Software Foundation; either version 2, or(at your option)
|
||||||
// any later version.
|
// any later version.
|
||||||
//
|
//
|
||||||
// This program is distributed in the hope that it will be useful,
|
// This program is distributed in the hope that it will be useful,
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
// GNU General Public License for more details.
|
// GNU General Public License for more details.
|
||||||
//
|
//
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program; if not, write to the Free Software Foundation,
|
// along with this program; if not, write to the Free Software Foundation,
|
||||||
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
#ifndef VBA_GBAinline_H
|
#ifndef VBA_GBAinline_H
|
||||||
#define VBA_GBAinline_H
|
#define VBA_GBAinline_H
|
||||||
|
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
#include "Port.h"
|
#include "Port.h"
|
||||||
#include "RTC.h"
|
#include "RTC.h"
|
||||||
|
#include "Sound.h"
|
||||||
extern bool cpuSramEnabled;
|
|
||||||
extern bool cpuFlashEnabled;
|
extern bool cpuSramEnabled;
|
||||||
extern bool cpuEEPROMEnabled;
|
extern bool cpuFlashEnabled;
|
||||||
extern bool cpuEEPROMSensorEnabled;
|
extern bool cpuEEPROMEnabled;
|
||||||
|
extern bool cpuEEPROMSensorEnabled;
|
||||||
extern int lspeed;
|
extern int lspeed;
|
||||||
extern void LinkSStop(void);
|
extern void LinkSStop(void);
|
||||||
extern bool cpuDmaHack;
|
extern bool cpuDmaHack;
|
||||||
extern u32 cpuDmaLast;
|
extern bool cpuDmaHack2;
|
||||||
extern bool timer0On;
|
extern u32 cpuDmaLast;
|
||||||
extern int timer0Ticks;
|
extern bool timer0On;
|
||||||
extern int timer0ClockReload;
|
extern int timer0Ticks;
|
||||||
extern bool timer1On;
|
extern int timer0ClockReload;
|
||||||
extern int timer1Ticks;
|
extern bool timer1On;
|
||||||
extern int timer1ClockReload;
|
extern int timer1Ticks;
|
||||||
extern bool timer2On;
|
extern int timer1ClockReload;
|
||||||
extern int timer2Ticks;
|
extern bool timer2On;
|
||||||
extern int timer2ClockReload;
|
extern int timer2Ticks;
|
||||||
extern bool timer3On;
|
extern int timer2ClockReload;
|
||||||
extern int timer3Ticks;
|
extern bool timer3On;
|
||||||
extern int timer3ClockReload;
|
extern int timer3Ticks;
|
||||||
extern int cpuTotalTicks;
|
extern int timer3ClockReload;
|
||||||
|
extern int cpuTotalTicks;
|
||||||
#define CPUReadByteQuick(addr) \
|
|
||||||
map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
|
#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 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]))
|
#define CPUReadMemoryQuick(addr) \
|
||||||
|
READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
|
||||||
static inline u32 CPUReadMemory(u32 address)
|
|
||||||
{
|
static inline u32 CPUReadMemory(u32 address)
|
||||||
|
{
|
||||||
#ifdef DEV_VERSION
|
|
||||||
if(address & 3) {
|
#ifdef DEV_VERSION
|
||||||
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
if(address & 3) {
|
||||||
log("Unaligned word read: %08x at %08x\n", address, armMode ?
|
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
||||||
armNextPC - 4 : armNextPC - 2);
|
log("Unaligned word read: %08x at %08x\n", address, armMode ?
|
||||||
}
|
armNextPC - 4 : armNextPC - 2);
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
#endif
|
||||||
u32 value;
|
|
||||||
switch(address >> 24) {
|
u32 value;
|
||||||
case 0:
|
switch(address >> 24) {
|
||||||
if(reg[15].I >> 24) {
|
case 0:
|
||||||
if(address < 0x4000) {
|
if(reg[15].I >> 24) {
|
||||||
#ifdef DEV_VERSION
|
if(address < 0x4000) {
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
#ifdef DEV_VERSION
|
||||||
log("Illegal word read: %08x at %08x\n", address, armMode ?
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
armNextPC - 4 : armNextPC - 2);
|
log("Illegal word read: %08x at %08x\n", address, armMode ?
|
||||||
}
|
armNextPC - 4 : armNextPC - 2);
|
||||||
#endif
|
}
|
||||||
|
#endif
|
||||||
value = READ32LE(((u32 *)&biosProtected));
|
|
||||||
}
|
value = READ32LE(((u32 *)&biosProtected));
|
||||||
else goto unreadable;
|
}
|
||||||
} else
|
else goto unreadable;
|
||||||
value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
|
} else
|
||||||
break;
|
value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
|
||||||
case 2:
|
break;
|
||||||
value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
|
case 2:
|
||||||
break;
|
value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
|
||||||
case 3:
|
break;
|
||||||
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
|
case 3:
|
||||||
break;
|
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
|
||||||
case 4:
|
break;
|
||||||
if((address>=0x4000120||address<=0x4000126)&&lspeed)
|
case 4:
|
||||||
|
if((address>=0x4000120||address<=0x4000126)&&lspeed)
|
||||||
LinkSStop();
|
LinkSStop();
|
||||||
|
if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
|
||||||
if((address < 0x4000400) && ioReadable[address & 0x3fc]) {
|
if(ioReadable[(address & 0x3fc) + 2])
|
||||||
if(ioReadable[(address & 0x3fc) + 2])
|
value = soundRead32(address & 0x3fC);
|
||||||
value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
|
else
|
||||||
else
|
value = soundRead16(address & 0x3fc);
|
||||||
value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
|
} else goto unreadable;
|
||||||
} else goto unreadable;
|
break;
|
||||||
break;
|
case 5:
|
||||||
case 5:
|
value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
|
||||||
value = READ32LE(((u32 *)&paletteRAM[address & 0x3fC]));
|
break;
|
||||||
break;
|
case 6:
|
||||||
case 6:
|
address = (address & 0x1fffc);
|
||||||
address = (address & 0x1fffc);
|
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
||||||
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
{
|
||||||
{
|
value = 0;
|
||||||
value = 0;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
if ((address & 0x18000) == 0x18000)
|
||||||
if ((address & 0x18000) == 0x18000)
|
address &= 0x17fff;
|
||||||
address &= 0x17fff;
|
value = READ32LE(((u32 *)&vram[address]));
|
||||||
value = READ32LE(((u32 *)&vram[address]));
|
break;
|
||||||
break;
|
case 7:
|
||||||
case 7:
|
value = READ32LE(((u32 *)&oam[address & 0x3FC]));
|
||||||
value = READ32LE(((u32 *)&oam[address & 0x3FC]));
|
break;
|
||||||
break;
|
case 8:
|
||||||
case 8:
|
case 9:
|
||||||
case 9:
|
case 10:
|
||||||
case 10:
|
case 11:
|
||||||
case 11:
|
case 12:
|
||||||
case 12:
|
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
|
||||||
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
|
break;
|
||||||
break;
|
case 13:
|
||||||
case 13:
|
if(cpuEEPROMEnabled)
|
||||||
if(cpuEEPROMEnabled)
|
// no need to swap this
|
||||||
// no need to swap this
|
return eepromRead(address);
|
||||||
return eepromRead(address);
|
goto unreadable;
|
||||||
goto unreadable;
|
case 14:
|
||||||
case 14:
|
if(cpuFlashEnabled | cpuSramEnabled)
|
||||||
if(cpuFlashEnabled | cpuSramEnabled)
|
// no need to swap this
|
||||||
// no need to swap this
|
return flashRead(address);
|
||||||
return flashRead(address);
|
// default
|
||||||
// default
|
default:
|
||||||
default:
|
unreadable:
|
||||||
unreadable:
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
log("Illegal word read: %08x at %08x\n", address, armMode ?
|
||||||
log("Illegal word read: %08x at %08x\n", address, armMode ?
|
armNextPC - 4 : armNextPC - 2);
|
||||||
armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
|
||||||
|
if(cpuDmaHack || cpuDmaHack2) {
|
||||||
if(cpuDmaHack) {
|
value = cpuDmaLast;
|
||||||
value = cpuDmaLast;
|
} else {
|
||||||
} else {
|
if(armState) {
|
||||||
if(armState) {
|
value = CPUReadMemoryQuick(reg[15].I);
|
||||||
value = CPUReadMemoryQuick(reg[15].I);
|
} else {
|
||||||
} else {
|
value = CPUReadHalfWordQuick(reg[15].I) |
|
||||||
value = CPUReadHalfWordQuick(reg[15].I) |
|
CPUReadHalfWordQuick(reg[15].I) << 16;
|
||||||
CPUReadHalfWordQuick(reg[15].I) << 16;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if(address & 3) {
|
||||||
if(address & 3) {
|
#ifdef C_CORE
|
||||||
#ifdef C_CORE
|
int shift = (address & 3) << 3;
|
||||||
int shift = (address & 3) << 3;
|
value = (value >> shift) | (value << (32 - shift));
|
||||||
value = (value >> shift) | (value << (32 - shift));
|
#else
|
||||||
#else
|
#ifdef __GNUC__
|
||||||
#ifdef __GNUC__
|
asm("and $3, %%ecx;"
|
||||||
asm("and $3, %%ecx;"
|
"shl $3 ,%%ecx;"
|
||||||
"shl $3 ,%%ecx;"
|
"ror %%cl, %0"
|
||||||
"ror %%cl, %0"
|
: "=r" (value)
|
||||||
: "=r" (value)
|
: "r" (value), "c" (address));
|
||||||
: "r" (value), "c" (address));
|
#else
|
||||||
#else
|
__asm {
|
||||||
__asm {
|
mov ecx, address;
|
||||||
mov ecx, address;
|
and ecx, 3;
|
||||||
and ecx, 3;
|
shl ecx, 3;
|
||||||
shl ecx, 3;
|
ror [dword ptr value], cl;
|
||||||
ror [dword ptr value], cl;
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
}
|
||||||
}
|
return value;
|
||||||
return value;
|
}
|
||||||
}
|
|
||||||
|
extern u32 myROM[];
|
||||||
extern u32 myROM[];
|
|
||||||
|
static inline u32 CPUReadHalfWord(u32 address)
|
||||||
static inline u32 CPUReadHalfWord(u32 address)
|
{
|
||||||
{
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(address & 1) {
|
||||||
if(address & 1) {
|
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
||||||
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
|
||||||
log("Unaligned halfword read: %08x at %08x\n", address, armMode ?
|
armNextPC - 4 : armNextPC - 2);
|
||||||
armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
|
||||||
|
u32 value;
|
||||||
u32 value;
|
|
||||||
|
switch(address >> 24) {
|
||||||
switch(address >> 24) {
|
case 0:
|
||||||
case 0:
|
if (reg[15].I >> 24) {
|
||||||
if (reg[15].I >> 24) {
|
if(address < 0x4000) {
|
||||||
if(address < 0x4000) {
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
|
||||||
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
|
armNextPC - 4 : armNextPC - 2);
|
||||||
armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
value = READ16LE(((u16 *)&biosProtected[address&2]));
|
||||||
value = READ16LE(((u16 *)&biosProtected[address&2]));
|
} else goto unreadable;
|
||||||
} else goto unreadable;
|
} else
|
||||||
} else
|
value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
|
||||||
value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
|
||||||
value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
|
break;
|
||||||
break;
|
case 3:
|
||||||
case 3:
|
value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
|
||||||
value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
|
break;
|
||||||
break;
|
case 4:
|
||||||
case 4:
|
if((address>=0x4000120||address<=0x4000126)&&lspeed)
|
||||||
if((address>=0x4000120||address<=0x4000126)&&lspeed)
|
|
||||||
LinkSStop();
|
LinkSStop();
|
||||||
|
if((address < 0x4000400) && ioReadable[address & 0x3fe])
|
||||||
if((address < 0x4000400) && ioReadable[address & 0x3fe])
|
{
|
||||||
{
|
value = soundRead16(address & 0x3fe);
|
||||||
value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
|
if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E))
|
||||||
if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E))
|
{
|
||||||
{
|
if (((address & 0x3fe) == 0x100) && timer0On)
|
||||||
if (((address & 0x3fe) == 0x100) && timer0On)
|
value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload);
|
||||||
value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload);
|
else
|
||||||
else
|
if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4))
|
||||||
if (((address & 0x3fe) == 0x104) && timer1On && !(TM1CNT & 4))
|
value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload);
|
||||||
value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload);
|
else
|
||||||
else
|
if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4))
|
||||||
if (((address & 0x3fe) == 0x108) && timer2On && !(TM2CNT & 4))
|
value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload);
|
||||||
value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload);
|
else
|
||||||
else
|
if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4))
|
||||||
if (((address & 0x3fe) == 0x10C) && timer3On && !(TM3CNT & 4))
|
value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
|
||||||
value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
|
}
|
||||||
}
|
}
|
||||||
}
|
else goto unreadable;
|
||||||
else goto unreadable;
|
break;
|
||||||
break;
|
case 5:
|
||||||
case 5:
|
value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
|
||||||
value = READ16LE(((u16 *)&paletteRAM[address & 0x3fe]));
|
break;
|
||||||
break;
|
case 6:
|
||||||
case 6:
|
address = (address & 0x1fffe);
|
||||||
address = (address & 0x1fffe);
|
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
||||||
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
{
|
||||||
{
|
value = 0;
|
||||||
value = 0;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
if ((address & 0x18000) == 0x18000)
|
||||||
if ((address & 0x18000) == 0x18000)
|
address &= 0x17fff;
|
||||||
address &= 0x17fff;
|
value = READ16LE(((u16 *)&vram[address]));
|
||||||
value = READ16LE(((u16 *)&vram[address]));
|
break;
|
||||||
break;
|
case 7:
|
||||||
case 7:
|
value = READ16LE(((u16 *)&oam[address & 0x3fe]));
|
||||||
value = READ16LE(((u16 *)&oam[address & 0x3fe]));
|
break;
|
||||||
break;
|
case 8:
|
||||||
case 8:
|
case 9:
|
||||||
case 9:
|
case 10:
|
||||||
case 10:
|
case 11:
|
||||||
case 11:
|
case 12:
|
||||||
case 12:
|
if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
|
||||||
if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
|
value = rtcRead(address);
|
||||||
value = rtcRead(address);
|
else
|
||||||
else
|
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
|
||||||
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
|
break;
|
||||||
break;
|
case 13:
|
||||||
case 13:
|
if(cpuEEPROMEnabled)
|
||||||
if(cpuEEPROMEnabled)
|
// no need to swap this
|
||||||
// no need to swap this
|
return eepromRead(address);
|
||||||
return eepromRead(address);
|
goto unreadable;
|
||||||
goto unreadable;
|
case 14:
|
||||||
case 14:
|
if(cpuFlashEnabled | cpuSramEnabled)
|
||||||
if(cpuFlashEnabled | cpuSramEnabled)
|
// no need to swap this
|
||||||
// no need to swap this
|
return flashRead(address);
|
||||||
return flashRead(address);
|
// default
|
||||||
// default
|
default:
|
||||||
default:
|
unreadable:
|
||||||
unreadable:
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
|
||||||
log("Illegal halfword read: %08x at %08x\n", address, armMode ?
|
armNextPC - 4 : armNextPC - 2);
|
||||||
armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
if(cpuDmaHack2 || cpuDmaHack) {
|
||||||
if(cpuDmaHack) {
|
value = cpuDmaLast & 0xFFFF;
|
||||||
value = cpuDmaLast & 0xFFFF;
|
} else {
|
||||||
} else {
|
if(armState) {
|
||||||
if(armState) {
|
value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
|
||||||
value = CPUReadHalfWordQuick(reg[15].I + (address & 2));
|
} else {
|
||||||
} else {
|
value = CPUReadHalfWordQuick(reg[15].I);
|
||||||
value = CPUReadHalfWordQuick(reg[15].I);
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
if(address & 1) {
|
||||||
if(address & 1) {
|
value = (value >> 8) | (value << 24);
|
||||||
value = (value >> 8) | (value << 24);
|
}
|
||||||
}
|
|
||||||
|
return value;
|
||||||
return value;
|
}
|
||||||
}
|
|
||||||
|
static inline u16 CPUReadHalfWordSigned(u32 address)
|
||||||
static inline u16 CPUReadHalfWordSigned(u32 address)
|
{
|
||||||
{
|
u16 value = CPUReadHalfWord(address);
|
||||||
u16 value = CPUReadHalfWord(address);
|
if((address & 1))
|
||||||
if((address & 1))
|
value = (s8)value;
|
||||||
value = (s8)value;
|
return value;
|
||||||
return value;
|
}
|
||||||
}
|
|
||||||
|
static inline u8 CPUReadByte(u32 address)
|
||||||
static inline u8 CPUReadByte(u32 address)
|
{
|
||||||
{
|
switch(address >> 24) {
|
||||||
switch(address >> 24) {
|
case 0:
|
||||||
case 0:
|
if (reg[15].I >> 24) {
|
||||||
if (reg[15].I >> 24) {
|
if(address < 0x4000) {
|
||||||
if(address < 0x4000) {
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
log("Illegal byte read: %08x at %08x\n", address, armMode ?
|
||||||
log("Illegal byte read: %08x at %08x\n", address, armMode ?
|
armNextPC - 4 : armNextPC - 2);
|
||||||
armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
return biosProtected[address & 3];
|
||||||
return biosProtected[address & 3];
|
} else goto unreadable;
|
||||||
} else goto unreadable;
|
}
|
||||||
}
|
return bios[address & 0x3FFF];
|
||||||
return bios[address & 0x3FFF];
|
case 2:
|
||||||
case 2:
|
return workRAM[address & 0x3FFFF];
|
||||||
return workRAM[address & 0x3FFFF];
|
case 3:
|
||||||
case 3:
|
return internalRAM[address & 0x7fff];
|
||||||
return internalRAM[address & 0x7fff];
|
case 4:
|
||||||
case 4:
|
if((address>=0x4000120||address<=0x4000126)&&lspeed)
|
||||||
if((address>=0x4000120||address<=0x4000126)&&lspeed)
|
|
||||||
LinkSStop();
|
LinkSStop();
|
||||||
|
if((address < 0x4000400) && ioReadable[address & 0x3ff])
|
||||||
if((address < 0x4000400) && ioReadable[address & 0x3ff])
|
return soundRead(address & 0x3ff);
|
||||||
return ioMem[address & 0x3ff];
|
else goto unreadable;
|
||||||
else goto unreadable;
|
case 5:
|
||||||
case 5:
|
return paletteRAM[address & 0x3ff];
|
||||||
return paletteRAM[address & 0x3ff];
|
case 6:
|
||||||
case 6:
|
address = (address & 0x1ffff);
|
||||||
address = (address & 0x1ffff);
|
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
||||||
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
return 0;
|
||||||
return 0;
|
if ((address & 0x18000) == 0x18000)
|
||||||
if ((address & 0x18000) == 0x18000)
|
address &= 0x17fff;
|
||||||
address &= 0x17fff;
|
return vram[address];
|
||||||
return vram[address];
|
case 7:
|
||||||
case 7:
|
return oam[address & 0x3ff];
|
||||||
return oam[address & 0x3ff];
|
case 8:
|
||||||
case 8:
|
case 9:
|
||||||
case 9:
|
case 10:
|
||||||
case 10:
|
case 11:
|
||||||
case 11:
|
case 12:
|
||||||
case 12:
|
return rom[address & 0x1FFFFFF];
|
||||||
return rom[address & 0x1FFFFFF];
|
case 13:
|
||||||
case 13:
|
if(cpuEEPROMEnabled)
|
||||||
if(cpuEEPROMEnabled)
|
return eepromRead(address);
|
||||||
return eepromRead(address);
|
goto unreadable;
|
||||||
goto unreadable;
|
case 14:
|
||||||
case 14:
|
if(cpuSramEnabled | cpuFlashEnabled)
|
||||||
if(cpuSramEnabled | cpuFlashEnabled)
|
return flashRead(address);
|
||||||
return flashRead(address);
|
if(cpuEEPROMSensorEnabled) {
|
||||||
if(cpuEEPROMSensorEnabled) {
|
switch(address & 0x00008f00) {
|
||||||
switch(address & 0x00008f00) {
|
case 0x8200:
|
||||||
case 0x8200:
|
return systemGetSensorX() & 255;
|
||||||
return systemGetSensorX() & 255;
|
case 0x8300:
|
||||||
case 0x8300:
|
return (systemGetSensorX() >> 8)|0x80;
|
||||||
return (systemGetSensorX() >> 8)|0x80;
|
case 0x8400:
|
||||||
case 0x8400:
|
return systemGetSensorY() & 255;
|
||||||
return systemGetSensorY() & 255;
|
case 0x8500:
|
||||||
case 0x8500:
|
return systemGetSensorY() >> 8;
|
||||||
return systemGetSensorY() >> 8;
|
}
|
||||||
}
|
}
|
||||||
}
|
// default
|
||||||
// default
|
default:
|
||||||
default:
|
unreadable:
|
||||||
unreadable:
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_READ) {
|
log("Illegal byte read: %08x at %08x\n", address, armMode ?
|
||||||
log("Illegal byte read: %08x at %08x\n", address, armMode ?
|
armNextPC - 4 : armNextPC - 2);
|
||||||
armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
if(cpuDmaHack || cpuDmaHack2) {
|
||||||
if(cpuDmaHack) {
|
return cpuDmaLast & 0xFF;
|
||||||
return cpuDmaLast & 0xFF;
|
} else {
|
||||||
} else {
|
if(armState) {
|
||||||
if(armState) {
|
return CPUReadByteQuick(reg[15].I+(address & 3));
|
||||||
return CPUReadByteQuick(reg[15].I+(address & 3));
|
} else {
|
||||||
} else {
|
return CPUReadByteQuick(reg[15].I+(address & 1));
|
||||||
return CPUReadByteQuick(reg[15].I+(address & 1));
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
static inline void CPUWriteMemory(u32 address, u32 value)
|
||||||
static inline void CPUWriteMemory(u32 address, u32 value)
|
{
|
||||||
{
|
|
||||||
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(address & 3) {
|
||||||
if(address & 3) {
|
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
||||||
if(systemVerbose & VERBOSE_UNALIGNED_MEMORY) {
|
log("Unaligned word write: %08x to %08x from %08x\n",
|
||||||
log("Unaligned word write: %08x to %08x from %08x\n",
|
value,
|
||||||
value,
|
address,
|
||||||
address,
|
armMode ? armNextPC - 4 : armNextPC - 2);
|
||||||
armMode ? armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
|
||||||
|
switch(address >> 24) {
|
||||||
switch(address >> 24) {
|
case 0x02:
|
||||||
case 0x02:
|
#ifdef BKPT_SUPPORT
|
||||||
#ifdef BKPT_SUPPORT
|
if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
|
||||||
if(*((u32 *)&freezeWorkRAM[address & 0x3FFFC]))
|
cheatsWriteMemory(address & 0x203FFFC,
|
||||||
cheatsWriteMemory(address & 0x203FFFC,
|
value);
|
||||||
value);
|
else
|
||||||
else
|
#endif
|
||||||
#endif
|
WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
|
||||||
WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
|
break;
|
||||||
break;
|
case 0x03:
|
||||||
case 0x03:
|
#ifdef BKPT_SUPPORT
|
||||||
#ifdef BKPT_SUPPORT
|
if(*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
|
||||||
if(*((u32 *)&freezeInternalRAM[address & 0x7ffc]))
|
cheatsWriteMemory(address & 0x3007FFC,
|
||||||
cheatsWriteMemory(address & 0x3007FFC,
|
value);
|
||||||
value);
|
else
|
||||||
else
|
#endif
|
||||||
#endif
|
WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
|
||||||
WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
|
break;
|
||||||
break;
|
case 0x04:
|
||||||
case 0x04:
|
if(address < 0x4000400) {
|
||||||
if(address < 0x4000400) {
|
CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
|
||||||
CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
|
CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
|
||||||
CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
|
} else goto unwritable;
|
||||||
} else goto unwritable;
|
break;
|
||||||
break;
|
case 0x05:
|
||||||
case 0x05:
|
#ifdef BKPT_SUPPORT
|
||||||
#ifdef BKPT_SUPPORT
|
if(*((u32 *)&freezePRAM[address & 0x3fc]))
|
||||||
if(*((u32 *)&freezePRAM[address & 0x3fc]))
|
cheatsWriteMemory(address & 0x70003FC,
|
||||||
cheatsWriteMemory(address & 0x70003FC,
|
value);
|
||||||
value);
|
else
|
||||||
else
|
#endif
|
||||||
#endif
|
WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
|
||||||
WRITE32LE(((u32 *)&paletteRAM[address & 0x3FC]), value);
|
break;
|
||||||
break;
|
case 0x06:
|
||||||
case 0x06:
|
address = (address & 0x1fffc);
|
||||||
address = (address & 0x1fffc);
|
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
||||||
if (((DISPCNT & 7) >2) && ((address & 0x1C000) == 0x18000))
|
return;
|
||||||
return;
|
if ((address & 0x18000) == 0x18000)
|
||||||
if ((address & 0x18000) == 0x18000)
|
address &= 0x17fff;
|
||||||
address &= 0x17fff;
|
|
||||||
|
#ifdef BKPT_SUPPORT
|
||||||
#ifdef BKPT_SUPPORT
|
if(*((u32 *)&freezeVRAM[address]))
|
||||||
if(*((u32 *)&freezeVRAM[address]))
|
cheatsWriteMemory(address + 0x06000000, value);
|
||||||
cheatsWriteMemory(address + 0x06000000, value);
|
else
|
||||||
else
|
#endif
|
||||||
#endif
|
|
||||||
|
WRITE32LE(((u32 *)&vram[address]), value);
|
||||||
WRITE32LE(((u32 *)&vram[address]), value);
|
break;
|
||||||
break;
|
case 0x07:
|
||||||
case 0x07:
|
#ifdef BKPT_SUPPORT
|
||||||
#ifdef BKPT_SUPPORT
|
if(*((u32 *)&freezeOAM[address & 0x3fc]))
|
||||||
if(*((u32 *)&freezeOAM[address & 0x3fc]))
|
cheatsWriteMemory(address & 0x70003FC,
|
||||||
cheatsWriteMemory(address & 0x70003FC,
|
value);
|
||||||
value);
|
else
|
||||||
else
|
#endif
|
||||||
#endif
|
WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
|
||||||
WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
|
break;
|
||||||
break;
|
case 0x0D:
|
||||||
case 0x0D:
|
if(cpuEEPROMEnabled) {
|
||||||
if(cpuEEPROMEnabled) {
|
eepromWrite(address, value);
|
||||||
eepromWrite(address, value);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
goto unwritable;
|
||||||
goto unwritable;
|
case 0x0E:
|
||||||
case 0x0E:
|
if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
|
||||||
if(!eepromInUse | cpuSramEnabled | cpuFlashEnabled) {
|
(*cpuSaveGameFunc)(address, (u8)value);
|
||||||
(*cpuSaveGameFunc)(address, (u8)value);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
// default
|
||||||
// default
|
default:
|
||||||
default:
|
unwritable:
|
||||||
unwritable:
|
#ifdef DEV_VERSION
|
||||||
#ifdef DEV_VERSION
|
if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
|
||||||
if(systemVerbose & VERBOSE_ILLEGAL_WRITE) {
|
log("Illegal word write: %08x to %08x from %08x\n",
|
||||||
log("Illegal word write: %08x to %08x from %08x\n",
|
value,
|
||||||
value,
|
address,
|
||||||
address,
|
armMode ? armNextPC - 4 : armNextPC - 2);
|
||||||
armMode ? armNextPC - 4 : armNextPC - 2);
|
}
|
||||||
}
|
#endif
|
||||||
#endif
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
#endif //VBA_GBAinline_H
|
||||||
#endif //VBA_GBAinline_H
|
|
||||||
|
|
|
@ -320,7 +320,7 @@ void Blip_Synth_::volume_unit( double new_unit )
|
||||||
factor *= 2.0;
|
factor *= 2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( shift )
|
// if ( shift )
|
||||||
{
|
{
|
||||||
kernel_unit >>= shift;
|
kernel_unit >>= shift;
|
||||||
assert( kernel_unit > 0 ); // fails if volume unit is too low
|
assert( kernel_unit > 0 ); // fails if volume unit is too low
|
||||||
|
|
|
@ -107,7 +107,7 @@ void Gb_Apu::reset(bool igba)
|
||||||
square1.reset();
|
square1.reset();
|
||||||
square2.reset();
|
square2.reset();
|
||||||
wave.reset(gba = igba);
|
wave.reset(gba = igba);
|
||||||
noise.reset();
|
noise.reset(igba);
|
||||||
noise.bits = 1;
|
noise.bits = 1;
|
||||||
wave.wave_pos = 0;
|
wave.wave_pos = 0;
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
void Gb_Noise::run( gb_time_t time, gb_time_t end_time, int playing )
|
||||||
{
|
{
|
||||||
int amp = volume & playing;
|
int amp = volume & playing;
|
||||||
|
|
||||||
int tap = 13 - (regs [3] & 8);
|
int tap = 13 - (regs [3] & 8);
|
||||||
if ( bits >> tap & 2 )
|
if ( bits >> tap & 2 )
|
||||||
amp = -amp;
|
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 =
|
const blip_resampled_time_t resampled_period =
|
||||||
output->resampled_duration( period );
|
output->resampled_duration( period );
|
||||||
blip_resampled_time_t resampled_time = output->resampled_time( time );
|
blip_resampled_time_t resampled_time = output->resampled_time( time );
|
||||||
unsigned bits = this->bits;
|
// unsigned bits = this->bits;
|
||||||
int delta = amp * 2;
|
int delta = amp * 2;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -215,7 +216,7 @@ void Gb_Noise::run( gb_time_t time, gb_time_t end_time, int playing )
|
||||||
}
|
}
|
||||||
while ( time < end_time );
|
while ( time < end_time );
|
||||||
|
|
||||||
this->bits = bits;
|
//this->bits = bits;
|
||||||
last_amp = delta >> 1;
|
last_amp = delta >> 1;
|
||||||
}
|
}
|
||||||
delay = time - end_time;
|
delay = time - end_time;
|
||||||
|
@ -227,7 +228,7 @@ void Gb_Wave::reset(bool gba)
|
||||||
{
|
{
|
||||||
volume_forced = 0;
|
volume_forced = 0;
|
||||||
wave_pos = 0;
|
wave_pos = 0;
|
||||||
wave_mode = gba;
|
wave_mode = (gba ? 1 : 0);
|
||||||
wave_size = 32;
|
wave_size = 32;
|
||||||
wave_bank = 0;
|
wave_bank = 0;
|
||||||
memset( wave, 0, sizeof wave );
|
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 )
|
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
|
int volume_shift = (volume - 1) & 7; // volume = 0 causes shift = 7
|
||||||
|
|
|
@ -57,10 +57,17 @@ struct Gb_Square : Gb_Env
|
||||||
|
|
||||||
struct Gb_Noise : Gb_Env
|
struct Gb_Noise : Gb_Env
|
||||||
{
|
{
|
||||||
|
bool gba;
|
||||||
typedef Blip_Synth<blip_med_quality,1> Synth;
|
typedef Blip_Synth<blip_med_quality,1> Synth;
|
||||||
Synth const* synth;
|
Synth const* synth;
|
||||||
unsigned bits;
|
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 );
|
void run( gb_time_t, gb_time_t, int playing );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ int lspeed = 0;
|
||||||
lserver ls;
|
lserver ls;
|
||||||
lclient lc;
|
lclient lc;
|
||||||
bool oncewait = false, after = false;
|
bool oncewait = false, after = false;
|
||||||
bool adapter = true;
|
bool adapter = false;
|
||||||
u8 rfu_cmd, rfu_qsend, rfu_qrecv;
|
u8 rfu_cmd, rfu_qsend, rfu_qrecv;
|
||||||
int rfu_state, rfu_polarity, linktime2, counter, rfu_masterq;
|
int rfu_state, rfu_polarity, linktime2, counter, rfu_masterq;
|
||||||
int transferend, numtransfers = 0;
|
int transferend, numtransfers = 0;
|
||||||
|
|
|
@ -670,7 +670,7 @@ void soundDirectSoundATimer()
|
||||||
{
|
{
|
||||||
if(soundDSAEnabled) {
|
if(soundDSAEnabled) {
|
||||||
if(soundDSFifoACount <= 16) {
|
if(soundDSFifoACount <= 16) {
|
||||||
CPUCheckDMA(3, 2);
|
cpuDmaHack2 = CPUCheckDMA(3, 2);
|
||||||
if(soundDSFifoACount <= 16) {
|
if(soundDSFifoACount <= 16) {
|
||||||
soundEvent(FIFOA_L, (u16)0);
|
soundEvent(FIFOA_L, (u16)0);
|
||||||
soundEvent(FIFOA_H, (u16)0);
|
soundEvent(FIFOA_H, (u16)0);
|
||||||
|
@ -699,8 +699,7 @@ void soundDirectSoundBTimer()
|
||||||
{
|
{
|
||||||
if(soundDSBEnabled) {
|
if(soundDSBEnabled) {
|
||||||
if(soundDSFifoBCount <= 16) {
|
if(soundDSFifoBCount <= 16) {
|
||||||
//cpuDmaHack2 =
|
cpuDmaHack2 = CPUCheckDMA(3, 4);
|
||||||
CPUCheckDMA(3, 4);
|
|
||||||
if(soundDSFifoBCount <= 16) {
|
if(soundDSFifoBCount <= 16) {
|
||||||
soundEvent(FIFOB_L, (u16)0);
|
soundEvent(FIFOB_L, (u16)0);
|
||||||
soundEvent(FIFOB_H, (u16)0);
|
soundEvent(FIFOB_H, (u16)0);
|
||||||
|
|
|
@ -998,7 +998,7 @@ void gbWriteMemory(register u16 address, register u8 value)
|
||||||
case 0x3d:
|
case 0x3d:
|
||||||
case 0x3e:
|
case 0x3e:
|
||||||
case 0x3f: {
|
case 0x3f: {
|
||||||
gbMemory[address] = value;
|
SOUND_EVENT(address,value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1783,6 +1783,11 @@ u8 gbReadMemory(register u16 address)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(address >= 0xff00) {
|
if(address >= 0xff00) {
|
||||||
|
|
||||||
|
if (address >= 0xFF10 && address <= 0xFF3F) {
|
||||||
|
return gbSoundRead(address);
|
||||||
|
}
|
||||||
|
|
||||||
switch(address & 0x00ff) {
|
switch(address & 0x00ff) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
{
|
{
|
||||||
|
@ -3527,6 +3532,8 @@ static bool gbWriteSaveState(gzFile gzFile)
|
||||||
utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01));
|
utilGzWrite(gzFile, &gbDataMMM01, sizeof(gbDataMMM01));
|
||||||
|
|
||||||
utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
|
utilGzWrite(gzFile, gbPalette, 128 * sizeof(u16));
|
||||||
|
|
||||||
|
for (int i = 0xFF10; i <= 0xFF3F; i++) gbMemory[i] = gbReadMemory(i);
|
||||||
|
|
||||||
utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000);
|
utilGzWrite(gzFile, &gbMemory[0x8000], 0x8000);
|
||||||
|
|
||||||
|
@ -3718,6 +3725,8 @@ static bool gbReadSaveState(gzFile gzFile)
|
||||||
|
|
||||||
utilGzRead(gzFile, &gbMemory[0x8000], 0x8000);
|
utilGzRead(gzFile, &gbMemory[0x8000], 0x8000);
|
||||||
|
|
||||||
|
for (int i = 0xFF10; i <= 0xFF3F; i++) gbSoundEvent(i, gbMemory[i]);
|
||||||
|
|
||||||
if(gbRamSize && gbRam) {
|
if(gbRamSize && gbRam) {
|
||||||
if (version < 11)
|
if (version < 11)
|
||||||
utilGzRead(gzFile, gbRam, gbRamSize);
|
utilGzRead(gzFile, gbRam, gbRamSize);
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
#include "gbGlobals.h"
|
#include "gbGlobals.h"
|
||||||
#include "gbSound.h"
|
#include "gbSound.h"
|
||||||
|
|
||||||
|
#include "../Gb_Apu/Multi_Buffer.h"
|
||||||
|
#include "../Gb_Apu/Gb_Apu.h"
|
||||||
|
|
||||||
extern u8 soundBuffer[6][735];
|
extern u8 soundBuffer[6][735];
|
||||||
extern u16 soundFinalWave[1470];
|
extern u16 soundFinalWave[1470];
|
||||||
extern int soundVolume;
|
extern int soundVolume;
|
||||||
|
@ -56,6 +59,9 @@ extern int soundBufferIndex;
|
||||||
int soundVIN = 0;
|
int soundVIN = 0;
|
||||||
extern int soundDebug;
|
extern int soundDebug;
|
||||||
|
|
||||||
|
extern Multi_Buffer * apu_out;
|
||||||
|
extern Gb_Apu * apu;
|
||||||
|
|
||||||
extern int sound1On;
|
extern int sound1On;
|
||||||
extern int sound1ATL;
|
extern int sound1ATL;
|
||||||
int sound1ATLreload;
|
int sound1ATLreload;
|
||||||
|
@ -132,7 +138,45 @@ extern bool soundLowPass;
|
||||||
extern bool soundReverse;
|
extern bool soundReverse;
|
||||||
extern bool soundOffFlag;
|
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)
|
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);
|
log("Sound event: %08lx %02x\n", address, data);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
switch(address) {
|
if (apu && address >= NR10 && address <= 0xFF3F)
|
||||||
case NR10:
|
{
|
||||||
gbMemory[address] = data | 0x80;
|
int clock = (SOUND_CLOCK_TICKS - soundTicks) * 95 / (24 * (gbSpeed ? 2 : 1));
|
||||||
sound1SweepATL = sound1SweepATLReload = 344 * ((data >> 4) & 7);
|
if (address == NR50)
|
||||||
sound1SweepSteps = data & 7;
|
{
|
||||||
sound1SweepUpDown = data & 0x08;
|
apu->write_register(clock, address, data);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
break;
|
else if (address == NR51)
|
||||||
case NR21:
|
{
|
||||||
gbMemory[address] = data | 0x3f;
|
soundBalance = data;
|
||||||
sound2Wave = soundWavePattern[data >> 6];
|
apu->write_register(clock, address, data & soundEnableFlag);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
case NR30:
|
apu->write_register(clock, address, data);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
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()
|
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()
|
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()
|
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()
|
void gbSoundMix()
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
if(soundBalance & 16) {
|
|
||||||
res += ((s8)soundBuffer[0][soundIndex]);
|
blip_sample_t out[2] = {0, 0};
|
||||||
}
|
|
||||||
if(soundBalance & 32) {
|
if ( ! apu_out ) return;
|
||||||
res += ((s8)soundBuffer[1][soundIndex]);
|
|
||||||
}
|
while (!apu_out->read_samples(&out[0], 2))
|
||||||
if(soundBalance & 64) {
|
{
|
||||||
res += ((s8)soundBuffer[2][soundIndex]);
|
int ticks = SOUND_CLOCK_TICKS * 95 / (24 * (gbSpeed ? 2 : 1));
|
||||||
}
|
bool was_stereo = apu->end_frame( ticks );
|
||||||
if(soundBalance & 128) {
|
apu_out->end_frame( ticks, was_stereo );
|
||||||
res += ((s8)soundBuffer[3][soundIndex]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gbDigitalSound)
|
res = out[0];
|
||||||
res *= soundLevel1*256;
|
|
||||||
else
|
//res = (res * 7 * 60) >> 8;
|
||||||
res *= soundLevel1*60;
|
|
||||||
|
|
||||||
if(soundEcho) {
|
if(soundEcho) {
|
||||||
res *= 2;
|
res *= 2;
|
||||||
|
@ -664,25 +285,7 @@ void gbSoundMix()
|
||||||
else
|
else
|
||||||
soundFinalWave[soundBufferIndex++] = res;
|
soundFinalWave[soundBufferIndex++] = res;
|
||||||
|
|
||||||
res = 0;
|
res = out[1];
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if(soundEcho) {
|
if(soundEcho) {
|
||||||
res *= 2;
|
res *= 2;
|
||||||
|
@ -734,10 +337,10 @@ void gbSoundTick()
|
||||||
{
|
{
|
||||||
if(systemSoundOn) {
|
if(systemSoundOn) {
|
||||||
if(soundMasterOn) {
|
if(soundMasterOn) {
|
||||||
gbSoundChannel1();
|
/*gbSoundChannel1();
|
||||||
gbSoundChannel2();
|
gbSoundChannel2();
|
||||||
gbSoundChannel3();
|
gbSoundChannel3();
|
||||||
gbSoundChannel4();
|
gbSoundChannel4();*/
|
||||||
|
|
||||||
gbSoundMix();
|
gbSoundMix();
|
||||||
} else {
|
} else {
|
||||||
|
@ -775,7 +378,7 @@ void gbSoundReset()
|
||||||
soundLevel2 = 7;
|
soundLevel2 = 7;
|
||||||
soundVIN = 0;
|
soundVIN = 0;
|
||||||
|
|
||||||
sound1On = 0;
|
/*sound1On = 0;
|
||||||
sound1ATL = 0;
|
sound1ATL = 0;
|
||||||
sound1Skip = 0;
|
sound1Skip = 0;
|
||||||
sound1Index = 0;
|
sound1Index = 0;
|
||||||
|
@ -821,53 +424,48 @@ void gbSoundReset()
|
||||||
sound4EnvelopeVolume = 0;
|
sound4EnvelopeVolume = 0;
|
||||||
sound4EnvelopeATL = 0;
|
sound4EnvelopeATL = 0;
|
||||||
sound4EnvelopeUpDown = 0;
|
sound4EnvelopeUpDown = 0;
|
||||||
sound4EnvelopeATLReload = 0;
|
sound4EnvelopeATLReload = 0;*/
|
||||||
|
|
||||||
// don't translate
|
// don't translate
|
||||||
if(soundDebug) {
|
if(soundDebug) {
|
||||||
log("*** Sound Init ***\n");
|
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);
|
if (apu_out)
|
||||||
gbSoundEvent(0xff1b, 0xff);
|
{
|
||||||
gbSoundEvent(0xff1c, 0xbf);
|
apu_out->clear();
|
||||||
gbSoundEvent(0xff1e, 0xbf);
|
apu->reset(false);
|
||||||
|
|
||||||
gbSoundEvent(0xff20, 0xff);
|
extern const BOOST::uint8_t sound_data[Gb_Apu::end_addr - Gb_Apu::start_addr + 1];
|
||||||
gbSoundEvent(0xff21, 0x00);
|
|
||||||
gbSoundEvent(0xff22, 0x00);
|
|
||||||
gbSoundEvent(0xff23, 0xbf);
|
|
||||||
gbSoundEvent(0xff24, 0x77);
|
|
||||||
gbSoundEvent(0xff25, 0xf3);
|
|
||||||
|
|
||||||
if (gbHardware & 0x4)
|
int addr = 0;
|
||||||
gbSoundEvent(0xff26, 0xf0);
|
|
||||||
else
|
while (addr < 0x30) {
|
||||||
gbSoundEvent(0xff26, 0xf1);
|
apu->write_register( 0, 0xFF10 + addr, sound_data [ addr ] );
|
||||||
|
addr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// don't translate
|
// don't translate
|
||||||
if(soundDebug) {
|
if(soundDebug) {
|
||||||
log("*** Sound Init Complete ***\n");
|
log("*** Sound Init Complete ***\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
sound1On = 0;
|
/*sound1On = 0;
|
||||||
sound2On = 0;
|
sound2On = 0;
|
||||||
sound3On = 0;
|
sound3On = 0;
|
||||||
sound4On = 0;
|
sound4On = 0;*/
|
||||||
|
|
||||||
int addr = 0xff30;
|
if (apu)
|
||||||
|
{
|
||||||
|
int addr = 0xff30;
|
||||||
|
|
||||||
while(addr < 0xff40) {
|
while(addr < 0xff40) {
|
||||||
gbMemory[addr++] = 0x00;
|
/*gbMemory[addr++] = 0x00;
|
||||||
gbMemory[addr++] = 0xff;
|
gbMemory[addr++] = 0xff;*/
|
||||||
|
gbSoundEvent(addr++, 0x00);
|
||||||
|
gbSoundEvent(addr++, 0xFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(soundFinalWave, 0x00, soundBufferLen);
|
memset(soundFinalWave, 0x00, soundBufferLen);
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define NR12 0xff12
|
#define NR12 0xff12
|
||||||
#define NR13 0xff13
|
#define NR13 0xff13
|
||||||
#define NR14 0xff14
|
#define NR14 0xff14
|
||||||
|
#define NR20 0xff15
|
||||||
#define NR21 0xff16
|
#define NR21 0xff16
|
||||||
#define NR22 0xff17
|
#define NR22 0xff17
|
||||||
#define NR23 0xff18
|
#define NR23 0xff18
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
#define NR32 0xff1c
|
#define NR32 0xff1c
|
||||||
#define NR33 0xff1d
|
#define NR33 0xff1d
|
||||||
#define NR34 0xff1e
|
#define NR34 0xff1e
|
||||||
|
#define NR40 0xff1f
|
||||||
#define NR41 0xff20
|
#define NR41 0xff20
|
||||||
#define NR42 0xff21
|
#define NR42 0xff21
|
||||||
#define NR43 0xff22
|
#define NR43 0xff22
|
||||||
|
@ -54,6 +56,8 @@ extern void gbSoundReadGame(int,gzFile);
|
||||||
extern void gbSoundEvent(register u16, register int);
|
extern void gbSoundEvent(register u16, register int);
|
||||||
extern void gbSoundSetQuality(int);
|
extern void gbSoundSetQuality(int);
|
||||||
|
|
||||||
|
extern u8 gbSoundRead(u16 address);
|
||||||
|
|
||||||
extern int soundTicks;
|
extern int soundTicks;
|
||||||
extern int soundQuality;
|
extern int soundQuality;
|
||||||
extern int SOUND_CLOCK_TICKS;
|
extern int SOUND_CLOCK_TICKS;
|
||||||
|
|
|
@ -32,7 +32,10 @@
|
||||||
|
|
||||||
// OpenGL
|
// OpenGL
|
||||||
#include <gl/GL.h> // main include file
|
#include <gl/GL.h> // main include file
|
||||||
|
#ifdef HAS_GLEXT
|
||||||
#include <gl/glext.h>
|
#include <gl/glext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int );
|
typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int );
|
||||||
|
|
||||||
extern int Init_2xSaI(u32);
|
extern int Init_2xSaI(u32);
|
||||||
|
|
Loading…
Reference in New Issue