mirror of
https://github.com/dborth/vbagx.git
synced 2024-11-29 14:04:16 +01:00
475 lines
10 KiB
C++
475 lines
10 KiB
C++
/****************************************************************************
|
|
* Visual Boy Advance GX
|
|
*
|
|
* Tantric September 2008
|
|
*
|
|
* vbasupport.cpp
|
|
*
|
|
* VBA support code
|
|
***************************************************************************/
|
|
|
|
#include <gccore.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "agb/GBA.h"
|
|
#include "agb/agbprint.h"
|
|
#include "Flash.h"
|
|
#include "Port.h"
|
|
#include "RTC.h"
|
|
#include "Sound.h"
|
|
#include "unzip.h"
|
|
#include "Util.h"
|
|
#include "dmg/GB.h"
|
|
#include "dmg/gbGlobals.h"
|
|
|
|
#include "vba.h"
|
|
#include "fileop.h"
|
|
#include "audio.h"
|
|
#include "vmmem.h"
|
|
#include "input.h"
|
|
#include "video.h"
|
|
#include "menudraw.h"
|
|
|
|
extern "C"
|
|
{
|
|
#include "tbtime.h"
|
|
#include "sdfileio.h"
|
|
}
|
|
|
|
static tb_t start, now;
|
|
|
|
u32 loadtimeradjust;
|
|
|
|
static u32 autoFrameSkipLastTime = 0;
|
|
static int frameskipadjust = 0;
|
|
|
|
int vAspect = 0;
|
|
int hAspect = 0;
|
|
|
|
/****************************************************************************
|
|
* VBA Globals
|
|
***************************************************************************/
|
|
int RGB_LOW_BITS_MASK=0x821;
|
|
int systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
|
|
|
int systemDebug = 0;
|
|
int emulating = 0;
|
|
|
|
int sensorX = 2047;
|
|
int sensorY = 2047;
|
|
|
|
int systemFrameSkip = 0;
|
|
bool systemSoundOn = false;
|
|
int systemVerbose = 0;
|
|
int cartridgeType = 0;
|
|
int srcWidth = 0;
|
|
int srcHeight = 0;
|
|
int destWidth = 0;
|
|
int destHeight = 0;
|
|
int srcPitch = 0;
|
|
int saveExists = 0;
|
|
int systemRedShift = 0;
|
|
int systemBlueShift = 0;
|
|
int systemGreenShift = 0;
|
|
int systemColorDepth = 0;
|
|
u16 systemGbPalette[24];
|
|
u16 systemColorMap16[0x10000];
|
|
//u32 systemColorMap32[0x10000];
|
|
u32 *systemColorMap32 = (u32 *)&systemColorMap16;
|
|
|
|
struct EmulatedSystem emulator =
|
|
{
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
false,
|
|
0
|
|
};
|
|
|
|
/****************************************************************************
|
|
* systemGetClock
|
|
*
|
|
* Returns number of milliseconds since program start
|
|
****************************************************************************/
|
|
u32 systemGetClock( void )
|
|
{
|
|
mftb(&now);
|
|
return tb_diff_msec(&now, &start) - loadtimeradjust;
|
|
}
|
|
|
|
void systemFrame() {}
|
|
void systemScreenCapture(int a) {}
|
|
void systemShowSpeed(int speed) {}
|
|
void systemGbBorderOn() {}
|
|
|
|
bool systemPauseOnFrame()
|
|
{
|
|
return false;
|
|
}
|
|
/*
|
|
void GC_Sleep(u32 dwMiliseconds)
|
|
{
|
|
int nVBlanks = (dwMiliseconds / 16);
|
|
while (nVBlanks-- > 0)
|
|
{
|
|
VIDEO_WaitVSync();
|
|
}
|
|
}
|
|
*/
|
|
void system10Frames(int rate)
|
|
{
|
|
if ( cartridgeType == 1 )
|
|
return;
|
|
|
|
u32 time = systemGetClock();
|
|
u32 diff = time - autoFrameSkipLastTime;
|
|
int speed = 100;
|
|
|
|
if(diff)
|
|
speed = (1000000/rate)/diff;
|
|
/* char temp[512];
|
|
sprintf(temp,"Speed: %i",speed);
|
|
MENU_DrawString( -1, 450,temp , 1 ); */
|
|
|
|
if(speed >= 98)
|
|
{
|
|
frameskipadjust++;
|
|
|
|
if(frameskipadjust >= 3)
|
|
{
|
|
frameskipadjust=0;
|
|
if(systemFrameSkip > 0)
|
|
systemFrameSkip--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(speed < 80)
|
|
frameskipadjust -= (90 - speed)/5;
|
|
else if(systemFrameSkip < 9)
|
|
frameskipadjust--;
|
|
|
|
if(frameskipadjust <= -2)
|
|
{
|
|
frameskipadjust += 2;
|
|
if(systemFrameSkip < 9)
|
|
systemFrameSkip++;
|
|
}
|
|
}
|
|
|
|
autoFrameSkipLastTime = time;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* System
|
|
****************************************************************************/
|
|
|
|
void systemGbPrint(u8 *data,int pages,int feed,int palette, int contrast) {}
|
|
void debuggerOutput(const char *s, u32 addr) {}
|
|
void (*dbgOutput)(const char *s, u32 addr) = debuggerOutput;
|
|
void systemMessage(int num, const char *msg, ...) {}
|
|
|
|
/****************************************************************************
|
|
* Saves
|
|
****************************************************************************/
|
|
|
|
bool LoadBattery(int method, bool silent)
|
|
{
|
|
char filepath[1024];
|
|
bool result = false;
|
|
|
|
ShowAction ((char*) "Loading...");
|
|
|
|
if(method == METHOD_AUTO)
|
|
method = autoSaveMethod(); // we use 'Save' because we need R/W
|
|
|
|
if(method == METHOD_SD || method == METHOD_USB)
|
|
{
|
|
ChangeFATInterface(method, NOTSILENT);
|
|
sprintf (filepath, "%s/%s/%s.sav", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename);
|
|
result = emulator.emuReadBattery(filepath);
|
|
}
|
|
|
|
if(!result && !silent)
|
|
WaitPrompt ((char*) "Save file not found");
|
|
|
|
return result;
|
|
}
|
|
|
|
bool SaveBattery(int method, bool silent)
|
|
{
|
|
char filepath[1024];
|
|
bool result = false;
|
|
|
|
ShowAction ((char*) "Saving...");
|
|
|
|
if(method == METHOD_AUTO)
|
|
method = autoSaveMethod(); // we use 'Save' because we need R/W
|
|
|
|
if(method == METHOD_SD || method == METHOD_USB)
|
|
{
|
|
ChangeFATInterface(method, NOTSILENT);
|
|
sprintf (filepath, "%s/%s/%s.sav", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename);
|
|
result = emulator.emuWriteBattery(filepath);
|
|
}
|
|
|
|
if(!silent)
|
|
{
|
|
if(result)
|
|
WaitPrompt ((char*) "Save successful");
|
|
else
|
|
WaitPrompt ((char*) "Save failed");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool LoadState(int method, bool silent)
|
|
{
|
|
char filepath[1024];
|
|
bool result = false;
|
|
|
|
ShowAction ((char*) "Loading...");
|
|
|
|
if(method == METHOD_AUTO)
|
|
method = autoSaveMethod(); // we use 'Save' because we need R/W
|
|
|
|
if(method == METHOD_SD || method == METHOD_USB)
|
|
{
|
|
ChangeFATInterface(method, NOTSILENT);
|
|
sprintf (filepath, "%s/%s/%s.sgm", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename);
|
|
result = emulator.emuReadState(filepath);
|
|
}
|
|
|
|
if(!result && !silent)
|
|
WaitPrompt ((char*) "State file not found");
|
|
|
|
return result;
|
|
}
|
|
|
|
bool SaveState(int method, bool silent)
|
|
{
|
|
char filepath[1024];
|
|
bool result = false;
|
|
|
|
ShowAction ((char*) "Saving...");
|
|
|
|
if(method == METHOD_AUTO)
|
|
method = autoSaveMethod(); // we use 'Save' because we need R/W
|
|
|
|
if(method == METHOD_SD || method == METHOD_USB)
|
|
{
|
|
ChangeFATInterface(method, NOTSILENT);
|
|
sprintf (filepath, "%s/%s/%s.sgm", ROOTFATDIR, GCSettings.SaveFolder, ROMFilename);
|
|
result = emulator.emuWriteState(filepath);
|
|
}
|
|
|
|
if(!silent)
|
|
{
|
|
if(result)
|
|
WaitPrompt ((char*) "Save successful");
|
|
else
|
|
WaitPrompt ((char*) "Save failed");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Sound
|
|
****************************************************************************/
|
|
|
|
void systemWriteDataToSoundBuffer()
|
|
{
|
|
MIXER_AddSamples((u8 *)soundFinalWave, (cartridgeType == 1));
|
|
}
|
|
|
|
bool systemSoundInit()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
bool systemCanChangeSoundQuality()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
void systemSoundPause() {}
|
|
void systemSoundResume() {}
|
|
void systemSoundReset() {}
|
|
void systemSoundShutdown() {}
|
|
|
|
/****************************************************************************
|
|
* systemReadJoypads
|
|
****************************************************************************/
|
|
bool systemReadJoypads()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
u32 systemReadJoypad(int which)
|
|
{
|
|
return GetJoy();
|
|
}
|
|
|
|
/****************************************************************************
|
|
* systemDrawScreen
|
|
****************************************************************************/
|
|
void systemDrawScreen()
|
|
{
|
|
// GB / GBC Have oodles of time - so sync on VSync
|
|
GX_Render( srcWidth, srcHeight, pix, srcPitch );
|
|
|
|
#ifdef HW_RVL
|
|
VIDEO_WaitVSync ();
|
|
#else
|
|
if ( cartridgeType == 1 )
|
|
{
|
|
VIDEO_WaitVSync();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int loadVBAROM(char filename[])
|
|
{
|
|
cartridgeType = 0;
|
|
srcWidth = 0;
|
|
srcHeight = 0;
|
|
destWidth = 0;
|
|
destHeight = 0;
|
|
srcPitch = 0;
|
|
|
|
IMAGE_TYPE type = utilFindType(filename);
|
|
|
|
switch( type )
|
|
{
|
|
case IMAGE_GBA:
|
|
//WaitPrompt("GameBoy Advance Image");
|
|
cartridgeType = 2;
|
|
emulator = GBASystem;
|
|
srcWidth = 240;
|
|
srcHeight = 160;
|
|
VMCPULoadROM(filename);
|
|
// Actual Visual Aspect is 1.57
|
|
hAspect = 70;
|
|
vAspect = 46;
|
|
srcPitch = 484;
|
|
soundQuality = 2;
|
|
soundBufferLen = 1470;
|
|
cpuSaveType = 0;
|
|
break;
|
|
|
|
case IMAGE_GB:
|
|
//WaitPrompt("GameBoy Image");
|
|
cartridgeType = 1;
|
|
emulator = GBSystem;
|
|
srcWidth = 160;
|
|
srcHeight = 144;
|
|
gbLoadRom(filename);
|
|
// Actual physical aspect is 1.0
|
|
hAspect = 60;
|
|
vAspect = 46;
|
|
srcPitch = 324;
|
|
soundQuality = 1;
|
|
soundBufferLen = 1470 * 2;
|
|
break;
|
|
|
|
default:
|
|
WaitPrompt((char *)"Unknown Image");
|
|
return 0;
|
|
break;
|
|
}
|
|
|
|
// Set defaults
|
|
flashSetSize(0x20000); // 128K saves
|
|
rtcEnable(true);
|
|
agbPrintEnable(false);
|
|
soundOffFlag = false;
|
|
soundLowPass = true;
|
|
|
|
// Setup GX
|
|
GX_Render_Init( srcWidth, srcHeight, hAspect, vAspect );
|
|
|
|
if ( cartridgeType == 1 )
|
|
{
|
|
gbSoundReset();
|
|
gbSoundSetQuality(soundQuality);
|
|
}
|
|
else
|
|
{
|
|
soundSetQuality(soundQuality);
|
|
CPUInit("/VBA/BIOS/BIOS.GBA", 1);
|
|
CPUReset();
|
|
}
|
|
|
|
soundVolume = 0;
|
|
systemSoundOn = true;
|
|
|
|
soundInit();
|
|
|
|
emulating = 1;
|
|
|
|
// reset frameskip variables
|
|
autoFrameSkipLastTime = frameskipadjust = systemFrameSkip = 0;
|
|
|
|
// Start system clock
|
|
mftb(&start);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* EEPROM
|
|
****************************************************************************/
|
|
int systemGetSensorX()
|
|
{
|
|
return sensorX;
|
|
}
|
|
|
|
int systemGetSensorY()
|
|
{
|
|
return sensorY;
|
|
}
|
|
|
|
void systemUpdateMotionSensor() {}
|
|
|
|
/****************************************************************************
|
|
* Palette
|
|
****************************************************************************/
|
|
|
|
void InitialisePalette()
|
|
{
|
|
int i;
|
|
// Build GBPalette
|
|
for( i = 0; i < 24; )
|
|
{
|
|
systemGbPalette[i++] = (0x1f) | (0x1f << 5) | (0x1f << 10);
|
|
systemGbPalette[i++] = (0x15) | (0x15 << 5) | (0x15 << 10);
|
|
systemGbPalette[i++] = (0x0c) | (0x0c << 5) | (0x0c << 10);
|
|
systemGbPalette[i++] = 0;
|
|
}
|
|
// Set palette etc - Fixed to RGB565
|
|
systemColorDepth = 16;
|
|
systemRedShift = 11;
|
|
systemGreenShift = 6;
|
|
systemBlueShift = 0;
|
|
for(i = 0; i < 0x10000; i++)
|
|
{
|
|
systemColorMap16[i] =
|
|
((i & 0x1f) << systemRedShift) |
|
|
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
|
(((i & 0x7c00) >> 10) << systemBlueShift);
|
|
}
|
|
}
|