LINK: Add AdaMN's work for reference
git-svn-id: https://svn.code.sf.net/p/vbam/code/branches/adamn-link@1140 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
parent
b2d9c51e5f
commit
ed7e1247b1
Binary file not shown.
|
@ -24,7 +24,7 @@
|
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseOfMfc>Static</UseOfMfc>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
|
@ -49,13 +49,13 @@
|
|||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)$(Platform)\$(Configuration)_temp\</IntDir>
|
||||
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</PreBuildEventUseInBuild>
|
||||
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreBuildEventUseInBuild>
|
||||
<PreLinkEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreLinkEventUseInBuild>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
|
||||
<PostBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PostBuildEventUseInBuild>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)$(Platform)\$(Configuration)_temp\</IntDir>
|
||||
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</PreBuildEventUseInBuild>
|
||||
<PreBuildEventUseInBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</PreBuildEventUseInBuild>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
|
||||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
|
||||
|
@ -66,9 +66,9 @@
|
|||
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
|
||||
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" />
|
||||
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Template|Win32'" />
|
||||
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\libs\Win32;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86;$(LibraryPath)</LibraryPath>
|
||||
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%programfiles%\OpenAL 1.1 SDK\libs\Win32;$(DXSDK_DIR)\lib\x86;$(LibraryPath)</LibraryPath>
|
||||
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\libs\Win32;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath)</IncludePath>
|
||||
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%programfiles%\OpenAL 1.1 SDK\include;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
|
||||
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Template|Win32'">C:\Program Files (x86)\OpenAL 1.1 SDK\include;C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include;$(IncludePath)</IncludePath>
|
||||
<IncludePath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%programfiles%\OpenAL 1.1 SDK\include;$(DXSDK_DIR)\Include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%programfiles%\OpenAL 1.1 SDK\libs\Win32;$(DXSDK_DIR)\lib\x86;$(LibraryPath)</LibraryPath>
|
||||
|
@ -100,7 +100,7 @@
|
|||
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<ProgramDataBaseFileName>$(IntDir)$(ProjectName).pdb</ProgramDataBaseFileName>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
</ClCompile>
|
||||
|
@ -124,6 +124,7 @@
|
|||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<MinimumRequiredVersion>5.0</MinimumRequiredVersion>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
|
@ -177,6 +178,7 @@
|
|||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
|
||||
</Link>
|
||||
<NASM>
|
||||
<Optimization>1</Optimization>
|
||||
|
@ -709,7 +711,7 @@
|
|||
</ImportGroup>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties RESOURCE_FILE="\Users\Shawn\Desktop\shuffle2proj\vba-m\src\win32\VBA.rc" />
|
||||
<UserProperties RESOURCE_FILE="" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
|
@ -61,6 +61,7 @@ extern int systemGetSensorY();
|
|||
extern bool systemCanChangeSoundQuality();
|
||||
extern void systemShowSpeed(int);
|
||||
extern void system10Frames(int);
|
||||
extern void system1Frames(int rate, int count);
|
||||
extern void systemFrame();
|
||||
extern void systemGbBorderOn();
|
||||
|
||||
|
@ -86,6 +87,9 @@ extern int systemFrameSkip;
|
|||
extern int systemSaveUpdateCounter;
|
||||
extern int systemSpeed;
|
||||
|
||||
extern int lastSA;
|
||||
extern int lastSR;
|
||||
|
||||
#define SYSTEM_SAVE_UPDATED 30
|
||||
#define SYSTEM_SAVE_NOT_UPDATED 0
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ License along with this module; if not, write to the Free Software Foundation,
|
|||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
#include "../system.h"
|
||||
|
||||
unsigned const vol_reg = 0xFF24;
|
||||
unsigned const stereo_reg = 0xFF25;
|
||||
|
@ -317,6 +318,9 @@ void Gb_Apu::write_register( blip_time_t time, unsigned addr, int data )
|
|||
{
|
||||
int old_data = regs [reg];
|
||||
regs [reg] = data;
|
||||
|
||||
//if(lastSA>=0x70 && lastSA<=0x75)
|
||||
//log("CH3 Addr:%04X = %04X Regs[%d]:%02X->%02X\n",lastSA,lastSR,reg,old_data,data);
|
||||
|
||||
if ( addr < vol_reg )
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@ inline void Gb_Osc::update_amp( blip_time_t time, int new_amp )
|
|||
{
|
||||
last_amp = new_amp;
|
||||
med_synth->offset( time, delta, output );
|
||||
//good_synth->offset( time, delta, output );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -280,12 +281,12 @@ inline void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int
|
|||
|
||||
switch ( reg )
|
||||
{
|
||||
case 0:
|
||||
case 0: //NR30
|
||||
if ( !dac_enabled() )
|
||||
enabled = false;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 1: //NR31
|
||||
length_ctr = max_len - data;
|
||||
break;
|
||||
|
||||
|
@ -571,9 +572,9 @@ void Gb_Noise::run( blip_time_t time, blip_time_t end_time )
|
|||
void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
|
||||
{
|
||||
// Calc volume
|
||||
static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
|
||||
static byte const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 }; //4 = 100%
|
||||
int const volume_shift = 2;
|
||||
int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB
|
||||
int const volume_idx = regs [2] >> 5 & (agb_mask | 3); // 2 bits on DMG/CGB, 3 on AGB //AdamN: osc.regs[2]=apu.regs[12] (NR32)
|
||||
int const volume_mul = volumes [volume_idx];
|
||||
|
||||
// Determine what will be generated
|
||||
|
@ -585,10 +586,10 @@ void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
|
|||
if ( dac_enabled() )
|
||||
{
|
||||
// Play inaudible frequencies as constant amplitude
|
||||
amp = 8 << 4; // really depends on average of all samples in wave
|
||||
amp = 8 << 4; // really depends on average of all samples in wave //AdamN: can we use this->last_amp instead?
|
||||
|
||||
// if delay is larger, constant amplitude won't start yet
|
||||
if ( frequency() <= 0x7FB || delay > 15 * clk_mul )
|
||||
if ( frequency() <= 0x7FB || delay > 15 * clk_mul ) //2043
|
||||
{
|
||||
if ( volume_mul )
|
||||
playing = (int) enabled;
|
||||
|
@ -609,13 +610,14 @@ void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
|
|||
|
||||
// wave size and bank
|
||||
int const size20_mask = 0x20;
|
||||
int const flags = regs [0] & agb_mask;
|
||||
int const wave_mask = (flags & size20_mask) | 0x1F;
|
||||
int const flags = regs [0] & agb_mask; //AdamN: osc.regs[0]=apu.regs[10] (NR30)
|
||||
int const wave_mask = (flags & size20_mask) | 0x1F; //AdamN: Bank Dimension
|
||||
int swap_banks = 0;
|
||||
if ( flags & bank40_mask )
|
||||
if ( flags & bank40_mask ) //AdamN: Bank 1
|
||||
{
|
||||
swap_banks = flags & size20_mask;
|
||||
swap_banks = flags & size20_mask; //AdamN: Bank Dimension, swap_banks = Use 2 Banks (64 digits)
|
||||
wave += bank_size/2 - (swap_banks >> 1);
|
||||
//wave = &this->wave_ram[bank_size/2 - (swap_banks >> 1)];
|
||||
}
|
||||
|
||||
int ph = this->phase ^ swap_banks;
|
||||
|
@ -640,13 +642,14 @@ void Gb_Wave::run( blip_time_t time, blip_time_t end_time )
|
|||
ph = (ph + 1) & wave_mask;
|
||||
|
||||
// Scale by volume
|
||||
int amp = (nybble * volume_mul) >> (volume_shift + 4);
|
||||
int amp = (nybble * volume_mul) >> (volume_shift + 4); //AdamN: should we use +dac_bias in here?
|
||||
|
||||
int delta = amp - lamp;
|
||||
if ( delta )
|
||||
{
|
||||
lamp = amp;
|
||||
med_synth->offset_inline( time, delta, out );
|
||||
//good_synth->offset_inline( time, delta, out );
|
||||
}
|
||||
time += per;
|
||||
}
|
||||
|
|
|
@ -165,11 +165,11 @@ private:
|
|||
int period() const { return (2048 - frequency()) * (2 * clk_mul); }
|
||||
|
||||
// Non-zero if DAC is enabled
|
||||
int dac_enabled() const { return regs [0] & 0x80; }
|
||||
int dac_enabled() const { return regs [0] & 0x80; } //AdamN: osc.regs[0]=apu.regs[10]
|
||||
|
||||
void corrupt_wave();
|
||||
|
||||
BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; }
|
||||
BOOST::uint8_t* wave_bank() const { return &wave_ram [(~regs [0] & bank40_mask) >> 2 & agb_mask]; } //AdamN: osc.regs[0]=apu.regs[10]
|
||||
|
||||
// Wave index that would be accessed, or -1 if no access would occur
|
||||
int access( unsigned addr ) const;
|
||||
|
|
170
src/gb/GB.cpp
170
src/gb/GB.cpp
|
@ -14,6 +14,8 @@
|
|||
#include "gbSGB.h"
|
||||
#include "gbSound.h"
|
||||
#include "../Util.h"
|
||||
#include "../gba/GBALink.h"
|
||||
//#include "../gba/Globals.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _stricmp strcasecmp
|
||||
|
@ -790,16 +792,81 @@ void gbWriteMemory(register u16 address, register u8 value)
|
|||
}
|
||||
|
||||
case 0x01: {
|
||||
#ifdef GBA_LOGGING
|
||||
if(gbMemory[0xff01]!=value)
|
||||
if(systemVerbose & VERBOSE_SIO) {
|
||||
log("SioSB(%04X) : %02X %02X->%02X %d\n", PC.W-2, gbMemory[0xff02], gbMemory[0xff01], value, GetTickCount() ); //register_LY
|
||||
}
|
||||
#endif
|
||||
gbMemory[0xff01] = value;
|
||||
//if(value==0xff/*0x00*/) LinkFirstTime = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// serial control
|
||||
case 0x02: {
|
||||
#ifdef GBA_LOGGING
|
||||
if(gbMemory[0xff02]!=value)
|
||||
if(systemVerbose & VERBOSE_SIO) {
|
||||
log("SioSC(%04X) : %02X->%02X %02X %d\n", PC.W-2, gbMemory[0xff02], value, gbMemory[0xff01], GetTickCount() ); //register_LY
|
||||
}
|
||||
#endif
|
||||
gbSerialOn = (value & 0x80);
|
||||
//if(gba_link_enabled && lanlink.connected)
|
||||
if( EmuReseted ||(gbMemory[0xff02] & 0x7c)||(value & 0x7c)||(!(value & 0x81)) ) { //trying to detect whether the game has exited multiplay mode, pokemon blue start w/ 0x7e while pocket racing start w/ 0x7c
|
||||
LinkFirstTime = true;
|
||||
if( EmuReseted ||(gbMemory[0xff02] & 0x7c)||(value & 0x7c) )
|
||||
if(lanlink.connected)
|
||||
if(linkid) lc.DiscardData();
|
||||
else ls.DiscardData(1);
|
||||
}
|
||||
EmuReseted = false;
|
||||
gbMemory[0xff02] = value;
|
||||
if(gbSerialOn) {
|
||||
gbSerialTicks = GBSERIAL_CLOCK_TICKS;
|
||||
|
||||
LinkIsWaiting = true;
|
||||
|
||||
//Do data exchange, master initiate the transfer
|
||||
//may cause visual artifact if not processed immediately, is it due to IRQ stuff or invalid data being exchanged?
|
||||
if( (value & 1) /*|| (!LinkFirstTime)*/ ) { //&& !linkid //internal clock
|
||||
if(gbSerialFunction) {
|
||||
gbSIO_SC = value;
|
||||
LogStrPush("gbWrite");
|
||||
//if(linkid /*&& (value & 1)*/) {gbMemory[0xff01] = 0xff; LinkFirstTime = true;} else
|
||||
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); //gbSerialFunction/gbStartLink/gbPrinter
|
||||
LogStrPop(7);
|
||||
} else gbMemory[0xff01]=0xff;
|
||||
//gbSerialTicks = GBSERIAL_CLOCK_TICKS; //1; //0; //wrong value in gbSerialTicks could cause visual artifact
|
||||
gbMemory[0xff02] &= 0x7f;
|
||||
gbSerialOn = 0;
|
||||
//if(register_IE & 8)
|
||||
gbMemory[0xff0f] = register_IF |= 8;
|
||||
//gbSerialBits = 0;
|
||||
//LinkFirstTime = false;
|
||||
//if(!(value & 1)) LinkFirstTime = true;
|
||||
} /*else //external clock
|
||||
{
|
||||
u16 dat = 0;
|
||||
//if(gbSerialFunction)
|
||||
{
|
||||
gbSIO_SC = value;
|
||||
LogStrPush("gbWrite");
|
||||
dat = gbLinkUpdate(gbMemory[0xff01]);
|
||||
gbMemory[0xff01] = (dat >> 8); //gbSerialFunction/gbStartLink/gbPrinter
|
||||
LogStrPop(7);
|
||||
}
|
||||
if(dat & 1) {
|
||||
//gbSerialTicks = GBSERIAL_CLOCK_TICKS; //1; //0; //wrong value in gbSerialTicks could cause visual artifact
|
||||
gbMemory[0xff02] &= 0x7f;
|
||||
gbSerialOn = 0;
|
||||
//if(register_IE & 8)
|
||||
gbMemory[0xff0f] = register_IF |= 8;
|
||||
//gbSerialBits = 0;
|
||||
//LinkFirstTime = false;
|
||||
//if(!(value & 1)) LinkFirstTime = true;
|
||||
}
|
||||
}*/
|
||||
#ifdef OLD_GB_LINK
|
||||
if(linkConnected) {
|
||||
if(value & 1) {
|
||||
|
@ -2174,6 +2241,8 @@ void gbGetHardwareType()
|
|||
|
||||
void gbReset()
|
||||
{
|
||||
EmuReseted = true;
|
||||
LinkFirstTime = true;
|
||||
gbGetHardwareType();
|
||||
|
||||
oldRegister_WY = 146;
|
||||
|
@ -4487,6 +4556,8 @@ void gbDrawLine()
|
|||
|
||||
void gbEmulate(int ticksToStop)
|
||||
{
|
||||
if(EmuCtr>0) {log("Emu inside Emu:%d\n",EmuCtr);return;}
|
||||
|
||||
gbRegister tempRegister;
|
||||
u8 tempValue;
|
||||
s8 offset;
|
||||
|
@ -4916,8 +4987,9 @@ void gbEmulate(int ticksToStop)
|
|||
gbFrameCount++;
|
||||
systemFrame();
|
||||
|
||||
if((gbFrameCount % 10) == 0)
|
||||
system10Frames(60);
|
||||
/*if((gbFrameCount % 10) == 0)
|
||||
system10Frames(60);*/
|
||||
system1Frames(60, gbFrameCount);
|
||||
|
||||
if(gbFrameCount >= 60) {
|
||||
u32 currentTime = systemGetClock();
|
||||
|
@ -5186,8 +5258,9 @@ void gbEmulate(int ticksToStop)
|
|||
|
||||
systemFrame();
|
||||
|
||||
if((gbFrameCount % 10) == 0)
|
||||
system10Frames(60);
|
||||
/*if((gbFrameCount % 10) == 0)
|
||||
system10Frames(60);*/
|
||||
system1Frames(60, gbFrameCount);
|
||||
|
||||
if(gbFrameCount >= 60) {
|
||||
u32 currentTime = systemGetClock();
|
||||
|
@ -5206,7 +5279,33 @@ void gbEmulate(int ticksToStop)
|
|||
gbMemory[0xff41] = register_STAT;
|
||||
|
||||
// serial emulation
|
||||
if(gbSerialOn) {
|
||||
gbSerialOn = (gbMemory[0xff02] & 0x80);
|
||||
/*if(gba_link_enabled && lanlink.connected && (register_LY>=144)) {
|
||||
//if(gbSerialOn)
|
||||
{
|
||||
u16 dat = 0;
|
||||
if(gbSerialFunction) { // external device
|
||||
gbSIO_SC = gbMemory[0xff02];
|
||||
LogStrPush("gbEmu");
|
||||
if(!LinkFirstTime) dat = (gbSerialFunction(gbMemory[0xff01]) << 8) | 1; else
|
||||
dat = gbLinkUpdate(gbMemory[0xff01]);
|
||||
gbMemory[0xff01] = (dat >> 8);
|
||||
LogStrPop(5);
|
||||
if(gbSerialOn && (dat & 1)) {
|
||||
gbMemory[0xff02] &= 0x7f;
|
||||
gbSerialOn = 0;
|
||||
//if(register_IE & 8)
|
||||
gbMemory[0xff0f] = register_IF |= 8;
|
||||
}
|
||||
} //else gbMemory[0xff01] = 0xff;
|
||||
}
|
||||
gbSerialTicks = 1; //GBSERIAL_CLOCK_TICKS; //0; //seems to cause varies visual artifact if gbSerialTicks value isn't right
|
||||
gbSerialBits = 0;
|
||||
}*/
|
||||
static int SIOctr = 0;
|
||||
SIOctr++;
|
||||
if(!lanlink.speed || (SIOctr % 5))
|
||||
if(gbSerialOn) { //Transfer Started
|
||||
#ifdef OLD_GB_LINK
|
||||
if(linkConnected) {
|
||||
gbSerialTicks -= clockTicks;
|
||||
|
@ -5229,7 +5328,7 @@ void gbEmulate(int ticksToStop)
|
|||
}
|
||||
} else {
|
||||
#endif
|
||||
if(gbMemory[0xff02] & 1) {
|
||||
if(gbMemory[0xff02] & 1) { //internal clocks (master)
|
||||
gbSerialTicks -= clockTicks;
|
||||
|
||||
// overflow
|
||||
|
@ -5238,21 +5337,66 @@ void gbEmulate(int ticksToStop)
|
|||
// gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
|
||||
// increment number of shifted bits
|
||||
gbSerialBits++;
|
||||
if(gbSerialBits == 8) {
|
||||
if(gbSerialBits >= 8) {
|
||||
// end of transmission
|
||||
if(gbSerialFunction) // external device
|
||||
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]);
|
||||
else
|
||||
gbMemory[0xff01] = 0xff;
|
||||
gbSerialTicks = 0;
|
||||
/*if(gbSerialFunction) { // external device
|
||||
gbSIO_SC = gbMemory[0xff02];
|
||||
LogStrPush("gbEmu");
|
||||
gbMemory[0xff01] = gbSerialFunction(gbMemory[0xff01]); //gbStartLik/gbPrinter
|
||||
LogStrPop(5);
|
||||
LinkFirstTime = false;
|
||||
} else
|
||||
gbMemory[0xff01] = 0xff;*/
|
||||
gbSerialTicks = 0;
|
||||
//if(!linkid)
|
||||
/*{
|
||||
gbMemory[0xff02] &= 0x7f;
|
||||
gbSerialOn = 0;
|
||||
gbMemory[0xff0f] = register_IF |= 8;
|
||||
}*/
|
||||
gbSerialBits = 0;
|
||||
} else
|
||||
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
||||
}
|
||||
}
|
||||
} else //external clocks (slave)
|
||||
{
|
||||
gbSerialTicks -= clockTicks;
|
||||
|
||||
// overflow
|
||||
while(gbSerialTicks <= 0) {
|
||||
// shift serial byte to right and put a 1 bit in its place
|
||||
// gbMemory[0xff01] = 0x80 | (gbMemory[0xff01]>>1);
|
||||
// increment number of shifted bits
|
||||
gbSerialBits++;
|
||||
if(gbSerialBits >= 8) {
|
||||
// end of transmission
|
||||
u16 dat = 0;
|
||||
if(!LinkIsWaiting) {
|
||||
if(lanlink.connected)
|
||||
if(linkid) lc.DiscardData();
|
||||
else ls.DiscardData(1);
|
||||
} else
|
||||
if(gbSerialFunction) { // external device
|
||||
gbSIO_SC = gbMemory[0xff02];
|
||||
LogStrPush("gbEmu");
|
||||
if(!LinkFirstTime) dat = (gbSerialFunction(gbMemory[0xff01]) << 8) | 1; else //external clock not suppose to start a transfer, but there are time where both side using external clock and couldn't communicate properly
|
||||
dat = gbLinkUpdate(gbMemory[0xff01]);
|
||||
gbMemory[0xff01] = (dat >> 8);
|
||||
LogStrPop(5);
|
||||
} //else
|
||||
//gbMemory[0xff01] = 0xff;
|
||||
gbSerialTicks = 0;
|
||||
if(dat & 1) //if(linkid)
|
||||
{
|
||||
gbMemory[0xff02] &= 0x7f;
|
||||
gbSerialOn = 0;
|
||||
gbMemory[0xff0f] = register_IF |= 8;
|
||||
}
|
||||
gbSerialBits = 0;
|
||||
} else
|
||||
gbSerialTicks += GBSERIAL_CLOCK_TICKS;
|
||||
}
|
||||
}
|
||||
#ifdef OLD_GB_LINK
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef GBGLOBALS_H
|
||||
#define GBGLOBALS_H
|
||||
|
||||
#define VERBOSE_SIO 2048
|
||||
|
||||
extern int gbRomSizeMask;
|
||||
extern int gbRomSize;
|
||||
extern int gbRamSize;
|
||||
|
|
|
@ -657,7 +657,7 @@ static void count(u32 opcode, int cond_res)
|
|||
#define OP_MVN \
|
||||
EMIT1(not, eax) \
|
||||
EMIT2(mov, eax, REGREF1(esi))
|
||||
#define OP_MVNS CHECK_PC(OP_MVN EMIT2(test,eax,eax), SETCOND_LOGICAL)
|
||||
#define OP_MVNS CHECK_PC(OP_MVN EMIT2(test,eax,eax), SETCOND_LOGICAL) //AdamN: NOT eax doesn't affect any flags in x86 so need to add TEST for SETCOND_LOGICAL to works properly
|
||||
|
||||
// ALU cleanup macro
|
||||
#define ALU_FINISH ALU_TRAILER
|
||||
|
|
387
src/gba/GBA.cpp
387
src/gba/GBA.cpp
|
@ -22,6 +22,10 @@
|
|||
#include "agbprint.h"
|
||||
#include "GBALink.h"
|
||||
|
||||
#ifdef _MSC_VER //#ifdef _WIN32
|
||||
#include "../Win32/WinHelper.h" // AdamN: for CCriticalSection
|
||||
#endif
|
||||
|
||||
#ifdef PROFILING
|
||||
#include "prof/prof.h"
|
||||
#endif
|
||||
|
@ -32,6 +36,8 @@
|
|||
|
||||
extern int emulating;
|
||||
|
||||
extern bool AppTerminated = false;
|
||||
|
||||
int SWITicks = 0;
|
||||
int IRQTicks = 0;
|
||||
|
||||
|
@ -59,6 +65,9 @@ bool cpuFlashEnabled = true;
|
|||
bool cpuEEPROMEnabled = true;
|
||||
bool cpuEEPROMSensorEnabled = false;
|
||||
|
||||
bool breakpt = false;
|
||||
u32 breakaddr = 0xffffffff;
|
||||
|
||||
u32 cpuPrefetch[2];
|
||||
|
||||
int cpuTotalTicks = 0;
|
||||
|
@ -815,7 +824,7 @@ static bool CPUReadState(gzFile gzFile)
|
|||
THUMB_PREFETCH;
|
||||
}
|
||||
|
||||
CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
|
||||
CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204)); //WAITCNT
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1779,7 +1788,8 @@ void CPUSoftwareInterrupt(int comment)
|
|||
#endif
|
||||
if(useBios) {
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
//if(comment>0x2A) //AdamN: what is the idea of flooding the log with all interrupts?? having a stats showing how many times each interrupt being called might be more usefull than flooding
|
||||
if(systemVerbose & VERBOSE_SWI) { //AdamN: trying to capture only the impossible (should be logged even when logging not enabled tho)
|
||||
log("SWI: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
|
||||
armState ? armNextPC - 4: armNextPC -2,
|
||||
reg[0].I,
|
||||
|
@ -1827,31 +1837,31 @@ void CPUSoftwareInterrupt(int comment)
|
|||
stopState = true;
|
||||
cpuNextEvent = cpuTotalTicks;
|
||||
break;
|
||||
case 0x04:
|
||||
case 0x04: //AdamN: IntrWait
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("IntrWait: 0x%08x,0x%08x (VCOUNT = %2d)\n",
|
||||
reg[0].I,
|
||||
reg[1].I,
|
||||
reg[1].I, //AdamN: Interrupt flag(s) to wait for (same format as IE/IF registers)
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
CPUSoftwareInterrupt();
|
||||
CPUSoftwareInterrupt(); //AdamN: Forcefully sets IME=1 and wait in Halt state until one (or more) of the specified interrupt(s) occurs.
|
||||
break;
|
||||
case 0x05:
|
||||
case 0x05: //AdamN: this VBlankIntrWait oftenly called (every 1/60 sec) so it should be handled properly
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("VBlankIntrWait: (VCOUNT = %2d)\n",
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
CPUSoftwareInterrupt();
|
||||
CPUSoftwareInterrupt(); //AdamN: set r0=1,r1=1 then execute IntrWait
|
||||
break;
|
||||
case 0x06:
|
||||
CPUSoftwareInterrupt();
|
||||
case 0x06: //AdamN: Div oftenly called so it should be handled properly
|
||||
BIOS_Div(); //CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x07:
|
||||
CPUSoftwareInterrupt();
|
||||
case 0x07: //AdamN: DivArm
|
||||
BIOS_DivARM(); //CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x08:
|
||||
BIOS_Sqrt();
|
||||
|
@ -1862,7 +1872,7 @@ void CPUSoftwareInterrupt(int comment)
|
|||
case 0x0A:
|
||||
BIOS_ArcTan2();
|
||||
break;
|
||||
case 0x0B:
|
||||
case 0x0B: //AdamN: CpuSet oftenly called so it should be handled properly
|
||||
{
|
||||
int len = (reg[2].I & 0x1FFFFF) >>1;
|
||||
if (!(((reg[0].I & 0xe000000) == 0) ||
|
||||
|
@ -1888,7 +1898,7 @@ void CPUSoftwareInterrupt(int comment)
|
|||
}
|
||||
BIOS_CpuSet();
|
||||
break;
|
||||
case 0x0C:
|
||||
case 0x0C: //AdamN: CpuFastSet oftenly called so it should be handled properly
|
||||
{
|
||||
int len = (reg[2].I & 0x1FFFFF) >>5;
|
||||
if (!(((reg[0].I & 0xe000000) == 0) ||
|
||||
|
@ -2005,7 +2015,7 @@ void CPUSoftwareInterrupt(int comment)
|
|||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("SoundBiasSet: 0x%08x (VCOUNT = %2d)\n",
|
||||
reg[0].I,
|
||||
reg[0].I, //AdamN: r0=BIAS Level (0=Level 000h, any other value=Level 200h), r1=Delay Count on NDS (GBA uses a fixed delay count of 8)
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
|
@ -2014,15 +2024,152 @@ void CPUSoftwareInterrupt(int comment)
|
|||
else
|
||||
soundResume();
|
||||
break;
|
||||
/*case 0x1A: //AdamN: SoundDriverInit, calling sequences after SoundDriverInit then SoundChannelClear then SoundDriverMode, then repeated SoundDriverVSync+SoundDriverMain
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("SoundDriverInit: 0x%08x (VCOUNT = %2d)\n",
|
||||
reg[0].I, //AdamN: Pointer to SoundArea structure
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
CPUSoftwareInterrupt();
|
||||
break;*/
|
||||
case 0x1B: //AdamN: SoundDriverMode
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("SoundDriverMode: 0x%08x (VCOUNT = %2d)\n",
|
||||
reg[0].I, //AdamN: Sound driver operation mode
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
//CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x1C: //AdamN: SoundDriverMain (no param)
|
||||
//CPUSoftwareInterrupt(); //AdamN: Call (using/after SoundDriverVSync) every 1/60 of a second, immediately after the V-Blank interrupt. After that, this routine is called after BG and OBJ processing is executed.
|
||||
break;
|
||||
case 0x1D: //AdamN: SoundDriverVSync
|
||||
//CPUSoftwareInterrupt(); //AdamN: Resets the sound DMA (no param) to sync the BIOS sound driver
|
||||
break;
|
||||
case 0x1E: //AdamN: SoundChannelClear
|
||||
//CPUSoftwareInterrupt(); //AdamN: Clears all direct sound channels and stops the sound (no param)
|
||||
break;
|
||||
case 0x1F:
|
||||
BIOS_MidiKey2Freq();
|
||||
break;
|
||||
case 0x2A:
|
||||
case 0x20: //AdamN: SoundWhatever0/MusicPlayerOpen
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("MusicPlayerOpen: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
|
||||
armState ? armNextPC - 4: armNextPC -2,
|
||||
reg[0].I,
|
||||
reg[1].I,
|
||||
reg[2].I,
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
//CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x21: //AdamN: SoundWhatever1/MusicPlayerStart
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("MusicPlayerStart: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
|
||||
armState ? armNextPC - 4: armNextPC -2,
|
||||
reg[0].I,
|
||||
reg[1].I,
|
||||
reg[2].I,
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
//CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x22: //AdamN: SoundWhatever2/MusicPlayerStop
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("MusicPlayerStop: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
|
||||
armState ? armNextPC - 4: armNextPC -2,
|
||||
reg[0].I,
|
||||
reg[1].I,
|
||||
reg[2].I,
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
//CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x23: //AdamN: SoundWhatever3/MusicPlayerContinue
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("MusicPlayerContinue: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
|
||||
armState ? armNextPC - 4: armNextPC -2,
|
||||
reg[0].I,
|
||||
reg[1].I,
|
||||
reg[2].I,
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
//CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x24: //AdamN: SoundWhatever4/MusicPlayerFadeOut
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("MusicPlayerFadeOut: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
|
||||
armState ? armNextPC - 4: armNextPC -2,
|
||||
reg[0].I,
|
||||
reg[1].I,
|
||||
reg[2].I,
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
//CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x25: //AdamN: MultiBoot
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("MultiBoot: 0x%08x,0x%08x (VCOUNT = %2d)\n",
|
||||
reg[0].I, //AdamN: Pointer to MultiBootParam structure
|
||||
reg[1].I, //AdamN: Transfer Mode
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
//CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x26: //AdamN: HardReset
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("HardReset: (VCOUNT = %2d)\n",
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
CPUSoftwareInterrupt(); //Fully reset to Nintendo intro (no param)
|
||||
break;
|
||||
case 0x27: //AdamN: CustomHalt
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("CustomHalt: 0x%08x (VCOUNT = %2d)\n",
|
||||
reg[2].I, //AdamN: 8bit param (00h=Halt, 80h=Stop)
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
CPUSoftwareInterrupt();
|
||||
break;
|
||||
case 0x28: //AdamN: SoundDriverVSyncOff
|
||||
//CPUSoftwareInterrupt(); //AdamN: Stop sound DMA (no param) to prevent sound DMA from overflowing and playing noise when the game loading (as SoundDriverVSync might missed the 1/60sec interval)
|
||||
break;
|
||||
case 0x29: //AdamN: SoundDriverVSyncOn
|
||||
//CPUSoftwareInterrupt(); //AdamN: Restarts the sound DMA stopped with SoundDriverVSyncOff (no param) to restore sound driver operation
|
||||
break;
|
||||
case 0x2A: //AdamN: SoundGetJumpList
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("SoundGetJumpList: 0x%08x (VCOUNT = %2d)\n",
|
||||
reg[0].I, //AdamN: Destination address (must be aligned by 4) (120h bytes buffer)
|
||||
VCOUNT);
|
||||
}
|
||||
#endif
|
||||
BIOS_SndDriverJmpTableCopy();
|
||||
// let it go, because we don't really emulate this function
|
||||
default:
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
if(systemVerbose & VERBOSE_SWI) {
|
||||
log("SWI: %08x at %08x (0x%08x,0x%08x,0x%08x,VCOUNT = %2d)\n", comment,
|
||||
armState ? armNextPC - 4: armNextPC -2,
|
||||
reg[0].I,
|
||||
|
@ -2034,11 +2181,12 @@ void CPUSoftwareInterrupt(int comment)
|
|||
|
||||
if(!disableMessage) {
|
||||
systemMessage(MSG_UNSUPPORTED_BIOS_FUNCTION,
|
||||
N_("Unsupported BIOS function %02x called from %08x. A BIOS file is needed in order to get correct behaviour."),
|
||||
N_("Unsupported BIOS Function %02X called from %08x. A BIOS file is needed in order to get correct behaviour."),
|
||||
comment,
|
||||
armMode ? armNextPC - 4: armNextPC - 2);
|
||||
disableMessage = true;
|
||||
}
|
||||
//CPUSoftwareInterrupt(); //AdamN: not needed as it could cause the game to stop when there are no bios file
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2405,7 +2553,10 @@ void CPUUpdateRegister(u32 address, u16 value)
|
|||
{
|
||||
case 0x00:
|
||||
{ // we need to place the following code in { } because we declare & initialize variables in a case statement
|
||||
if((value & 7) > 5) {
|
||||
/*if((value & 4)&&((DISPCNT & 0x0010)!=(value & 0x0010))) {
|
||||
log("DISPCNT(%08x) : %04X->%04X %04X R0=%08X R1=%08X R2=%08X R14=%08X Z=%d (VCOUNT = %d)\n", armState ? armNextPC - 4: armNextPC -2, DISPCNT, value, DISPSTAT, reg[0].I, reg[1].I, reg[2].I, reg[14].I, Z_FLAG, VCOUNT);
|
||||
}*/
|
||||
if((value & 7) > 5) {
|
||||
// display modes above 0-5 are prohibited
|
||||
DISPCNT = (value & 7);
|
||||
}
|
||||
|
@ -2626,7 +2777,11 @@ void CPUUpdateRegister(u32 address, u16 value)
|
|||
case 0x7c:
|
||||
case 0x80:
|
||||
case 0x84:
|
||||
lastSR = value & 0xFF;
|
||||
lastSA = address&0xFF;
|
||||
soundEvent(address&0xFF, (u8)(value & 0xFF));
|
||||
lastSR = value >> 8;
|
||||
lastSA = (address&0xFF)+1;
|
||||
soundEvent((address&0xFF)+1, (u8)(value>>8));
|
||||
break;
|
||||
case 0x82:
|
||||
|
@ -2643,6 +2798,8 @@ void CPUUpdateRegister(u32 address, u16 value)
|
|||
case 0x9a:
|
||||
case 0x9c:
|
||||
case 0x9e:
|
||||
lastSR = value;
|
||||
lastSA = address&0xFF;
|
||||
soundEvent(address&0xFF, value);
|
||||
break;
|
||||
case 0xB0:
|
||||
|
@ -2822,16 +2979,79 @@ void CPUUpdateRegister(u32 address, u16 value)
|
|||
timerOnOffDelay|=8;
|
||||
cpuNextEvent = cpuTotalTicks;
|
||||
break;
|
||||
|
||||
|
||||
case COMM_SIODATA32_L:
|
||||
if(READ16LE(&ioMem[COMM_SIODATA32_L]) != value) {
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SIO) {
|
||||
log("SIODATAL(%d) : %04X %04X %04X->%04X %04X %04X %04X %04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), value, READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), VCOUNT );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
UPDATE_REG(COMM_SIODATA32_L, value);
|
||||
break;
|
||||
case COMM_SIODATA32_H:
|
||||
if(READ16LE(&ioMem[COMM_SIODATA32_H]) != value) {
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SIO) {
|
||||
log("SIODATAH(%d) : %04X %04X %04X %04X->%04X %04X %04X %04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), value, READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), VCOUNT );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
UPDATE_REG(COMM_SIODATA32_H, value);
|
||||
break;
|
||||
case COMM_SIOCNT:
|
||||
if(READ16LE(&ioMem[COMM_SIOCNT]) != (/*READ16LE(&ioMem[COMM_SIOCNT]) &*/ value)) {
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SIO) {
|
||||
if(value & 0x4000)
|
||||
log("SIOCNT(%08x) : %04X %04X->%04X %04X %04X %04X %04X %04X (VCOUNT = %d)\n", armState ? armNextPC - 4: armNextPC -2, READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), value, READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), VCOUNT );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if( EmuReseted ) { //trying to detect whether the game has exited multiplay mode (ie. game restarted)
|
||||
EmuReseted = false;
|
||||
LinkFirstTime = true;
|
||||
if(lanlink.connected)
|
||||
if(linkid) lc.DiscardData();
|
||||
else ls.DiscardData(1);
|
||||
}
|
||||
//UPDATE_REG(COMM_SIOCNT, value);
|
||||
lanlink.mode = GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]));
|
||||
if(lanlink.mode!=GetSIOMode(READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_RCNT]))) LinkFirstTime = true;
|
||||
StartLink(value);
|
||||
/*switch (GetSIOMode(value, READ16LE(&ioMem[COMM_RCNT]))) {
|
||||
case MULTIPLAYER:
|
||||
if(LinkHandlerActive) {
|
||||
if (value & 0x80) { //AdamN: Start/Busy Bit.7=1 (Active/Transfering)
|
||||
LinkCmdQueue(1,value);
|
||||
c_s.Lock(); //AdamN: Locking resource to prevent deadlock
|
||||
//UPDATE_REG(COMM_SIOCNT, value); //AdamN: when using socket handler SIOCNT need to be updated as soon as possible because program might be reading it and ORing it for the next update
|
||||
LinkParam1=value;
|
||||
LinkCommand|=1; //AdamN: StartLink command
|
||||
c_s.Unlock(); //AdamN: Locking resource to prevent deadlock
|
||||
} else UPDATE_REG(COMM_SIOCNT, value);
|
||||
} else {
|
||||
LogStrPush("CPUUpdReg");
|
||||
//UPDATE_REG(COMM_SIOCNT, value); //just for testing the effect
|
||||
if (value & 0x80) { //AdamN: Start/Busy Bit.7=1 (Active/Transfering)
|
||||
StartLink(value); //AdamN: using blocking sockets here can cause noticibly delays
|
||||
} else UPDATE_REG(COMM_SIOCNT, value);
|
||||
LogStrPop(9);
|
||||
}
|
||||
break;
|
||||
case NORMAL8:
|
||||
case NORMAL32:
|
||||
case UART:
|
||||
default:
|
||||
UPDATE_REG(COMM_SIOCNT, value);
|
||||
break;
|
||||
} */
|
||||
/*
|
||||
// old code path for no linking...
|
||||
{
|
||||
if (value & 0x80) {
|
||||
if (value & 0x80) { //Start bit.7
|
||||
value &= 0xff7f;
|
||||
if ((value & 1) && (value & 0x4000)) {
|
||||
if ((value & 1) && (value & 0x4000)) { //IRQ Enable bit.14
|
||||
UPDATE_REG(COMM_SIODATA8, 0xFF);
|
||||
IF |= 0x80;
|
||||
UPDATE_REG(0x202, IF);
|
||||
|
@ -2843,24 +3063,65 @@ void CPUUpdateRegister(u32 address, u16 value)
|
|||
*/
|
||||
break;
|
||||
|
||||
case COMM_SIODATA8:
|
||||
if (gba_link_enabled)
|
||||
LinkSSend(value);
|
||||
UPDATE_REG(COMM_RCNT, value);
|
||||
case COMM_SIODATA8: //AdamN: 8bit(SIODATA8) on Normal/UART(up to 4x8bit with FIFO), 16bit(SIOMLT_SEND) on Multiplayer mode
|
||||
if(READ16LE(&ioMem[COMM_SIOMLT_SEND]) != (/*READ16LE(&ioMem[COMM_SIOMLT_SEND]) &*/ value)) {
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SIO) {
|
||||
log("SIODATA(%d) : %04X %04X %04X %04X %04X %04X %04X->%04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), READ16LE(&ioMem[COMM_SIOMLT_SEND]), value, VCOUNT );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
UPDATE_REG(COMM_SIODATA8, value); //COMM_SIOMLT_SEND
|
||||
/*if (gba_link_enabled && lanlink.connected) //AdamN: added active connection checking, don't send any packet if there are no connection
|
||||
LinkSSend(value); //AdamN: Does sending packet really needed in this part?(as transfers are initiated by SIOCNT)
|
||||
UPDATE_REG(COMM_RCNT, value); //AdamN: is this really necessary?? seems to break connection
|
||||
*/
|
||||
/*if(linkid && (READ16LE(&ioMem[COMM_SIOMLT_SEND]) & 0x3f)==0x0f) {
|
||||
lc.WaitForData(-1);
|
||||
LinkUpdate2(0);
|
||||
}*/
|
||||
break;
|
||||
|
||||
case 0x130:
|
||||
case 0x130: //AdamN: KEYINPUT
|
||||
P1 |= (value & 0x3FF);
|
||||
UPDATE_REG(0x130, P1);
|
||||
break;
|
||||
|
||||
case 0x132:
|
||||
case 0x132: //AdamN: KEYCNT
|
||||
UPDATE_REG(0x132, value & 0xC3FF);
|
||||
break;
|
||||
|
||||
case COMM_RCNT:
|
||||
StartGPLink(value);
|
||||
case COMM_RCNT: //AdamN: often reach here even when no connection yet
|
||||
/*if(lanlink.connected)
|
||||
if(linkid) {
|
||||
lc.DiscardData(); //AdamN: discarding may cause server to wait for infinity
|
||||
} else {
|
||||
//ls.DiscardData();
|
||||
}*/
|
||||
lanlink.mode = GetSIOMode(READ16LE(&ioMem[COMM_SIOCNT]), value);
|
||||
if(READ16LE(&ioMem[COMM_RCNT]) != (/*READ16LE(&ioMem[COMM_RCNT]) &*/ value)) {
|
||||
#ifdef GBA_LOGGING
|
||||
if(systemVerbose & VERBOSE_SIO) {
|
||||
log("RCNT(%d) : %04X->%04X %04X %04X %04X %04X %04X (VCOUNT = %d)\n", GetTickCount(), READ16LE(&ioMem[COMM_RCNT]), value, READ16LE(&ioMem[COMM_SIOCNT]), READ16LE(&ioMem[COMM_SIOMULTI0]), READ16LE(&ioMem[COMM_SIOMULTI1]), READ16LE(&ioMem[COMM_SIOMULTI2]), READ16LE(&ioMem[COMM_SIOMULTI3]), VCOUNT );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*if(LinkHandlerActive) {
|
||||
LinkCmdQueue(2,value);
|
||||
c_s.Lock(); //AdamN: Locking resource to prevent deadlock
|
||||
LinkParam2=value;
|
||||
LinkCommand|=2; //AdamN: StartGPLink command
|
||||
c_s.Unlock(); //AdamN: Locking resource to prevent deadlock
|
||||
} else {
|
||||
LogStrPush("CPUUpdReg");*/
|
||||
StartGPLink(value); //AdamN: doesn't need to be put in different thread as it doesn't send/recv data
|
||||
/*LogStrPop(9);
|
||||
}*/
|
||||
break;
|
||||
|
||||
/*case COMM_IR:
|
||||
StartIRLink(value); //AdamN: not made yet tho, probably not useful
|
||||
break;*/
|
||||
|
||||
case COMM_JOYCNT:
|
||||
{
|
||||
|
@ -3128,6 +3389,8 @@ void CPUInit(const char *biosFileName, bool useBiosFile)
|
|||
|
||||
void CPUReset()
|
||||
{
|
||||
EmuReseted = true;
|
||||
LinkFirstTime = true;
|
||||
if(gbaSaveType == 0) {
|
||||
if(eepromInUse)
|
||||
gbaSaveType = 3;
|
||||
|
@ -3475,21 +3738,27 @@ extern void winlog(const char *, ...);
|
|||
|
||||
void CPULoop(int ticks)
|
||||
{
|
||||
if(EmuCtr>0) {log("Emu inside Emu:%d\n",EmuCtr);return;}
|
||||
|
||||
int clockTicks;
|
||||
int timerOverflow = 0;
|
||||
// variable used by the CPU core
|
||||
cpuTotalTicks = 0;
|
||||
|
||||
cpuBreakLoop = false; //
|
||||
// shuffle2: what's the purpose?
|
||||
if(gba_link_enabled)
|
||||
cpuNextEvent = 1;
|
||||
/*if(gba_link_enabled && lanlink.connected && lanlink.mode==MULTIPLAYER && frameCount < systemFrameSkip)
|
||||
//if(linkid)
|
||||
cpuNextEvent = 159; //224; //else; //AdamN: this is to prevent CPU from executing too many opcodes when frame being skipped which cause Linking instability (ie. in-game timeout reached on client)
|
||||
else */
|
||||
cpuNextEvent = CPUUpdateTicks(); //cpuNextEvent = 1; //224 //AdamN: this will cause slowdown?*/
|
||||
bool NewFrame = false;
|
||||
|
||||
cpuBreakLoop = false;
|
||||
cpuNextEvent = CPUUpdateTicks();
|
||||
//cpuBreakLoop = false;
|
||||
//cpuNextEvent = CPUUpdateTicks(); //
|
||||
if(cpuNextEvent > ticks)
|
||||
cpuNextEvent = ticks;
|
||||
|
||||
|
||||
for(;;) {
|
||||
#ifndef FINAL_VERSION
|
||||
if(systemDebug) {
|
||||
|
@ -3526,6 +3795,7 @@ void CPULoop(int ticks)
|
|||
}
|
||||
#endif /* FINAL_VERSION */
|
||||
|
||||
if(breakpt && armNextPC==breakaddr) holdState=true; //AdamN: checking for breakpoint
|
||||
if(!holdState && !SWITicks) {
|
||||
if(armState) {
|
||||
if (!armExecute())
|
||||
|
@ -3555,7 +3825,7 @@ void CPULoop(int ticks)
|
|||
cpuTotalTicks = 0;
|
||||
cpuDmaHack = false;
|
||||
|
||||
updateLoop:
|
||||
updateLoop:
|
||||
|
||||
if (IRQTicks)
|
||||
{
|
||||
|
@ -3581,7 +3851,7 @@ void CPULoop(int ticks)
|
|||
lcdTicks += 224;
|
||||
DISPSTAT |= 2;
|
||||
UPDATE_REG(0x04, DISPSTAT);
|
||||
if(DISPSTAT & 16) {
|
||||
if(DISPSTAT & 16) { // entering H-Blank
|
||||
IF |= 2;
|
||||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
|
@ -3608,12 +3878,15 @@ void CPULoop(int ticks)
|
|||
DISPSTAT &= 0xFFFD;
|
||||
if(VCOUNT == 160) {
|
||||
count++;
|
||||
NewFrame = true;
|
||||
systemFrame();
|
||||
|
||||
if((count % 10) == 0) {
|
||||
/*if((count % 10) == 0) {
|
||||
system10Frames(60);
|
||||
}
|
||||
if(count == 60) {
|
||||
}*/
|
||||
system1Frames(60, count);
|
||||
|
||||
if(count >= 60) {
|
||||
u32 time = systemGetClock();
|
||||
if(time != lastTime) {
|
||||
u32 t = 100000/(time - lastTime);
|
||||
|
@ -3623,6 +3896,7 @@ void CPULoop(int ticks)
|
|||
lastTime = time;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
u32 joy = 0;
|
||||
// update joystick information
|
||||
if(systemReadJoypads())
|
||||
|
@ -3667,11 +3941,12 @@ void CPULoop(int ticks)
|
|||
DISPSTAT |= 1;
|
||||
DISPSTAT &= 0xFFFD;
|
||||
UPDATE_REG(0x04, DISPSTAT);
|
||||
if(DISPSTAT & 0x0008) {
|
||||
if(DISPSTAT & 0x0008) { //entering V-Blank
|
||||
IF |= 1;
|
||||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
CPUCheckDMA(1, 0x0f);
|
||||
|
||||
if(frameCount >= framesToSkip) {
|
||||
systemDrawScreen();
|
||||
frameCount = 0;
|
||||
|
@ -3786,7 +4061,10 @@ void CPULoop(int ticks)
|
|||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} //else //AdamN: this seems to fix the instability of linking when frame being skipped, but it causes artifact at the top lines when connection established in game, does cpu executes more opcodes when frameskipped?
|
||||
//frameCount++; //AdamN: shouldn't increase frameCount here, instead do something useless just to delay before calling LinkUpdate to maintain stability
|
||||
//if(lanlink.connected) if(linkid) cpuNextEvent = cpuTotalTicks;/*lc.WaitForData(0); else ls.WaitForData(0);*/
|
||||
|
||||
// entering H-Blank
|
||||
DISPSTAT |= 2;
|
||||
UPDATE_REG(0x04, DISPSTAT);
|
||||
|
@ -3796,6 +4074,7 @@ void CPULoop(int ticks)
|
|||
IF |= 2;
|
||||
UPDATE_REG(0x202, IF);
|
||||
}
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3942,8 +4221,21 @@ void CPULoop(int ticks)
|
|||
if (gba_joybus_enabled)
|
||||
JoyBusUpdate(clockTicks);
|
||||
|
||||
if (gba_link_enabled)
|
||||
LinkUpdate(clockTicks);
|
||||
if (gba_link_enabled && (lanlink.connected || !lanlink.active)) { //AdamN: don't update if there are no connection
|
||||
LinkUpdate(clockTicks); //AdamN: when frame being skipped LinkUpdate might not be called(?) thus causing instability
|
||||
NewFrame = false;
|
||||
//if(LinkHandlerActive) {
|
||||
//LinkCmdQueue(8,clockTicks);
|
||||
//c_s.Lock(); //AdamN: Locking resource to prevent deadlock
|
||||
//LinkParam8=clockTicks;
|
||||
//LinkCommand|=8; //AdamN: LinkUpdate command
|
||||
//c_s.Unlock(); //AdamN: Locking resource to prevent deadlock
|
||||
//} else if(/*(clockTicks & 1)&&*/(lanlink.connected)) { //AdamN: it seems LinkUpdate need to be called every cycle, occasionally doesn't works
|
||||
//LogStrPush("CPULoop");
|
||||
//LinkUpdate2(clockTicks); //AdamN: using blocking sockets here can cause noticibly delays
|
||||
//LogStrPop(7);
|
||||
//}
|
||||
}
|
||||
|
||||
cpuNextEvent = CPUUpdateTicks();
|
||||
|
||||
|
@ -3960,8 +4252,11 @@ void CPULoop(int ticks)
|
|||
}
|
||||
|
||||
// shuffle2: what's the purpose?
|
||||
if(gba_link_enabled)
|
||||
cpuNextEvent = 1;
|
||||
/*if(gba_link_enabled && lanlink.connected)
|
||||
cpuNextEvent = 1; //AdamN: this will cause great slowdown*/
|
||||
/*if(gba_link_enabled && lanlink.connected && lanlink.mode==MULTIPLAYER && frameCount < systemFrameSkip)
|
||||
//if(linkid)
|
||||
cpuNextEvent = 159; //224;*/ //cpuTotalTicks+224; //AdamN: this is to prevent CPU from executing too many opcodes when frame being skipped which cause Linking instability (ie. in-game timeout reached on client)
|
||||
|
||||
if(IF && (IME & 1) && armIrqEnable) {
|
||||
int res = IF & IE;
|
||||
|
|
|
@ -66,6 +66,12 @@ extern bool armState;
|
|||
extern int armMode;
|
||||
extern void (*cpuSaveGameFunc)(u32,u8);
|
||||
|
||||
extern int cpuNextEvent;
|
||||
extern int cpuTotalTicks;
|
||||
extern bool holdState;
|
||||
extern bool breakpt;
|
||||
extern u32 breakaddr;
|
||||
|
||||
#ifdef BKPT_SUPPORT
|
||||
extern u8 freezeWorkRAM[0x40000];
|
||||
extern u8 freezeInternalRAM[0x8000];
|
||||
|
|
2962
src/gba/GBALink.cpp
2962
src/gba/GBALink.cpp
File diff suppressed because it is too large
Load Diff
|
@ -4,30 +4,41 @@
|
|||
#include <SFML/Network.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER //#ifdef _WIN32
|
||||
#include "../Win32/WinHelper.h" // AdamN: for CCriticalSection
|
||||
#endif
|
||||
|
||||
#define LINK_PARENTLOST 0x80
|
||||
#define UNSUPPORTED -1
|
||||
#define MULTIPLAYER 0
|
||||
#define NORMAL8 1
|
||||
#define NORMAL32 2
|
||||
#define NORMAL32 2 //AdamN: wireless use normal32 also
|
||||
#define UART 3
|
||||
#define JOYBUS 4
|
||||
#define GP 5
|
||||
#define INFRARED 6 //AdamN: Infrared Register at 4000136h
|
||||
#define RFU_INIT 0
|
||||
#define RFU_COMM 1
|
||||
#define RFU_SEND 2
|
||||
#define RFU_RECV 3
|
||||
|
||||
#define COMM_SIODATA32_L 0x120
|
||||
#define COMM_SIODATA32_H 0x122
|
||||
#define COMM_SIODATA32_L 0x120 //AdamN: Lower 16bit on Normal mode
|
||||
#define COMM_SIODATA32_H 0x122 //AdamN: Higher 16bit on Normal mode
|
||||
#define COMM_SIOMULTI0 0x120 //AdamN: SIOMULTI0 (16bit) on MultiPlayer mode (Parent/Master)
|
||||
#define COMM_SIOMULTI1 0x122 //AdamN: SIOMULTI1 (16bit) on MultiPlayer mode (Child1/Slave1)
|
||||
#define COMM_SIOMULTI2 0x124 //AdamN: SIOMULTI2 (16bit) on MultiPlayer mode (Child2/Slave2)
|
||||
#define COMM_SIOMULTI3 0x126 //AdamN: SIOMULTI3 (16bit) on MultiPlayer mode (Child3/Slave3)
|
||||
#define COMM_SIOCNT 0x128
|
||||
#define COMM_SIODATA8 0x12a
|
||||
#define COMM_RCNT 0x134
|
||||
#define COMM_SIODATA8 0x12a //AdamN: 8bit on Normal/UART mode, (up to 4x8bit with FIFO)
|
||||
#define COMM_SIOMLT_SEND 0x12a //AdamN: SIOMLT_SEND (16bit R/W) on MultiPlayer mode (local outgoing)
|
||||
#define COMM_RCNT 0x134 //AdamN: SIO Mode (4bit data) on GeneralPurpose mode
|
||||
#define COMM_IR 0x136 //AdamN: Infrared Register (16bit) 1bit data at a time(LED On/Off)?
|
||||
#define COMM_JOYCNT 0x140
|
||||
#define COMM_JOY_RECV_L 0x150
|
||||
#define COMM_JOY_RECV_L 0x150 //AdamN: Send/Receive 8bit Lower first then 8bit Higher
|
||||
#define COMM_JOY_RECV_H 0x152
|
||||
#define COMM_JOY_TRANS_L 0x154
|
||||
#define COMM_JOY_TRANS_L 0x154 //AdamN: Send/Receive 8bit Lower first then 8bit Higher
|
||||
#define COMM_JOY_TRANS_H 0x156
|
||||
#define COMM_JOYSTAT 0x158
|
||||
#define COMM_JOYSTAT 0x158 //AdamN: Send/Receive 8bit lower only
|
||||
|
||||
#define JOYSTAT_RECV 2
|
||||
#define JOYSTAT_SEND 8
|
||||
|
@ -53,11 +64,14 @@ typedef struct {
|
|||
int lastlinktime;
|
||||
u8 numgbas;
|
||||
u8 linkflags;
|
||||
int rfu_q[4];
|
||||
u8 rfu_request[4];
|
||||
int rfu_linktime[4];
|
||||
u32 rfu_bdata[4][7];
|
||||
u32 rfu_data[4][32];
|
||||
int rfu_q[5];
|
||||
u16 rfu_qid[5];
|
||||
u8 rfu_request[5];
|
||||
u16 rfu_reqid[5];
|
||||
int rfu_linktime[5];
|
||||
u32 rfu_bdata[5][7]; //for 0x16/0x1d/0x1e?
|
||||
u32 rfu_gdata[5]; //for 0x17/0x19?/0x1e?
|
||||
u32 rfu_data[5][32]; //for 0x24-0x26
|
||||
} LINKDATA;
|
||||
|
||||
class lserver{
|
||||
|
@ -65,56 +79,81 @@ class lserver{
|
|||
fd_set fdset;
|
||||
timeval wsocktimeout;
|
||||
//timeval udptimeout;
|
||||
public:
|
||||
char inbuffer[256], outbuffer[256];
|
||||
int *intinbuffer;
|
||||
u16 *u16inbuffer;
|
||||
u32 *u32inbuffer;
|
||||
int *intoutbuffer;
|
||||
u16 *u16outbuffer;
|
||||
u32 *u32outbuffer;
|
||||
int insize, outsize;
|
||||
int counter;
|
||||
int done;
|
||||
public:
|
||||
int howmanytimes;
|
||||
SOCKET tcpsocket[4];
|
||||
SOCKADDR_IN udpaddr[4];
|
||||
SOCKET tcpsocket[5];
|
||||
SOCKADDR_IN udpaddr[5];
|
||||
DWORD latency[5];
|
||||
lserver(void);
|
||||
int Init(void*);
|
||||
void Send(void);
|
||||
void Recv(void);
|
||||
BOOL Send(void);
|
||||
BOOL Recv(void);
|
||||
BOOL WaitForData(int ms);
|
||||
BOOL SendData(int size, int nretry = 0);
|
||||
BOOL SendData(const char *buf, int size, int nretry = 0);
|
||||
BOOL RecvData(int size, int idx, bool peek = false);
|
||||
BOOL IsDataReady(void);
|
||||
int DiscardData(int idx);
|
||||
};
|
||||
|
||||
class lclient{
|
||||
fd_set fdset;
|
||||
timeval wsocktimeout;
|
||||
public:
|
||||
char inbuffer[256], outbuffer[256];
|
||||
int *intinbuffer;
|
||||
u16 *u16inbuffer;
|
||||
u32 *u32inbuffer;
|
||||
int *intoutbuffer;
|
||||
u16 *u16outbuffer;
|
||||
int numbytes;
|
||||
public:
|
||||
u32 *u32outbuffer;
|
||||
int numbytes, insize, outsize;
|
||||
bool oncesend;
|
||||
SOCKADDR_IN serverinfo;
|
||||
SOCKET noblock;
|
||||
int numtransfers;
|
||||
lclient(void);
|
||||
int Init(LPHOSTENT, void*);
|
||||
void Send(void);
|
||||
void Recv(void);
|
||||
BOOL Send(void);
|
||||
BOOL Recv(void);
|
||||
void CheckConn(void);
|
||||
BOOL SendData(int size, int nretry = 0);
|
||||
BOOL SendData(const char *buf, int size, int nretry = 0);
|
||||
BOOL RecvData(int size, bool peek = false);
|
||||
BOOL WaitForData(int ms);
|
||||
BOOL IsDataReady(void);
|
||||
int DiscardData(void);
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
SOCKET tcpsocket;
|
||||
//SOCKET udpsocket;
|
||||
DWORD latency;
|
||||
int numgbas;
|
||||
HANDLE thread;
|
||||
u8 type;
|
||||
u8 server;
|
||||
bool terminate;
|
||||
bool connected;
|
||||
bool speed;
|
||||
bool speed; //speedhack
|
||||
bool active;
|
||||
int mode;
|
||||
} LANLINKDATA;
|
||||
|
||||
typedef struct {
|
||||
u16 Command;
|
||||
u16 Param;
|
||||
} LINKCMDPRM;
|
||||
#endif
|
||||
|
||||
extern bool gba_joybus_enabled;
|
||||
|
@ -124,24 +163,47 @@ extern sf::IPAddress joybusHostAddr;
|
|||
extern void JoyBusConnect();
|
||||
extern void JoyBusShutdown();
|
||||
extern void JoyBusUpdate(int ticks);
|
||||
extern inline int GetSIOMode(u16 siocnt, u16 rcnt);
|
||||
|
||||
extern bool gba_link_enabled;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
extern void LogStrPush(const char *str);
|
||||
extern void LogStrPop(int len);
|
||||
extern void LinkCmdQueue(u16 Cmd, u16 Prm);
|
||||
extern u8 gbStartLink(u8 b);
|
||||
extern u16 gbLinkUpdate(u8 b);
|
||||
extern void StartLink(u16);
|
||||
extern void StartLink2(u16);
|
||||
extern void StartGPLink(u16);
|
||||
extern void LinkSSend(u16);
|
||||
extern void LinkUpdate(int);
|
||||
extern void LinkUpdate2(int ticks, int FrameCnt);
|
||||
extern void LinkChildStop();
|
||||
extern void LinkChildSend(u16);
|
||||
extern void CloseLanLink();
|
||||
extern void CloseLink(); //CloseLanLink(); //AdamN: this should be CloseLink isn't?
|
||||
extern char *MakeInstanceFilename(const char *Input);
|
||||
extern LANLINKDATA lanlink;
|
||||
extern int vbaid;
|
||||
extern bool rfu_enabled;
|
||||
extern int linktimeout;
|
||||
extern u8 gbSIO_SC;
|
||||
extern lclient lc;
|
||||
extern lserver ls;
|
||||
extern int linkid;
|
||||
extern bool linkdatarecvd[4];
|
||||
extern bool LinkIsWaiting;
|
||||
extern bool LinkFirstTime;
|
||||
extern bool EmuReseted;
|
||||
extern int EmuCtr;
|
||||
extern WinHelper::CCriticalSection c_s; //AdamN: critical section object to lock shared resource on multithread as CWnd is not thread-safe
|
||||
extern int LinkCommand;
|
||||
extern int LinkParam1;
|
||||
extern int LinkParam2;
|
||||
extern int LinkParam4;
|
||||
extern int LinkParam8;
|
||||
extern bool LinkHandlerActive;
|
||||
//extern CPtrList LinkCmdList;
|
||||
#else // These are stubbed for now
|
||||
inline void StartLink(u16){}
|
||||
inline void StartGPLink(u16){}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#define VERBOSE_UNDEFINED 256
|
||||
#define VERBOSE_AGBPRINT 512
|
||||
#define VERBOSE_SOUNDOUTPUT 1024
|
||||
#define VERBOSE_SIO 2048
|
||||
#define VERBOSE_LINK 4096
|
||||
|
||||
extern reg_pair reg[45];
|
||||
extern bool ioReadable[0x400];
|
||||
|
|
|
@ -303,7 +303,7 @@ void soundEvent(u32 address, u16 data)
|
|||
{
|
||||
switch ( address )
|
||||
{
|
||||
case SGCNT0_H:
|
||||
case SGCNT0_H: //SOUNDCNT_H
|
||||
write_SGCNT0_H( data );
|
||||
break;
|
||||
|
||||
|
@ -319,7 +319,7 @@ void soundEvent(u32 address, u16 data)
|
|||
WRITE16LE( &ioMem[address], data );
|
||||
break;
|
||||
|
||||
case 0x88:
|
||||
case 0x88: //SOUNDBIAS
|
||||
data &= 0xC3FF;
|
||||
WRITE16LE( &ioMem[address], data );
|
||||
break;
|
||||
|
|
|
@ -856,7 +856,7 @@ void BIOS_RegisterRamReset(u32 flags)
|
|||
// no need to trace here. this is only called directly from GBA.cpp
|
||||
// to emulate bios initialization
|
||||
|
||||
CPUUpdateRegister(0x0, 0x80);
|
||||
CPUUpdateRegister(0x0, 0x80); //DISPCNT
|
||||
|
||||
if(flags) {
|
||||
if(flags & 0x01) {
|
||||
|
@ -894,35 +894,35 @@ void BIOS_RegisterRamReset(u32 flags)
|
|||
for(i = 0; i < 0x18; i++)
|
||||
CPUUpdateRegister(0xb0+i*2, 0);
|
||||
|
||||
CPUUpdateRegister(0x130, 0);
|
||||
CPUUpdateRegister(0x20, 0x100);
|
||||
CPUUpdateRegister(0x30, 0x100);
|
||||
CPUUpdateRegister(0x26, 0x100);
|
||||
CPUUpdateRegister(0x36, 0x100);
|
||||
CPUUpdateRegister(0x130, 0); //KEYINPUT
|
||||
CPUUpdateRegister(0x20, 0x100); //BG2PA
|
||||
CPUUpdateRegister(0x30, 0x100); //BG3PA
|
||||
CPUUpdateRegister(0x26, 0x100); //BG2PD
|
||||
CPUUpdateRegister(0x36, 0x100); //BG3PD
|
||||
}
|
||||
|
||||
if(flags & 0x20) {
|
||||
int i;
|
||||
for(i = 0; i < 8; i++)
|
||||
CPUUpdateRegister(0x110+i*2, 0);
|
||||
CPUUpdateRegister(0x134, 0x8000);
|
||||
CPUUpdateRegister(0x110+i*2, 0); //Unused Registers after Timer Register?
|
||||
CPUUpdateRegister(0x134, 0x8000); //COMM_RCNT for GP/JOYBUS?
|
||||
for(i = 0; i < 7; i++)
|
||||
CPUUpdateRegister(0x140+i*2, 0);
|
||||
CPUUpdateRegister(0x140+i*2, 0); //Unused Registers after COMM_JOYCNT?
|
||||
}
|
||||
|
||||
if(flags & 0x40) {
|
||||
int i;
|
||||
CPUWriteByte(0x4000084, 0);
|
||||
CPUWriteByte(0x4000084, 0x80);
|
||||
CPUWriteMemory(0x4000080, 0x880e0000);
|
||||
CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
|
||||
CPUWriteByte(0x4000070, 0x70);
|
||||
CPUWriteByte(0x4000084, 0); //SOUNDCNT_X, Is this realy needed as below it's rewritten right?
|
||||
CPUWriteByte(0x4000084, 0x80); //SOUNDCNT_X, Rewritten above?
|
||||
CPUWriteMemory(0x4000080, 0x880e0000); //SOUNDCNT_L
|
||||
CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff); //SOUNDBIAS
|
||||
CPUWriteByte(0x4000070, 0x70); //SOUND3CNT_L
|
||||
for(i = 0; i < 8; i++)
|
||||
CPUUpdateRegister(0x90+i*2, 0);
|
||||
CPUWriteByte(0x4000070, 0);
|
||||
CPUWriteByte(0x4000070, 0); //SOUND3CNT_L, Rewritten again?
|
||||
for(i = 0; i < 8; i++)
|
||||
CPUUpdateRegister(0x90+i*2, 0);
|
||||
CPUWriteByte(0x4000084, 0);
|
||||
CPUWriteByte(0x4000084, 0); //SOUNDCNT_X, Another Rewriten??
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ public:
|
|||
void reset(); // stop and reset the secondary sound buffer
|
||||
void resume(); // resume the secondary sound buffer
|
||||
void write(u16 * finalWave, int length); // write the emulated sound to the secondary sound buffer
|
||||
// Configuration Changes
|
||||
void setThrottle( unsigned short throttle );
|
||||
};
|
||||
|
||||
|
||||
|
@ -191,6 +193,8 @@ bool DirectSound::init(long sampleRate)
|
|||
return false;
|
||||
}
|
||||
|
||||
setThrottle(theApp.throttle); //AdamN: setting sound pitch to current throttle
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -240,7 +244,7 @@ void DirectSound::write(u16 * finalWave, int length)
|
|||
LPVOID lpvPtr2;
|
||||
DWORD dwBytes2 = 0;
|
||||
|
||||
if( !speedup && synchronize && !theApp.throttle ) {
|
||||
if( !speedup && synchronize /*&& !theApp.throttle*/ ) {
|
||||
hr = dsbSecondary->GetStatus(&status);
|
||||
if( status & DSBSTATUS_PLAYING ) {
|
||||
if( !soundPaused ) {
|
||||
|
@ -310,6 +314,18 @@ void DirectSound::write(u16 * finalWave, int length)
|
|||
}
|
||||
}
|
||||
|
||||
void DirectSound::setThrottle( unsigned short throttle ) //AdamN: doesn't works quite right yet
|
||||
{
|
||||
if(!pDirectSound) return;
|
||||
if( dsbSecondary == NULL ) return;
|
||||
|
||||
if( throttle == 0 ) throttle = 100;
|
||||
//HRESULT hr = dsbPrimary->SetFrequency( (DWORD)(soundGetSampleRate() * throttle / 100.0f) ); //AdamN: may not be valid for primary buffer, also need to check CAPS whether frequency is supported or not
|
||||
//ASSERT( hr == S_OK );
|
||||
HRESULT hr = dsbSecondary->SetFrequency( (DWORD)(soundGetSampleRate() * throttle / 100.0f) ); //AdamN: may need to use IDirectMusicSegment8::SetLength to adjust the inverval for looping to prevent silence when pitch is higher than normal pitch or restarted/relooped when pitch is lower than normal before it finished the whole stream
|
||||
ASSERT( hr == S_OK );
|
||||
}
|
||||
|
||||
SoundDriver *newDirectSound()
|
||||
{
|
||||
return new DirectSound();
|
||||
|
|
|
@ -33,10 +33,15 @@ Disassemble::Disassemble(CWnd* pParent /*=NULL*/)
|
|||
m_t = FALSE;
|
||||
m_v = FALSE;
|
||||
m_z = FALSE;
|
||||
m_breakpt = FALSE;
|
||||
m_autostep = FALSE;
|
||||
mode = -1;
|
||||
//}}AFX_DATA_INIT
|
||||
mode = 0;
|
||||
address = 0;
|
||||
//breakaddr = 0xffffffff;
|
||||
//breakpt = false;
|
||||
autostep = false;
|
||||
autoUpdate = false;
|
||||
count = 1;
|
||||
}
|
||||
|
@ -56,6 +61,9 @@ void Disassemble::DoDataExchange(CDataExchange* pDX)
|
|||
DDX_Check(pDX, IDC_V, m_v);
|
||||
DDX_Check(pDX, IDC_Z, m_z);
|
||||
DDX_Radio(pDX, IDC_AUTOMATIC, mode);
|
||||
DDX_Check(pDX, IDC_BREAK_AT, m_breakpt);
|
||||
DDX_Control(pDX, IDC_ADDRESS2, m_address2);
|
||||
DDX_Check(pDX, IDC_AUTO_STEP, m_autostep);
|
||||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
@ -73,7 +81,9 @@ BEGIN_MESSAGE_MAP(Disassemble, CDialog)
|
|||
ON_BN_CLICKED(IDC_THUMB, OnThumb)
|
||||
ON_WM_VSCROLL()
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
ON_BN_CLICKED(IDC_BREAK_AT, &Disassemble::OnBnClickedBreakAt)
|
||||
ON_BN_CLICKED(IDC_STEPINTO, &Disassemble::OnBnClickedStepinto)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Disassemble message handlers
|
||||
|
@ -338,3 +348,38 @@ void Disassemble::PostNcDestroy()
|
|||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
|
||||
void Disassemble::OnBnClickedBreakAt()
|
||||
{
|
||||
// TODO: Add your control notification handler code here
|
||||
CString buffer;
|
||||
m_address2.GetWindowText(buffer);
|
||||
sscanf(buffer, "%x", &breakaddr);
|
||||
//if (mode==1)
|
||||
breakaddr&=0xfffffffc;
|
||||
//else if (mode==2)
|
||||
// breakaddr&=0xfffffffe;
|
||||
m_breakpt = !m_breakpt;
|
||||
breakpt = (bool)m_breakpt;
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
||||
void Disassemble::OnBnClickedStepinto()
|
||||
{
|
||||
// TODO: Add your control notification handler code here
|
||||
if(rom != NULL)
|
||||
{
|
||||
if(armState)
|
||||
breakaddr = breakaddr + 4;
|
||||
else
|
||||
breakaddr = breakaddr + 2;
|
||||
char buffer[20];
|
||||
sprintf(buffer, _T("%08x"), breakaddr);
|
||||
m_address2.SetWindowText(buffer);
|
||||
cpuNextEvent = 1; //cpuTotalTicks;
|
||||
holdState = false;
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,13 +22,17 @@ class Disassemble : public ResizeDlg, IUpdateListener
|
|||
void refresh();
|
||||
int count;
|
||||
bool autoUpdate;
|
||||
//bool breakpt;
|
||||
bool autostep;
|
||||
u32 address;
|
||||
//u32 breakaddr;
|
||||
Disassemble(CWnd* pParent = NULL); // standard constructor
|
||||
|
||||
// Dialog Data
|
||||
//{{AFX_DATA(Disassemble)
|
||||
enum { IDD = IDD_DISASSEMBLE };
|
||||
CEdit m_address;
|
||||
CEdit m_address2;
|
||||
CListBox m_list;
|
||||
BOOL m_c;
|
||||
BOOL m_f;
|
||||
|
@ -37,6 +41,8 @@ class Disassemble : public ResizeDlg, IUpdateListener
|
|||
BOOL m_t;
|
||||
BOOL m_v;
|
||||
BOOL m_z;
|
||||
BOOL m_breakpt;
|
||||
BOOL m_autostep;
|
||||
int mode;
|
||||
//}}AFX_DATA
|
||||
|
||||
|
@ -67,7 +73,10 @@ class Disassemble : public ResizeDlg, IUpdateListener
|
|||
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
|
||||
//}}AFX_MSG
|
||||
DECLARE_MESSAGE_MAP()
|
||||
};
|
||||
public:
|
||||
afx_msg void OnBnClickedBreakAt();
|
||||
afx_msg void OnBnClickedStepinto();
|
||||
};
|
||||
|
||||
//{{AFX_INSERT_LOCATION}}
|
||||
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#include "stdafx.h"
|
||||
//#include "afxctl.h"
|
||||
#include "vba.h"
|
||||
#include "LinkOptions.h"
|
||||
#include "../gba/GBALink.h"
|
||||
|
||||
/*#ifdef _MSC_VER //#ifdef _WIN32
|
||||
#include "WinHelper.h" // AdamN: MFC MultiThreading
|
||||
#endif*/
|
||||
|
||||
extern lserver ls;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -49,7 +54,7 @@ void LinkOptions::DoDataExchange(CDataExchange* pDX)
|
|||
|
||||
BOOL LinkOptions::OnInitDialog(){
|
||||
TCITEM tabitem;
|
||||
char tabtext[3][8] = {"General", "Server", "Client"};
|
||||
char tabtext[3][8] = {_T("General"), _T("Server"), _T("Client")};
|
||||
int i;
|
||||
|
||||
CDialog::OnInitDialog();
|
||||
|
@ -145,6 +150,11 @@ void LinkServer::DoDataExchange(CDataExchange* pDX)
|
|||
{
|
||||
CDialog::DoDataExchange(pDX);
|
||||
//{{AFX_DATA_MAP(LinkServer)
|
||||
BOOL ok = (theApp.cartridgeType != IMAGE_GB);
|
||||
GetDlgItem(IDC_LINK3P)->EnableWindow(ok);
|
||||
GetDlgItem(IDC_LINK4P)->EnableWindow(ok);
|
||||
GetDlgItem(IDC_LINK5P)->EnableWindow(rfu_enabled && ok);
|
||||
|
||||
DDX_Radio(pDX, IDC_LINK2P, m_numplayers);
|
||||
DDX_Radio(pDX, IDC_LINKTCP, m_prottype);
|
||||
DDX_Check(pDX, IDC_SSPEED, m_speed);
|
||||
|
@ -195,7 +205,7 @@ BOOL LinkServer::OnInitDialog()
|
|||
{
|
||||
CDialog::OnInitDialog();
|
||||
|
||||
m_numplayers = lanlink.numgbas;
|
||||
m_numplayers = max(lanlink.numgbas-1,0);
|
||||
m_prottype = lanlink.type;
|
||||
m_speed = lanlink.speed;
|
||||
|
||||
|
@ -455,14 +465,14 @@ void LinkOptions::OnOk()
|
|||
void LinkGeneral::OnRadio1()
|
||||
{
|
||||
m_type = 0;
|
||||
lanlink.active = 0;
|
||||
lanlink.active = 0; //Single Computer
|
||||
GetParent()->Invalidate();
|
||||
}
|
||||
|
||||
void LinkGeneral::OnRadio2()
|
||||
{
|
||||
m_type = 1;
|
||||
lanlink.active = 1;
|
||||
lanlink.active = 1; //Networks
|
||||
GetParent()->Invalidate();
|
||||
}
|
||||
|
||||
|
@ -473,7 +483,7 @@ BOOL LinkGeneral::OnInitDialog(){
|
|||
CDialog::OnInitDialog();
|
||||
|
||||
m_timeout.LimitText(5);
|
||||
sprintf(timeout, "%d", linktimeout);
|
||||
sprintf(timeout, _T("%d"), linktimeout);
|
||||
m_timeout.SetWindowText(timeout);
|
||||
|
||||
m_type = lanlink.active;
|
||||
|
@ -504,8 +514,8 @@ void LinkServer::OnServerStart()
|
|||
|
||||
if((errorcode=ls.Init(&dlg))!=0){
|
||||
char message[50];
|
||||
sprintf(message, "Error %d occured.\nPlease try again.", errorcode);
|
||||
MessageBox(message, "Error", MB_OK);
|
||||
sprintf(message, _T("Error %d occured.\nPlease try again."), errorcode);
|
||||
MessageBox(message, _T("Error"), MB_OK);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -520,6 +530,7 @@ BOOL LinkClient::OnInitDialog()
|
|||
|
||||
m_prottype = lanlink.type;
|
||||
m_hacks = lanlink.speed;
|
||||
m_serverip.SetWindowText(_T("localhost"));
|
||||
|
||||
UpdateData(FALSE);
|
||||
|
||||
|
@ -539,11 +550,12 @@ void LinkClient::OnLinkConnect()
|
|||
lanlink.speed = m_hacks==1 ? true : false;
|
||||
|
||||
m_serverip.GetWindowText(ipaddress, 30);
|
||||
|
||||
|
||||
if((errorcode=lc.Init(gethostbyname(ipaddress), &dlg))!=0){
|
||||
|
||||
char message[50];
|
||||
sprintf(message, "Error %d occured.\nPlease try again.", errorcode);
|
||||
MessageBox(message, "Error", MB_OK);
|
||||
sprintf(message, _T("Error %d occured.\nPlease try again."), errorcode);
|
||||
MessageBox(message, _T("Error"), MB_OK);
|
||||
return;
|
||||
}
|
||||
dlg.DoModal();
|
||||
|
@ -557,7 +569,7 @@ void LinkOptions::GetAllData(LinkGeneral *src)
|
|||
src->UpdateData(true);
|
||||
|
||||
src->m_timeout.GetWindowText(timeout, 5);
|
||||
sscanf(timeout, "%d", &linktimeout);
|
||||
sscanf(timeout, _T("%d"), &linktimeout);
|
||||
|
||||
if(src->m_type==0){
|
||||
lanlink.speed = 0;
|
||||
|
@ -593,6 +605,7 @@ void ServerWait::DoDataExchange(CDataExchange* pDX)
|
|||
//}}AFX_DATA_MAP
|
||||
}
|
||||
|
||||
|
||||
BEGIN_MESSAGE_MAP(ServerWait, CDialog)
|
||||
//{{AFX_MSG_MAP(ServerWait)
|
||||
ON_BN_CLICKED(ID_CANCEL, OnCancel)
|
||||
|
@ -604,7 +617,9 @@ END_MESSAGE_MAP()
|
|||
|
||||
void ServerWait::OnCancel()
|
||||
{
|
||||
lanlink.terminate = true;
|
||||
c_s.Lock(); //AdamN: Locking resource to prevent deadlock
|
||||
lanlink.terminate = true; //AdamN: accessing this might not be thread-safe w/o locking
|
||||
c_s.Unlock(); //AdamN: Unlock it after use
|
||||
CDialog::OnCancel();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ Logging::Logging(CWnd* pParent /*=NULL*/)
|
|||
m_dma3 = FALSE;
|
||||
m_agbprint = FALSE;
|
||||
m_undefined = FALSE;
|
||||
m_sio = FALSE;
|
||||
//}}AFX_DATA_INIT
|
||||
}
|
||||
|
||||
|
@ -52,6 +53,8 @@ void Logging::DoDataExchange(CDataExchange* pDX)
|
|||
DDX_Check(pDX, IDC_VERBOSE_AGBPRINT, m_agbprint);
|
||||
DDX_Check(pDX, IDC_VERBOSE_UNDEFINED, m_undefined);
|
||||
DDX_Check(pDX, IDC_VERBOSE_SOUNDOUTPUT, m_sound_output);
|
||||
DDX_Check(pDX, IDC_VERBOSE_SIO, m_sio);
|
||||
DDX_Check(pDX, IDC_VERBOSE_LINK, m_link);
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,10 +72,13 @@ BEGIN_MESSAGE_MAP(Logging, CDialog)
|
|||
ON_BN_CLICKED(IDC_VERBOSE_UNALIGNED_ACCESS, OnVerboseUnalignedAccess)
|
||||
ON_BN_CLICKED(IDC_VERBOSE_UNDEFINED, OnVerboseUndefined)
|
||||
ON_BN_CLICKED(IDC_VERBOSE_SOUNDOUTPUT, OnVerboseSoundoutput)
|
||||
ON_BN_CLICKED(IDC_VERBOSE_SIO, OnVerboseSIO)
|
||||
ON_BN_CLICKED(IDC_SAVE, OnSave)
|
||||
ON_EN_ERRSPACE(IDC_LOG, OnErrspaceLog)
|
||||
ON_EN_MAXTEXT(IDC_LOG, OnMaxtextLog)
|
||||
ON_WM_CLOSE()
|
||||
// ON_BN_CLICKED(IDC_VERBOSE_LINK, &Logging::OnBnClickedVerboseLink)
|
||||
ON_BN_CLICKED(IDC_VERBOSE_LINK, &Logging::OnVerboseLink)
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
|
||||
|
@ -147,6 +153,16 @@ void Logging::OnVerboseSoundoutput()
|
|||
systemVerbose ^= VERBOSE_SOUNDOUTPUT;
|
||||
}
|
||||
|
||||
void Logging::OnVerboseSIO()
|
||||
{
|
||||
systemVerbose ^= VERBOSE_SIO;
|
||||
}
|
||||
|
||||
void Logging::OnVerboseLink()
|
||||
{
|
||||
systemVerbose ^= VERBOSE_LINK;
|
||||
}
|
||||
|
||||
void Logging::OnSave()
|
||||
{
|
||||
int len = m_log.GetWindowTextLength();
|
||||
|
@ -213,6 +229,8 @@ BOOL Logging::OnInitDialog()
|
|||
m_undefined = (systemVerbose & VERBOSE_UNDEFINED) != 0;
|
||||
m_agbprint = (systemVerbose & VERBOSE_AGBPRINT) != 0;
|
||||
m_sound_output = (systemVerbose & VERBOSE_SOUNDOUTPUT) != 0;
|
||||
m_sio = (systemVerbose & VERBOSE_SIO) != 0;
|
||||
m_link = (systemVerbose & VERBOSE_LINK) != 0;
|
||||
UpdateData(FALSE);
|
||||
|
||||
m_log.LimitText(-1);
|
||||
|
@ -293,3 +311,7 @@ void toolsClearLog()
|
|||
Logging::instance->clearLog();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ public:
|
|||
BOOL m_agbprint;
|
||||
BOOL m_undefined;
|
||||
BOOL m_sound_output;
|
||||
BOOL m_sio;
|
||||
BOOL m_link;
|
||||
|
||||
// Overrides
|
||||
protected:
|
||||
|
@ -47,6 +49,8 @@ protected:
|
|||
afx_msg void OnVerboseUnalignedAccess();
|
||||
afx_msg void OnVerboseUndefined();
|
||||
afx_msg void OnVerboseSoundoutput();
|
||||
afx_msg void OnVerboseSIO();
|
||||
afx_msg void OnVerboseLink();
|
||||
afx_msg void OnSave();
|
||||
afx_msg void OnClose();
|
||||
afx_msg void OnErrspaceLog();
|
||||
|
|
|
@ -40,7 +40,12 @@
|
|||
void MainWnd::OnOptionsFrameskipThrottleNothrottle()
|
||||
{
|
||||
theApp.updateThrottle( 0 ); // disable
|
||||
theApp.autoFrameSkip = false;
|
||||
/*if(theApp.autoFrameSkip) {
|
||||
frameSkip = 0;
|
||||
gbFrameSkip = 0;
|
||||
systemFrameSkip = 0;
|
||||
}
|
||||
theApp.autoFrameSkip = false;*/
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI)
|
||||
|
@ -52,7 +57,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottleNothrottle(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsFrameskipThrottle25()
|
||||
{
|
||||
theApp.updateThrottle( 25 );
|
||||
theApp.autoFrameSkip = false;
|
||||
//theApp.autoFrameSkip = false;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI)
|
||||
|
@ -64,7 +69,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle25(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsFrameskipThrottle50()
|
||||
{
|
||||
theApp.updateThrottle( 50 );
|
||||
theApp.autoFrameSkip = false;
|
||||
//theApp.autoFrameSkip = false;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI)
|
||||
|
@ -76,7 +81,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle50(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsFrameskipThrottle100()
|
||||
{
|
||||
theApp.updateThrottle( 100 );
|
||||
theApp.autoFrameSkip = false;
|
||||
//theApp.autoFrameSkip = false;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI)
|
||||
|
@ -88,7 +93,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle100(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsFrameskipThrottle150()
|
||||
{
|
||||
theApp.updateThrottle( 150 );
|
||||
theApp.autoFrameSkip = false;
|
||||
//theApp.autoFrameSkip = false;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI)
|
||||
|
@ -100,7 +105,7 @@ void MainWnd::OnUpdateOptionsFrameskipThrottle150(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsFrameskipThrottle200()
|
||||
{
|
||||
theApp.updateThrottle( 200 );
|
||||
theApp.autoFrameSkip = false;
|
||||
//theApp.autoFrameSkip = false;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsFrameskipThrottle200(CCmdUI* pCmdUI)
|
||||
|
@ -116,7 +121,7 @@ void MainWnd::OnOptionsFrameskipThrottleOther()
|
|||
|
||||
if( v ) {
|
||||
theApp.updateThrottle( v );
|
||||
theApp.autoFrameSkip = false;
|
||||
//theApp.autoFrameSkip = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,12 +142,16 @@ void MainWnd::OnOptionsFrameskipAutomatic()
|
|||
theApp.autoFrameSkip = !theApp.autoFrameSkip;
|
||||
if(!theApp.autoFrameSkip && emulating)
|
||||
theApp.updateFrameSkip();
|
||||
else
|
||||
else if(theApp.autoFrameSkip)
|
||||
{
|
||||
theApp.throttle = false;
|
||||
frameSkip = 0;
|
||||
//theApp.throttle = false;
|
||||
frameSkip = 9;
|
||||
gbFrameSkip = 9;
|
||||
systemFrameSkip = 0;
|
||||
}
|
||||
//frameSkip = 0;
|
||||
//gbFrameSkip = 0;
|
||||
//systemFrameSkip = 0;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI)
|
||||
|
@ -152,6 +161,7 @@ void MainWnd::OnUpdateOptionsFrameskipAutomatic(CCmdUI* pCmdUI)
|
|||
|
||||
BOOL MainWnd::OnOptionsFrameskip(UINT nID)
|
||||
{
|
||||
//theApp.autoFrameSkip = false;
|
||||
switch(nID) {
|
||||
case ID_OPTIONS_VIDEO_FRAMESKIP_0:
|
||||
case ID_OPTIONS_VIDEO_FRAMESKIP_1:
|
||||
|
@ -166,7 +176,7 @@ BOOL MainWnd::OnOptionsFrameskip(UINT nID)
|
|||
}
|
||||
if(emulating)
|
||||
theApp.updateFrameSkip();
|
||||
theApp.updateThrottle( 0 );
|
||||
//theApp.updateThrottle( 0 );
|
||||
return TRUE;
|
||||
break;
|
||||
case ID_OPTIONS_VIDEO_FRAMESKIP_6:
|
||||
|
@ -180,7 +190,7 @@ BOOL MainWnd::OnOptionsFrameskip(UINT nID)
|
|||
}
|
||||
if(emulating)
|
||||
theApp.updateFrameSkip();
|
||||
theApp.updateThrottle( 0 );
|
||||
//theApp.updateThrottle( 0 );
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -585,8 +595,13 @@ void MainWnd::OnUpdateOptionsEmulatorDisablestatusmessages(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsEmulatorSynchronize()
|
||||
{
|
||||
synchronize = !synchronize;
|
||||
if (synchronize)
|
||||
theApp.throttle = false;
|
||||
if (synchronize) {
|
||||
//theApp.throttle = false;
|
||||
//theApp.autoFrameSkip = false;
|
||||
frameSkip = 0;
|
||||
gbFrameSkip = 0;
|
||||
systemFrameSkip = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsEmulatorSynchronize(CCmdUI* pCmdUI)
|
||||
|
@ -1023,6 +1038,8 @@ void MainWnd::OnUpdateOptionsGameboyBorder(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsGameboyPrinter()
|
||||
{
|
||||
theApp.winGbPrinterEnabled = !theApp.winGbPrinterEnabled;
|
||||
if(gba_link_enabled)
|
||||
gbSerialFunction = gbStartLink; else
|
||||
if(theApp.winGbPrinterEnabled)
|
||||
gbSerialFunction = gbPrinterSend;
|
||||
else
|
||||
|
@ -1560,7 +1577,7 @@ void MainWnd::OnOptionsLinkRFU()
|
|||
if(rfu_enabled) rfu_enabled = false;
|
||||
else {
|
||||
rfu_enabled = true;
|
||||
MessageBox("Please note this is the first version\nof RFU emulation code and it's not 100% bug free.\nAlso only 2 players single computer are supported at this time.", "Warning", MB_OK);
|
||||
//MessageBox("Please note this is the first version\nof RFU emulation code and it's not 100% bug free.\nAlso only 2 players single computer are supported at this time.", "Warning", MB_OK);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1572,6 +1589,12 @@ void MainWnd::OnUpdateOptionsLinkEnable(CCmdUI* pCmdUI)
|
|||
void MainWnd::OnOptionsLinkEnable()
|
||||
{
|
||||
gba_link_enabled = !gba_link_enabled;
|
||||
if(gba_link_enabled)
|
||||
gbSerialFunction = gbStartLink; else
|
||||
if(theApp.winGbPrinterEnabled)
|
||||
gbSerialFunction = gbPrinterSend;
|
||||
else
|
||||
gbSerialFunction = NULL;
|
||||
}
|
||||
|
||||
void MainWnd::OnUpdateOptionsLinkRFU(CCmdUI* pCmdUI)
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
void reset(); // stop and reset the secondary sound buffer
|
||||
void resume(); // play/resume the secondary sound buffer
|
||||
void write(u16 * finalWave, int length); // write the emulated sound to a sound buffer
|
||||
void setThrottle( unsigned short throttle ); //pitch
|
||||
|
||||
private:
|
||||
OPENALFNTABLE ALFunction;
|
||||
|
@ -181,6 +182,8 @@ bool OpenAL::init(long sampleRate)
|
|||
|
||||
|
||||
initialized = true;
|
||||
|
||||
setThrottle(theApp.throttle); //setting pitch to current throttle
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -281,7 +284,7 @@ void OpenAL::write(u16 * finalWave, int length)
|
|||
}
|
||||
}
|
||||
|
||||
if( !speedup && synchronize && !theApp.throttle ) {
|
||||
if( !speedup && synchronize /*&& !theApp.throttle*/ ) {
|
||||
// wait until at least one buffer has finished
|
||||
while( nBuffersProcessed == 0 ) {
|
||||
winlog( " waiting...\n" );
|
||||
|
@ -320,6 +323,20 @@ void OpenAL::write(u16 * finalWave, int length)
|
|||
}
|
||||
}
|
||||
|
||||
void OpenAL::setThrottle( unsigned short throttle )
|
||||
{
|
||||
if( !initialized ) return;
|
||||
winlog( "OpenAL::setThrottle\n" );
|
||||
|
||||
debugState();
|
||||
|
||||
if( throttle == 0 ) throttle = 100;
|
||||
ALFunction.alSourcef(source, AL_PITCH, (float)throttle / 100.0f );
|
||||
ASSERT_SUCCESS;
|
||||
|
||||
debugState(); //AdamN: is this needed?
|
||||
}
|
||||
|
||||
SoundDriver *newOpenAL()
|
||||
{
|
||||
winlog( "newOpenAL\n" );
|
||||
|
|
|
@ -59,8 +59,8 @@ void Throttle::OnOk()
|
|||
{
|
||||
UpdateData();
|
||||
|
||||
if(m_throttle < 5 || m_throttle > 1000)
|
||||
systemMessage(IDS_INVALID_THROTTLE_VALUE, "Invalid throttle value. Please enter a number between 5 and 1000");
|
||||
if(m_throttle < 5 || m_throttle > 2000)
|
||||
systemMessage(IDS_INVALID_THROTTLE_VALUE, "Invalid throttle value. Please enter a number between 5 and 2000");
|
||||
else
|
||||
EndDialog(m_throttle);
|
||||
}
|
||||
|
|
|
@ -149,6 +149,9 @@ void winOutput(const char *, u32);
|
|||
void (*dbgSignal)(int,int) = winSignal;
|
||||
void (*dbgOutput)(const char *, u32) = winOutput;
|
||||
|
||||
int lastSA = 0;
|
||||
int lastSR = 0;
|
||||
|
||||
#ifdef MMX
|
||||
extern "C" bool cpu_mmx;
|
||||
#endif
|
||||
|
@ -156,7 +159,7 @@ extern "C" bool cpu_mmx;
|
|||
namespace Sm60FPS
|
||||
{
|
||||
float K_fCpuSpeed = 100.0f; // was 98.0f before, but why?
|
||||
float K_fTargetFps = 60.0f * K_fCpuSpeed / 100;
|
||||
float K_fTargetFps = 60.0f * K_fCpuSpeed / 100.0f;
|
||||
float K_fDT = 1000.0f / K_fTargetFps;
|
||||
|
||||
u32 dwTimeElapse;
|
||||
|
@ -167,6 +170,7 @@ namespace Sm60FPS
|
|||
float fCurFPS;
|
||||
bool bLastSkip;
|
||||
int nCurSpeed;
|
||||
float nPrvSpeed;
|
||||
int bSaveMoreCPU;
|
||||
};
|
||||
|
||||
|
@ -336,8 +340,21 @@ VBA::VBA()
|
|||
}
|
||||
}
|
||||
|
||||
CString DataHex(const char *buf, int len) {
|
||||
CString dat = _T("");
|
||||
if(buf!=NULL && len>0) {
|
||||
for(int i=0; i<len; i++) {
|
||||
dat.AppendFormat(_T("%02X "), (byte)buf[i]);
|
||||
}
|
||||
}
|
||||
return dat;
|
||||
}
|
||||
|
||||
VBA::~VBA()
|
||||
{
|
||||
c_s.Lock();
|
||||
AppTerminated = true;
|
||||
c_s.Unlock();
|
||||
rpiCleanup();
|
||||
InterframeCleanup();
|
||||
|
||||
|
@ -352,6 +369,8 @@ VBA::~VBA()
|
|||
|
||||
JoyBusShutdown();
|
||||
|
||||
CloseLink(); //AdamN: closing connections gracefully
|
||||
|
||||
saveSettings();
|
||||
|
||||
if(moviePlaying) {
|
||||
|
@ -422,6 +441,8 @@ BOOL VBA::InitInstance()
|
|||
#endif
|
||||
#endif
|
||||
|
||||
//SetProcessAffinityMask(GetCurrentProcess(), 1); //AdamN: using only 1 CPU for all threads in this process for testing if there were bug caused by deadlock
|
||||
|
||||
SetRegistryKey(_T("VBA"));
|
||||
|
||||
remoteSetProtocol(0);
|
||||
|
@ -447,6 +468,7 @@ BOOL VBA::InitInstance()
|
|||
|
||||
if(!InitLink())
|
||||
return FALSE;
|
||||
lanlink.mode = NORMAL8;
|
||||
|
||||
bool force = false;
|
||||
|
||||
|
@ -839,18 +861,21 @@ void VBA::updateFilter()
|
|||
|
||||
void VBA::updateThrottle( unsigned short throttle )
|
||||
{
|
||||
//if(throttle>100 && synchronize) throttle = 100; //max speed when audio sync enabled is 100%
|
||||
|
||||
this->throttle = throttle;
|
||||
|
||||
if( throttle ) {
|
||||
Sm60FPS::K_fCpuSpeed = (float)throttle;
|
||||
Sm60FPS::K_fTargetFps = 60.0f * Sm60FPS::K_fCpuSpeed / 100;
|
||||
Sm60FPS::K_fDT = 1000.0f / Sm60FPS::K_fTargetFps;
|
||||
autoFrameSkip = false;
|
||||
/*autoFrameSkip = true;
|
||||
frameSkip = 0;
|
||||
systemFrameSkip = 0;
|
||||
gbFrameSkip = 0;
|
||||
systemFrameSkip = 0;*/
|
||||
}
|
||||
|
||||
soundSetThrottle(throttle);
|
||||
soundSetThrottle(throttle); //AdamN: only XAudio2 that have this feature? (added for OpenAL)
|
||||
}
|
||||
|
||||
|
||||
|
@ -1065,14 +1090,13 @@ void systemFrame()
|
|||
|
||||
void system10Frames(int rate)
|
||||
{
|
||||
|
||||
if( theApp.autoFrameSkip )
|
||||
{
|
||||
u32 time = systemGetClock();
|
||||
u32 diff = time - theApp.autoFrameSkipLastTime;
|
||||
theApp.autoFrameSkipLastTime = time;
|
||||
if( diff ) {
|
||||
// countermeasure against div/0 when debugging
|
||||
theApp.autoFrameSkipLastTime = time;
|
||||
Sm60FPS::nCurSpeed = (1000000/rate)/diff;
|
||||
} else {
|
||||
Sm60FPS::nCurSpeed = 100;
|
||||
|
@ -1112,6 +1136,96 @@ void system10Frames(int rate)
|
|||
#endif
|
||||
}
|
||||
|
||||
void system1Frames(int rate, int count) //AdamN: update skippedframes faster to make sure it didn't cause too many frames or too little frames being skipped
|
||||
{
|
||||
|
||||
if( theApp.autoFrameSkip ) //AdamN: CurSpeed might need to be updated regardless of autoframeskip for throttle to works properly w/o autoframeskip
|
||||
{
|
||||
theApp.autoFrameSkipCount++;
|
||||
u32 time = systemGetClock();
|
||||
u32 diff = time - theApp.autoFrameSkipLastTime;
|
||||
if( diff) {
|
||||
// countermeasure against div/0 when debugging
|
||||
int tm = (diff/theApp.autoFrameSkipCount);
|
||||
float cspd = (100000.0f/rate/*60.0f*/)/tm; //calc current speed smoothly (frame 1-10,2-11,3-12,so on)
|
||||
Sm60FPS::nCurSpeed = (int)cspd; //(500000/rate)/diff;
|
||||
if(theApp.autoFrameSkipCount >= 10) { //60
|
||||
theApp.autoFrameSkipCount--; //= 0; //to maintain 10 frames per update
|
||||
theApp.autoFrameSkipLastTime += tm ; //theApp.autoFrameSkipLastTime2;
|
||||
//theApp.autoFrameSkipLastTime2 += tm; //rough prediction of nextframe's time
|
||||
}/* else if(theApp.autoFrameSkipCount == 2)
|
||||
theApp.autoFrameSkipLastTime2 = time;*/
|
||||
//if(theApp.autoFrameSkip)
|
||||
{
|
||||
float tgtspd = Sm60FPS::K_fCpuSpeed;
|
||||
int maxfs = gbFrameSkip;
|
||||
if(theApp.cartridgeType == IMAGE_GBA) maxfs = frameSkip;
|
||||
//if(speedup && (count % 10)==0) theApp.updateThrottle(Sm60FPS::nCurSpeed); //update throttle on turbo, may slows down things
|
||||
//if(synchronize && tgtspd>100.0f) float tgtspd = 100.0f; //max speed when audio sync enabled is 100%, this is to prevent skippedframe piling up since CurSpeed never goes beyond 100
|
||||
if((systemFrameSkip < maxfs) && (Sm60FPS::nCurSpeed < tgtspd*0.94f/**0.89f *0.845f*/)) { //*0.7f
|
||||
/*if(maxfs==9) //special feature for auto-frameskip-cap=9
|
||||
if(Sm60FPS::nCurSpeed <= 1.01f*Sm60FPS::nPrvSpeed && systemFrameSkip>3) { //if frameskipping no longer effective, don't skip more
|
||||
systemFrameSkip--;
|
||||
//Sm60FPS::nPrvSpeed = 0.0f; //0.99f*Sm60FPS::nPrvSpeed;
|
||||
} else
|
||||
Sm60FPS::nPrvSpeed = (float)Sm60FPS::nCurSpeed;*/
|
||||
//frameSkip += 1;
|
||||
//gbFrameSkip += 1;
|
||||
systemFrameSkip += 1; //frames to skip for the next n frames
|
||||
} else
|
||||
if((systemFrameSkip > 0) && (Sm60FPS::nCurSpeed > tgtspd/**1.02f*//**1.1f *1.4f*/)) { //*1.07f
|
||||
//frameSkip -= 1;
|
||||
//gbFrameSkip -= 1;
|
||||
systemFrameSkip -= 1; //frames to skip for the next n frames
|
||||
}
|
||||
//Sm60FPS::nPrvSpeed = Sm60FPS::nCurSpeed;
|
||||
}
|
||||
//theApp.autoFrameSkipCount = 0;
|
||||
} else {
|
||||
/*if(theApp.autoFrameSkipCount == 2)
|
||||
theApp.autoFrameSkipLastTime2 = time;*/
|
||||
if(!Sm60FPS::nCurSpeed)
|
||||
Sm60FPS::nCurSpeed = (int)Sm60FPS::K_fCpuSpeed; //100;
|
||||
//frameSkip = 0;
|
||||
//gbFrameSkip = 0;
|
||||
//systemFrameSkip = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if((count % 10)!=0) return;
|
||||
|
||||
if(theApp.rewindMemory) {
|
||||
if(++theApp.rewindCounter >= (theApp.rewindTimer)) {
|
||||
theApp.rewindSaveNeeded = true;
|
||||
theApp.rewindCounter = 0;
|
||||
}
|
||||
}
|
||||
if(systemSaveUpdateCounter) {
|
||||
if(--systemSaveUpdateCounter <= SYSTEM_SAVE_NOT_UPDATED) {
|
||||
((MainWnd *)theApp.m_pMainWnd)->writeBatteryFile();
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
}
|
||||
}
|
||||
|
||||
theApp.wasPaused = false;
|
||||
|
||||
// Old autoframeskip crap... might be useful later. autoframeskip Ifdef above might be useless as well now
|
||||
// theApp.autoFrameSkipLastTime = time;
|
||||
|
||||
#ifdef LOG_PERFORMANCE
|
||||
if( systemSpeedCounter >= PERFORMANCE_INTERVAL ) {
|
||||
// log performance every PERFORMANCE_INTERVAL frames
|
||||
float a = 0.0f;
|
||||
for( unsigned short i = 0 ; i < PERFORMANCE_INTERVAL ; i++ ) {
|
||||
a += (float)systemSpeedTable[i];
|
||||
}
|
||||
a /= (float)PERFORMANCE_INTERVAL;
|
||||
log( _T("Speed: %f\n"), a );
|
||||
systemSpeedCounter = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void systemScreenMessage(const char *msg)
|
||||
{
|
||||
theApp.screenMessage = true;
|
||||
|
@ -1163,7 +1277,7 @@ SoundDriver * systemSoundInit()
|
|||
|
||||
if( drv ) {
|
||||
if (theApp.throttle)
|
||||
drv->setThrottle( theApp.throttle );
|
||||
drv->setThrottle( theApp.throttle ); //AdamN: XAudio2 seems the only one who has this feature?
|
||||
}
|
||||
|
||||
return drv;
|
||||
|
@ -1251,10 +1365,13 @@ BOOL VBA::OnIdle(LONG lCount)
|
|||
if(debugger)
|
||||
return TRUE; // continue loop
|
||||
return !::PeekMessage(&msg, NULL, NULL, NULL, PM_NOREMOVE);
|
||||
} else if(emulating && active && !paused) {
|
||||
} else if(emulating && (gba_link_enabled || active) && !paused) {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
emulator.emuMain(emulator.emuCount);
|
||||
if(lanlink.connected&&linkid&&lc.numtransfers==0) lc.CheckConn();
|
||||
emulator.emuMain(emulator.emuCount); //emuMain=CPULoop,emuCount=250000
|
||||
if(/*gba_link_enabled &&*/ lanlink.connected && linkid && lc.numtransfers==0 && (theApp.cartridgeType == IMAGE_GBA) && !rfu_enabled) {
|
||||
if(/*(i & 1) &&*/ !LinkHandlerActive)
|
||||
lc.CheckConn(); //AdamN: This is Needed for Client/Slave to works properly, but does it need to be called twice in the FOR loop?
|
||||
}
|
||||
|
||||
if(rewindSaveNeeded && rewindMemory && emulator.emuWriteMemState) {
|
||||
rewindCount++;
|
||||
|
@ -1622,6 +1739,8 @@ void VBA::loadSettings()
|
|||
|
||||
rfu_enabled = regQueryDwordValue("RFU", false) ? true : false;
|
||||
gba_link_enabled = regQueryDwordValue("linkEnabled", false) ? true : false;
|
||||
if(gba_link_enabled)
|
||||
gbSerialFunction = gbStartLink;
|
||||
gba_joybus_enabled = regQueryDwordValue("joybusEnabled", false) ? true : false;
|
||||
buffer = regQueryStringValue("joybusHostAddr", "");
|
||||
|
||||
|
@ -2620,11 +2739,11 @@ void Sm60FPS_Init()
|
|||
}
|
||||
|
||||
|
||||
bool Sm60FPS_CanSkipFrame()
|
||||
bool Sm60FPS_CanSkipFrame() //AdamN: autoframeskipping here doesn't seems to give much effect, more like only giving up to 1 frame skipped(per 10 frames) instead of up to 9 frames
|
||||
{
|
||||
if( theApp.autoFrameSkip ) {
|
||||
/*if( theApp.autoFrameSkip )*/ { //AdamN: this is the reason why throttle doesn't works properly w/o autoframeskip
|
||||
if( Sm60FPS::nFrameCnt == 0 ) {
|
||||
Sm60FPS::nFrameCnt = 0;
|
||||
//Sm60FPS::nFrameCnt = 0; //AdamN: is this really necessary?
|
||||
Sm60FPS::dwTimeElapse = 0;
|
||||
Sm60FPS::dwTime0 = GetTickCount();
|
||||
} else {
|
||||
|
@ -2634,14 +2753,18 @@ bool Sm60FPS_CanSkipFrame()
|
|||
|
||||
if( Sm60FPS::nCurSpeed > Sm60FPS::K_fCpuSpeed ) {
|
||||
Sm60FPS::fWantFPS += 1;
|
||||
if( Sm60FPS::fWantFPS > Sm60FPS::K_fTargetFps ){
|
||||
Sm60FPS::fWantFPS = Sm60FPS::K_fTargetFps;
|
||||
//frameSkip = 0;
|
||||
//systemFrameSkip = 0;
|
||||
if( Sm60FPS::fWantFPS > Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/ ){
|
||||
Sm60FPS::fWantFPS = Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/;
|
||||
}
|
||||
} else {
|
||||
if( Sm60FPS::nCurSpeed < (Sm60FPS::K_fCpuSpeed - 5) ) {
|
||||
if( Sm60FPS::nCurSpeed < (Sm60FPS::K_fCpuSpeed/**0.94f*/ /*- 5*/) ) {
|
||||
Sm60FPS::fWantFPS -= 1;
|
||||
if( Sm60FPS::fWantFPS < 30.f ) {
|
||||
Sm60FPS::fWantFPS = 30.f;
|
||||
//frameSkip += 1;
|
||||
//systemFrameSkip += 1;
|
||||
if( Sm60FPS::fWantFPS < 6.f/*30.f*/ ) {
|
||||
Sm60FPS::fWantFPS = 6.f/*30.f*/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2649,12 +2772,15 @@ bool Sm60FPS_CanSkipFrame()
|
|||
Sm60FPS::dwTime1 = GetTickCount();
|
||||
Sm60FPS::dwTimeElapse += (Sm60FPS::dwTime1 - Sm60FPS::dwTime0);
|
||||
Sm60FPS::dwTime0 = Sm60FPS::dwTime1;
|
||||
|
||||
if( !Sm60FPS::bLastSkip &&
|
||||
( (Sm60FPS::fWantFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU) ) {
|
||||
( (Sm60FPS::fWantFPS < Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/) || Sm60FPS::bSaveMoreCPU) ) {
|
||||
Sm60FPS::fCurFPS = (float)Sm60FPS::nFrameCnt * 1000 / Sm60FPS::dwTimeElapse;
|
||||
if( (Sm60FPS::fCurFPS < Sm60FPS::K_fTargetFps) || Sm60FPS::bSaveMoreCPU ) {
|
||||
if( (Sm60FPS::fCurFPS < Sm60FPS::K_fTargetFps/**(systemFrameSkip+1)*/) || Sm60FPS::bSaveMoreCPU ) {
|
||||
Sm60FPS::bLastSkip = true;
|
||||
Sm60FPS::nFrameCnt++;
|
||||
//frameSkip += 1;
|
||||
//systemFrameSkip += 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2662,16 +2788,20 @@ bool Sm60FPS_CanSkipFrame()
|
|||
}
|
||||
Sm60FPS::bLastSkip = false;
|
||||
Sm60FPS::nFrameCnt++;
|
||||
}
|
||||
//frameSkip = 0;
|
||||
//systemFrameSkip = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Sm60FPS_Sleep()
|
||||
{
|
||||
if( theApp.autoFrameSkip ) {
|
||||
if(!speedup) /*if( theApp.autoFrameSkip )*/ { //AdamN: this is the reason why throttle doesn't works properly w/o autoframeskip
|
||||
u32 dwTimePass = Sm60FPS::dwTimeElapse + (GetTickCount() - Sm60FPS::dwTime0);
|
||||
u32 dwTimeShould = (u32)(Sm60FPS::nFrameCnt * Sm60FPS::K_fDT);
|
||||
float kfdt = Sm60FPS::K_fDT;
|
||||
if(!theApp.autoFrameSkip) kfdt*=(systemFrameSkip+1);
|
||||
u32 dwTimeShould = (u32)(Sm60FPS::nFrameCnt * kfdt);
|
||||
if( dwTimeShould > dwTimePass ) {
|
||||
Sleep(dwTimeShould - dwTimePass);
|
||||
}
|
||||
|
|
|
@ -124,6 +124,8 @@ class VBA : public CWinApp
|
|||
bool tripleBuffering;
|
||||
unsigned short throttle;
|
||||
u32 autoFrameSkipLastTime;
|
||||
u32 autoFrameSkipLastTime2;
|
||||
int autoFrameSkipCount;
|
||||
bool autoFrameSkip;
|
||||
bool vsync;
|
||||
bool changingVideoSize;
|
||||
|
@ -255,6 +257,27 @@ class VBA : public CWinApp
|
|||
extern VBA theApp;
|
||||
extern int emulating;
|
||||
|
||||
extern bool AppTerminated; //AdamN: to mark Application is exiting for other threads to check
|
||||
extern CString DataHex(const char *buf, int len); //AdamN: buffer to hex string
|
||||
|
||||
namespace Sm60FPS
|
||||
{
|
||||
extern float K_fCpuSpeed; // was 98.0f before, but why?
|
||||
extern float K_fTargetFps;
|
||||
extern float K_fDT;
|
||||
|
||||
extern u32 dwTimeElapse;
|
||||
extern u32 dwTime0;
|
||||
extern u32 dwTime1;
|
||||
extern u32 nFrameCnt;
|
||||
extern float fWantFPS;
|
||||
extern float fCurFPS;
|
||||
extern bool bLastSkip;
|
||||
extern int nCurSpeed;
|
||||
extern float nPrvSpeed;
|
||||
extern int bSaveMoreCPU;
|
||||
};
|
||||
|
||||
#ifdef MMX
|
||||
extern "C" bool cpu_mmx;
|
||||
#endif
|
||||
|
|
|
@ -132,13 +132,14 @@ BEGIN
|
|||
CONTROL "Network",IDC_LINK_LAN,"Button",BS_AUTORADIOBUTTON,17,43,70,16
|
||||
END
|
||||
|
||||
IDD_LINKTAB2 DIALOG 0, 0, 210, 113
|
||||
IDD_LINKTAB2 DIALOGEX 0, 0, 210, 113
|
||||
STYLE DS_SETFONT | WS_CHILD
|
||||
FONT 8, "MS Sans Serif"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "2",IDC_LINK2P,"Button",BS_AUTORADIOBUTTON | WS_GROUP,46,16,21,13
|
||||
CONTROL "3",IDC_LINK3P,"Button",BS_AUTORADIOBUTTON,94,16,21,13
|
||||
CONTROL "4",IDC_LINK4P,"Button",BS_AUTORADIOBUTTON,142,16,21,13
|
||||
CONTROL "2",IDC_LINK2P,"Button",BS_AUTORADIOBUTTON | WS_GROUP,33,17,21,13
|
||||
CONTROL "3",IDC_LINK3P,"Button",BS_AUTORADIOBUTTON,73,17,21,13
|
||||
CONTROL "4",IDC_LINK4P,"Button",BS_AUTORADIOBUTTON,115,17,21,13
|
||||
CONTROL "5",IDC_LINK5P,"Button",BS_AUTORADIOBUTTON,156,17,21,13
|
||||
CONTROL "TCP/IP",IDC_LINKTCP,"Button",BS_AUTORADIOBUTTON | WS_GROUP,54,47,42,14
|
||||
CONTROL "UDP",IDC_LINKUDP,"Button",BS_AUTORADIOBUTTON | WS_DISABLED,121,47,33,14
|
||||
PUSHBUTTON "Start!",IDC_SERVERSTART,79,89,50,17
|
||||
|
@ -162,17 +163,17 @@ BEGIN
|
|||
CONTROL "On (fast)",IDC_SPEEDON,"Button",BS_AUTORADIOBUTTON,128,63,48,12
|
||||
END
|
||||
|
||||
IDD_SERVERWAIT DIALOG 0, 0, 186, 90
|
||||
IDD_SERVERWAIT DIALOGEX 0, 0, 186, 90
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Waiting for players"
|
||||
FONT 8, "MS Sans Serif"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
PUSHBUTTON "Cancel",IDCANCEL,63,69,50,14
|
||||
CONTROL "Progress1",IDC_SERVERWAIT,"msctls_progress32",WS_BORDER,33,50,120,13
|
||||
LTEXT "",IDC_STATIC1,7,7,154,8
|
||||
LTEXT "",IDC_STATIC2,7,17,105,8
|
||||
LTEXT "",IDC_STATIC3,7,25,105,8
|
||||
LTEXT "",IDC_STATIC4,7,33,105,8
|
||||
LTEXT "",IDC_STATIC1,7,7,178,8,SS_ENDELLIPSIS
|
||||
LTEXT "",IDC_STATIC2,7,17,175,8
|
||||
LTEXT "",IDC_STATIC3,7,25,175,8
|
||||
LTEXT "",IDC_STATIC4,7,33,175,8
|
||||
END
|
||||
|
||||
IDD_OPENDLG DIALOG 36, 24, 202, 117
|
||||
|
@ -740,10 +741,10 @@ BEGIN
|
|||
GROUPBOX "Sprite",IDC_STATIC,8,67,154,30
|
||||
END
|
||||
|
||||
IDD_DISASSEMBLE DIALOG 0, 0, 402, 225
|
||||
IDD_DISASSEMBLE DIALOGEX 0, 0, 402, 250
|
||||
STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
CAPTION "Disassemble"
|
||||
FONT 8, "MS Sans Serif"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "Automatic",IDC_AUTOMATIC,"Button",BS_AUTORADIOBUTTON | WS_GROUP,7,9,47,10
|
||||
CONTROL "ARM",IDC_ARM,"Button",BS_AUTORADIOBUTTON,62,9,32,10
|
||||
|
@ -800,6 +801,10 @@ BEGIN
|
|||
LTEXT "",IDC_MODE,376,176,20,8,SS_NOPREFIX
|
||||
SCROLLBAR IDC_VSCROLL,283,25,10,161,SBS_VERT
|
||||
PUSHBUTTON "Goto R15",IDC_GOPC,7,204,50,14
|
||||
CONTROL "Break at",IDC_BREAK_AT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,225,41,10
|
||||
EDITTEXT IDC_ADDRESS2,53,222,65,14,ES_UPPERCASE | ES_AUTOHSCROLL | WS_GROUP
|
||||
PUSHBUTTON "Step Into",IDC_STEPINTO,124,222,50,14
|
||||
CONTROL "Auto Step",IDC_AUTO_STEP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,179,225,47,10
|
||||
END
|
||||
|
||||
IDD_GDB_PORT DIALOG 0, 0, 186, 51
|
||||
|
@ -823,13 +828,12 @@ BEGIN
|
|||
LTEXT "",IDC_PORT,143,7,36,8,SS_NOPREFIX
|
||||
END
|
||||
|
||||
IDD_LOGGING DIALOGEX 0, 0, 382, 220
|
||||
IDD_LOGGING DIALOGEX 0, 0, 382, 257
|
||||
STYLE DS_SETFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
|
||||
EXSTYLE WS_EX_TOOLWINDOW
|
||||
CAPTION "Logging"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
BEGIN
|
||||
CONTROL "SWI",IDC_VERBOSE_SWI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,18,90,12
|
||||
CONTROL "Unaligned memory",IDC_VERBOSE_UNALIGNED_ACCESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,36,90,12
|
||||
CONTROL "Illegal write",IDC_VERBOSE_ILLEGAL_WRITE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,54,90,12
|
||||
CONTROL "Illegal read",IDC_VERBOSE_ILLEGAL_READ,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,72,90,12
|
||||
|
@ -839,12 +843,15 @@ BEGIN
|
|||
CONTROL "DMA 3",IDC_VERBOSE_DMA3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,144,90,12
|
||||
CONTROL "Undefined instruction",IDC_VERBOSE_UNDEFINED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,162,90,12
|
||||
CONTROL "AGBPrint",IDC_VERBOSE_AGBPRINT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,180,90,12
|
||||
EDITTEXT IDC_LOG,114,6,258,192,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
|
||||
PUSHBUTTON "Save...",IDC_SAVE,114,204,48,12
|
||||
PUSHBUTTON "Clear",IDC_CLEAR,168,204,48,12
|
||||
DEFPUSHBUTTON "OK",ID_OK,324,204,48,12
|
||||
GROUPBOX "Verbose",IDC_STATIC,6,6,102,210
|
||||
EDITTEXT IDC_LOG,114,6,258,226,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | WS_HSCROLL
|
||||
PUSHBUTTON "Save...",IDC_SAVE,113,238,48,12
|
||||
PUSHBUTTON "Clear",IDC_CLEAR,171,238,48,12
|
||||
DEFPUSHBUTTON "OK",ID_OK,327,238,48,12
|
||||
GROUPBOX "Verbose",IDC_STATIC,6,7,102,243
|
||||
CONTROL "Sound output",IDC_VERBOSE_SOUNDOUTPUT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,198,90,12
|
||||
CONTROL "SIO",IDC_VERBOSE_SIO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,216,90,12
|
||||
CONTROL "Link",IDC_VERBOSE_LINK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,233,90,12
|
||||
CONTROL "SWI",IDC_VERBOSE_SWI,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,19,90,12
|
||||
END
|
||||
|
||||
IDD_EXPORT_SPS DIALOGEX 0, 0, 248, 148
|
||||
|
@ -1238,6 +1245,14 @@ BEGIN
|
|||
BOTTOMMARGIN, 107
|
||||
END
|
||||
|
||||
IDD_LINKTAB2, DIALOG
|
||||
BEGIN
|
||||
END
|
||||
|
||||
IDD_SERVERWAIT, DIALOG
|
||||
BEGIN
|
||||
END
|
||||
|
||||
IDD_OPENDLG, DIALOG
|
||||
BEGIN
|
||||
RIGHTMARGIN, 165
|
||||
|
@ -1424,7 +1439,7 @@ BEGIN
|
|||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 396
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 218
|
||||
BOTTOMMARGIN, 243
|
||||
END
|
||||
|
||||
IDD_GDB_PORT, DIALOG
|
||||
|
@ -1448,7 +1463,7 @@ BEGIN
|
|||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 375
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 213
|
||||
BOTTOMMARGIN, 250
|
||||
END
|
||||
|
||||
IDD_EXPORT_SPS, DIALOG
|
||||
|
@ -1687,7 +1702,7 @@ BEGIN
|
|||
BEGIN
|
||||
MENUITEM "&Battery file...", ID_FILE_IMPORT_BATTERYFILE
|
||||
MENUITEM "Gameshark &code file...", ID_FILE_IMPORT_GAMESHARKCODEFILE
|
||||
MENUITEM "&Gameshark/Pro Action Replay Snapshot...", ID_FILE_IMPORT_GAMESHARKSNAPSHOT
|
||||
MENUITEM "&Gameshark/Pro Action Replay Snapshot...", ID_FILE_IMPORT_GAMESHARKSNAPSHOT
|
||||
END
|
||||
POPUP "Export"
|
||||
BEGIN
|
||||
|
@ -2225,13 +2240,21 @@ BEGIN
|
|||
IDS_LOADED_CHEATS "Loaded cheats"
|
||||
IDS_ERROR_DISP_COLOR "Unsupported display setting for color depth: %d bits. \nWindows desktop must be in either 16-bit, 24-bit or 32-bit mode for this program to work in window mode."
|
||||
IDS_ADD_GSA_CODE "Add GameSharkAdvance code"
|
||||
IDS_FILTER_GSVSPS "GS & PAC Snapshots (*.SPS;*.XPS)_*.SPS;*.XPS_GameShark SP Snapshots (*.GSV)_*.gsv__"
|
||||
IDS_FILTER_SPS "Gameshark Snapshot_*.SPS__"
|
||||
IDS_SELECT_SNAPSHOT_FILE "Select snapshot file"
|
||||
IDS_FILTER_SAV "Battery file_*.SAV_Flash save_*.DAT__"
|
||||
IDS_SELECT_BATTERY_FILE "Select battery file"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_INVALID_INTERVAL_VALUE
|
||||
"Invalid rewind interval value. Please enter a number between 0 and 600 seconds."
|
||||
IDS_REGISTRY "VisualBoyAdvance no longer uses the registry to store its settings. Your previous settings have been exported into the file: %s"
|
||||
IDS_MOVIE_PLAY "Playing a movie will load a save state which may erase your previous battery saves. Please be sure to have a saved state if you don't want to loose any previous data."
|
||||
IDS_FILTER_GSVSPS "GS & PAC Snapshots (*.SPS;*.XPS)_*.SPS;*.XPS_GameShark SP Snapshots (*.GSV)_*.gsv__"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_UNSUPPORTED_CHEAT_LIST_TYPE "Unsupported cheat list type %d"
|
||||
|
@ -2292,14 +2315,6 @@ BEGIN
|
|||
IDS_END_OF_MOVIE "end of movie"
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_INVALID_INTERVAL_VALUE
|
||||
"Invalid rewind interval value. Please enter a number between 0 and 600 seconds."
|
||||
IDS_REGISTRY "VisualBoyAdvance no longer uses the registry to store its settings. Your previous settings have been exported into the file: %s"
|
||||
IDS_MOVIE_PLAY "Playing a movie will load a save state which may erase your previous battery saves. Please be sure to have a saved state if you don't want to loose any previous data."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_OAL_NODEVICE "There are no sound devices present on this system."
|
||||
|
|
|
@ -278,6 +278,8 @@ bool XAudio2_Output::init(long sampleRate)
|
|||
|
||||
|
||||
initialized = true;
|
||||
|
||||
setThrottle(theApp.throttle); //AdamN: setting sound pitch to current throttle
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -303,7 +305,7 @@ void XAudio2_Output::write(u16 * finalWave, int length)
|
|||
break;
|
||||
} else {
|
||||
// the maximum number of buffers is currently queued
|
||||
if( synchronize && !speedup && !theApp.throttle ) {
|
||||
if( synchronize && !speedup /*&& !theApp.throttle*/ ) {
|
||||
// wait for one buffer to finish playing
|
||||
WaitForSingleObject( notify.hBufferEndEvent, INFINITE );
|
||||
} else {
|
||||
|
|
|
@ -150,6 +150,7 @@
|
|||
#define IDC_C_FLAG 1020
|
||||
#define IDC_CONTINUE 1020
|
||||
#define IDC_SAVE_DIR 1020
|
||||
#define IDC_STEPINTO 1020
|
||||
#define IDC_V_FLAG 1021
|
||||
#define IDC_CAPTURE_DIR 1021
|
||||
#define IDC_CHEAT_LIST 1021
|
||||
|
@ -215,6 +216,7 @@
|
|||
#define IDS_VALUE_CANNOT_BE_EMPTY 1042
|
||||
#define IDS_ERROR_ON_STARTDOC 1043
|
||||
#define IDC_R 1043
|
||||
#define IDC_ADDRESS2 1043
|
||||
#define IDS_ERROR_ON_STARTPAGE 1044
|
||||
#define IDC_G 1044
|
||||
#define IDS_ERROR_PRINTING_ON_STRETCH 1045
|
||||
|
@ -459,6 +461,8 @@
|
|||
#define IDC_ARM 1200
|
||||
#define IDC_THUMB 1201
|
||||
#define IDC_AUTO_UPDATE 1204
|
||||
#define IDC_BREAK_AT 1205
|
||||
#define IDC_AUTO_STEP 1206
|
||||
#define IDC_N 1210
|
||||
#define IDC_Z 1211
|
||||
#define IDC_C 1212
|
||||
|
@ -491,6 +495,8 @@
|
|||
#define IDC_VERBOSE_SOUNDOUTPUT 1235
|
||||
#define IDC_NOTES 1236
|
||||
#define IDC_CURRENT_ADDRESS_LABEL 1236
|
||||
#define IDC_VERBOSE_SIO 1236
|
||||
#define IDC_VERBOSE_LINK 1237
|
||||
#define IDC_LOAD 1238
|
||||
#define IDC_SIZE_CONTROL 1240
|
||||
#define IDC_MODES 1240
|
||||
|
@ -841,6 +847,7 @@
|
|||
#define IDC_LINK3P 40325
|
||||
#define IDC_LINK4P 40326
|
||||
#define IDC_CLINKUDP 40327
|
||||
#define IDC_LINK5P 40327
|
||||
#define IDC_SPEEDON 40328
|
||||
#define ID_OPTIONS_EMULATOR_REMOVEINTROSGBA 40331
|
||||
#define ID_Menu 40332
|
||||
|
|
Loading…
Reference in New Issue