bizswan: rotated display, lag frames, stuff

This commit is contained in:
goyuken 2014-05-30 20:53:52 +00:00
parent cc4df67923
commit 14f0faf7ff
12 changed files with 108 additions and 76 deletions

View File

@ -139,7 +139,7 @@ namespace BizHawk.Client.Common
using (var file = new HawkFile()) using (var file = new HawkFile())
{ {
var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64" }; var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC" };
// lets not use this unless we need to // lets not use this unless we need to
// file.NonArchiveExtensions = romExtensions; // file.NonArchiveExtensions = romExtensions;

View File

@ -41,8 +41,9 @@ namespace BizHawk.Emulation.Cores.WonderSwan
/// <param name="surface">uint32 video output buffer</param> /// <param name="surface">uint32 video output buffer</param>
/// <param name="soundbuff">int16 sound output buffer</param> /// <param name="soundbuff">int16 sound output buffer</param>
/// <param name="soundbuffsize">[In] max hold size of soundbuff [Out] number of samples actually deposited</param> /// <param name="soundbuffsize">[In] max hold size of soundbuff [Out] number of samples actually deposited</param>
/// <returns>true if lagged</returns>
[DllImport(dd, CallingConvention = cc)] [DllImport(dd, CallingConvention = cc)]
public static extern void bizswan_advance(IntPtr core, Buttons buttons, bool novideo, int[] surface, short[] soundbuff, ref int soundbuffsize); public static extern bool bizswan_advance(IntPtr core, Buttons buttons, bool novideo, int[] surface, short[] soundbuff, ref int soundbuffsize);
/// <summary> /// <summary>
/// load rom /// load rom
@ -51,9 +52,10 @@ namespace BizHawk.Emulation.Cores.WonderSwan
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="length"></param> /// <param name="length"></param>
/// <param name="settings"></param> /// <param name="settings"></param>
/// <param name="IsRotated">(out) true if screen is rotated left 90</param>
/// <returns></returns> /// <returns></returns>
[DllImport(dd, CallingConvention = cc)] [DllImport(dd, CallingConvention = cc)]
public static extern bool bizswan_load(IntPtr core, byte[] data, int length, [In] ref SyncSettings settings); public static extern bool bizswan_load(IntPtr core, byte[] data, int length, [In] ref SyncSettings settings, ref bool IsRotated);
/// <summary> /// <summary>
/// get size of saveram /// get size of saveram
@ -95,8 +97,8 @@ namespace BizHawk.Emulation.Cores.WonderSwan
DownY = 0x0040, DownY = 0x0040,
LeftY = 0x0080, LeftY = 0x0080,
Start = 0x0100, Start = 0x0100,
B = 0x0200, A = 0x0200,
A = 0x0400, B = 0x0400,
} }
public enum Language : byte public enum Language : byte
@ -131,8 +133,6 @@ namespace BizHawk.Emulation.Cores.WonderSwan
public Gender sex; public Gender sex;
public Bloodtype blood; public Bloodtype blood;
[MarshalAs(UnmanagedType.U1)] [MarshalAs(UnmanagedType.U1)]
public bool rotateinput;
[MarshalAs(UnmanagedType.U1)]
public bool color; // true for color system public bool color; // true for color system
[MarshalAs(UnmanagedType.U1)] [MarshalAs(UnmanagedType.U1)]
public bool userealtime; // true for use real real RTC instead of emulation pegged time public bool userealtime; // true for use real real RTC instead of emulation pegged time

View File

@ -54,20 +54,23 @@ namespace BizHawk.Emulation.Cores.WonderSwan
sex = BizSwan.Gender.Male, sex = BizSwan.Gender.Male,
blood = BizSwan.Bloodtype.A, blood = BizSwan.Bloodtype.A,
language = BizSwan.Language.Japanese, language = BizSwan.Language.Japanese,
rotateinput = false, // TODO
bday = 5, bday = 5,
bmonth = 12, bmonth = 12,
byear = 1968 byear = 1968
}; };
ss.SetName("LaForge"); ss.SetName("LaForge");
if (!BizSwan.bizswan_load(Core, rom, rom.Length, ref ss)) bool rotate = false;
if (!BizSwan.bizswan_load(Core, rom, rom.Length, ref ss, ref rotate))
throw new InvalidOperationException("bizswan_load() returned FALSE!"); throw new InvalidOperationException("bizswan_load() returned FALSE!");
CoreComm.VsyncNum = 3072000; // master CPU clock, also pixel clock CoreComm.VsyncNum = 3072000; // master CPU clock, also pixel clock
CoreComm.VsyncDen = (144 + 15) * (224 + 32); // 144 vislines, 15 vblank lines; 224 vispixels, 32 hblank pixels CoreComm.VsyncDen = (144 + 15) * (224 + 32); // 144 vislines, 15 vblank lines; 224 vispixels, 32 hblank pixels
saverambuff = new byte[BizSwan.bizswan_saveramsize(Core)]; saverambuff = new byte[BizSwan.bizswan_saveramsize(Core)];
InitVideo(rotate);
} }
catch catch
{ {
@ -94,12 +97,11 @@ namespace BizHawk.Emulation.Cores.WonderSwan
BizSwan.bizswan_reset(Core); BizSwan.bizswan_reset(Core);
int soundbuffsize = sbuff.Length; int soundbuffsize = sbuff.Length;
BizSwan.bizswan_advance(Core, GetButtons(), !render, vbuff, sbuff, ref soundbuffsize); IsLagFrame = BizSwan.bizswan_advance(Core, GetButtons(), !render, vbuff, sbuff, ref soundbuffsize);
if (soundbuffsize == sbuff.Length) if (soundbuffsize == sbuff.Length)
throw new Exception(); throw new Exception();
sbuffcontains = soundbuffsize; sbuffcontains = soundbuffsize;
IsLagFrame = false; // TODO
if (IsLagFrame) if (IsLagFrame)
LagCount++; LagCount++;
} }
@ -226,6 +228,20 @@ namespace BizHawk.Emulation.Cores.WonderSwan
public IVideoProvider VideoProvider { get { return this; } } public IVideoProvider VideoProvider { get { return this; } }
void InitVideo(bool rotate)
{
if (rotate)
{
BufferWidth = 144;
BufferHeight = 224;
}
else
{
BufferWidth = 224;
BufferHeight = 144;
}
}
private int[] vbuff = new int[224 * 144]; private int[] vbuff = new int[224 * 144];
public int[] GetVideoBuffer() public int[] GetVideoBuffer()
@ -233,10 +249,10 @@ namespace BizHawk.Emulation.Cores.WonderSwan
return vbuff; return vbuff;
} }
public int VirtualWidth { get { return 224; } } public int VirtualWidth { get { return BufferWidth; } }
public int VirtualHeight { get { return 144; } } public int VirtualHeight { get { return BufferHeight; } }
public int BufferWidth { get { return 224; } } public int BufferWidth { get; private set; }
public int BufferHeight { get { return 144; } } public int BufferHeight { get; private set; }
public int BackgroundColor { get { return unchecked((int)0xff000000); } } public int BackgroundColor { get { return unchecked((int)0xff000000); } }
#endregion #endregion

Binary file not shown.

View File

@ -154,18 +154,17 @@ namespace MDFN_IEN_WSWAN
bool GFX::ExecuteLine(uint32 *surface, bool skip) bool GFX::ExecuteLine(uint32 *surface, bool skip)
{ {
//static const void* const WEP_Tab[3] = { &&WEP0, &&WEP1, &&WEP2 }; // The things we do for debugger step mode save states! If we ever add more entries, remember to change the mask stuff in StateAction bool ret = false; // true if we finish frame here
bool ret;
// weppy = 0;
//WEP0: ;
ret = FALSE;
if(wsLine < 144) if(wsLine < 144)
{ {
if(!skip) if(!skip)
Scanline(surface + wsLine * 224); {
if (sys->rotate)
Scanline(surface + 223 * 144 + wsLine);
else
Scanline(surface + wsLine * 224);
}
} }
sys->memory.CheckSoundDMA(); sys->memory.CheckSoundDMA();
@ -183,7 +182,7 @@ namespace MDFN_IEN_WSWAN
if(wsLine == 144) if(wsLine == 144)
{ {
ret = TRUE; ret = true;
sys->interrupt.DoInterrupt(WSINT_VBLANK); sys->interrupt.DoInterrupt(WSINT_VBLANK);
//printf("VBlank: %d\n", wsLine); //printf("VBlank: %d\n", wsLine);
} }
@ -201,10 +200,9 @@ namespace MDFN_IEN_WSWAN
} }
} }
// weppy = 1; // CPU ==========================
sys->cpu.execute(224); sys->cpu.execute(224);
// goto *WEP_Tab[weppy]; // CPU ==========================
//WEP1: ;
wsLine = (wsLine + 1) % 159; wsLine = (wsLine + 1) % 159;
if(wsLine == LineCompare) if(wsLine == LineCompare)
@ -213,10 +211,9 @@ namespace MDFN_IEN_WSWAN
//printf("Line hit: %d\n", wsLine); //printf("Line hit: %d\n", wsLine);
} }
// weppy = 2; // CPU ==========================
sys->cpu.execute(32); sys->cpu.execute(32);
// goto *WEP_Tab[weppy]; // CPU ==========================
//WEP2: ;
sys->rtc.Clock(256); sys->rtc.Clock(256);
@ -236,8 +233,7 @@ namespace MDFN_IEN_WSWAN
wsLine = 0; wsLine = 0;
} }
// weppy = 0; return ret;
return(ret);
} }
void GFX::SetLayerEnableMask(uint32 mask) void GFX::SetLayerEnableMask(uint32 mask)
@ -248,7 +244,9 @@ namespace MDFN_IEN_WSWAN
void GFX::SetPixelFormat() void GFX::SetPixelFormat()
{ {
for(int r = 0; r < 16; r++) for(int r = 0; r < 16; r++)
{
for(int g = 0; g < 16; g++) for(int g = 0; g < 16; g++)
{
for(int b = 0; b < 16; b++) for(int b = 0; b < 16; b++)
{ {
uint32 neo_r, neo_g, neo_b; uint32 neo_r, neo_g, neo_b;
@ -270,6 +268,8 @@ namespace MDFN_IEN_WSWAN
ColorMapG[i] = 0xff000000 | neo_r << 16 | neo_g << 8 | neo_b << 0; ColorMapG[i] = 0xff000000 | neo_r << 16 | neo_g << 8 | neo_b << 0;
} }
}
}
} }
void GFX::Scanline(uint32 *target) void GFX::Scanline(uint32 *target)
@ -537,15 +537,23 @@ namespace MDFN_IEN_WSWAN
} // End sprite drawing } // End sprite drawing
const int hinc = sys->rotate ? -144 : 1;
if(wsVMode) if(wsVMode)
{ {
for(l=0;l<224;l++) for(l=0;l<224;l++)
target[l] = ColorMap[wsCols[b_bg_pal[l+7]][b_bg[(l+7)]&0xf]]; {
target[0] = ColorMap[wsCols[b_bg_pal[l+7]][b_bg[(l+7)]&0xf]];
target += hinc;
}
} }
else else
{ {
for(l=0;l<224;l++) for(l=0;l<224;l++)
target[l] = ColorMapG[(b_bg[l+7])&15]; {
target[0] = ColorMapG[(b_bg[l+7])&15];
target += hinc;
}
} }
} }
@ -556,11 +564,10 @@ namespace MDFN_IEN_WSWAN
void GFX::Reset() void GFX::Reset()
{ {
//weppy = 0; wsLine = 145; // all frames same length
wsLine=145; // all frames same length SetVideo(0, true);
SetVideo(0,TRUE);
memset(SpriteTable, 0, sizeof(SpriteTable)); std::memset(SpriteTable, 0, sizeof(SpriteTable));
SpriteCountCache = 0; SpriteCountCache = 0;
DispControl = 0; DispControl = 0;
BGColor = 0; BGColor = 0;
@ -592,11 +599,7 @@ namespace MDFN_IEN_WSWAN
HBCounter = 0; HBCounter = 0;
VBCounter = 0; VBCounter = 0;
std::memset(wsCols, 0, sizeof(wsCols));
for(int u0=0;u0<16;u0++)
for(int u1=0;u1<16;u1++)
wsCols[u0][u1]=0;
} }
} }

View File

@ -195,6 +195,6 @@ typedef unsigned char Boolean; /* 0 or 1 */
#error "Define MSB_FIRST or LSB_FIRST!" #error "Define MSB_FIRST or LSB_FIRST!"
#endif #endif
#include "error.h" //#include "error.h"
#endif #endif

View File

@ -23,7 +23,7 @@
#include <time.h> #include <time.h>
#include <math.h> #include <math.h>
#include <cstring> #include <cstring>
#include <vector> #include <cstdlib>
namespace MDFN_IEN_WSWAN namespace MDFN_IEN_WSWAN
@ -256,6 +256,7 @@ namespace MDFN_IEN_WSWAN
case 0xB3: CommControl = V & 0xF0; break; case 0xB3: CommControl = V & 0xF0; break;
case 0xb5: ButtonWhich = V >> 4; case 0xb5: ButtonWhich = V >> 4;
Lagged = false;
ButtonReadLatch = 0; ButtonReadLatch = 0;
if(ButtonWhich & 0x4) /*buttons*/ if(ButtonWhich & 0x4) /*buttons*/

View File

@ -30,6 +30,7 @@ public:
uint8 *wsSRAM; // = NULL; uint8 *wsSRAM; // = NULL;
uint16 WSButtonStatus; // bitfield of buttons, indeed uint16 WSButtonStatus; // bitfield of buttons, indeed
bool Lagged;
private: private:

View File

@ -26,10 +26,13 @@ namespace MDFN_IEN_WSWAN
static void GMTime(uint64 ticks, tm &time) static void GMTime(uint64 ticks, tm &time)
{ {
time_t t = ticks; time_t t = ticks;
#ifdef __GNUC__ #if defined _MSC_VER
gmtime_r(&t, &time);
#elif defined _MSC_VER
gmtime_s(&time, &t); gmtime_s(&time, &t);
#elif defined __MINGW32__
tm *tmp = gmtime(&t);
time = *tmp;
#elif defined __GNUC__
gmtime_r(&t, &time);
#endif #endif
} }
@ -58,7 +61,7 @@ namespace MDFN_IEN_WSWAN
{ {
tm newtime; tm newtime;
uint64 now = userealtime ? time(0) : CurrentTime; uint64 now = userealtime ? time(0) : CurrentTime;
GMTime(CurrentTime, newtime); GMTime(now, newtime);
switch(wsCA15) switch(wsCA15)
{ {

View File

@ -260,9 +260,9 @@ namespace MDFN_IEN_WSWAN
int ch = (A - 0x80) >> 1; int ch = (A - 0x80) >> 1;
if(A & 1) if(A & 1)
return(period[ch] >> 8); return period[ch] >> 8;
else else
return(period[ch]); return (uint8)period[ch];
} }
else if(A >= 0x88 && A <= 0x8B) else if(A >= 0x88 && A <= 0x8B)
return(volume[A - 0x88]); return(volume[A - 0x88]);
@ -320,7 +320,7 @@ namespace MDFN_IEN_WSWAN
sbuf[i]->bass_freq(20); sbuf[i]->bass_freq(20);
} }
double eff_volume = 1.0 / 4; double eff_volume = 0.1; //TOOLOUD 1.0 / 4;
WaveSynth.volume(eff_volume); WaveSynth.volume(eff_volume);
NoiseSynth.volume(eff_volume); NoiseSynth.volume(eff_volume);

View File

@ -65,10 +65,23 @@ namespace MDFN_IEN_WSWAN
cpu.set_reg(NEC_SP,0x2000); cpu.set_reg(NEC_SP,0x2000);
} }
static uint16 RotateButtons(uint16 input)
void System::Advance(uint16 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int &soundbuffsize)
{ {
memory.WSButtonStatus = buttons; int groupx = input & 0xf;
groupx <<= 1;
groupx |= groupx >> 4;
groupx &= 0x0f;
int groupy = input & 0xf0;
groupy <<= 1;
groupy |= groupy >> 4;
groupy &= 0xf0;
return input & 0xff00 | groupx | groupy;
}
bool System::Advance(uint16 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int &soundbuffsize)
{
memory.WSButtonStatus = rotate ? RotateButtons(buttons) : buttons;
memory.Lagged = true;
while (!gfx.ExecuteLine(surface, novideo)) while (!gfx.ExecuteLine(surface, novideo))
{ {
} }
@ -79,11 +92,12 @@ namespace MDFN_IEN_WSWAN
// how is this OK to reset? it's only used by the sound code, so once the sound for the frame has // how is this OK to reset? it's only used by the sound code, so once the sound for the frame has
// been collected, it's OK to zero. indeed, it should be done as there's no rollover protection // been collected, it's OK to zero. indeed, it should be done as there's no rollover protection
cpu.timestamp = 0; cpu.timestamp = 0;
return memory.Lagged;
} }
// Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 // Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
// Rounds up to the nearest power of 2. // Rounds up to the nearest power of 2.
static INLINE uint64 round_up_pow2(uint64 v) static INLINE uint32 round_up_pow2(uint32 v)
{ {
v--; v--;
v |= v >> 1; v |= v >> 1;
@ -91,7 +105,6 @@ namespace MDFN_IEN_WSWAN
v |= v >> 4; v |= v >> 4;
v |= v >> 8; v |= v >> 8;
v |= v >> 16; v |= v >> 16;
v |= v >> 32;
v++; v++;
v += (v == 0); v += (v == 0);
@ -115,7 +128,6 @@ namespace MDFN_IEN_WSWAN
return false; return false;
} }
real_rom_size = (length + 0xFFFF) & ~0xFFFF; real_rom_size = (length + 0xFFFF) & ~0xFFFF;
memory.rom_size = round_up_pow2(real_rom_size); memory.rom_size = round_up_pow2(real_rom_size);
@ -186,14 +198,7 @@ namespace MDFN_IEN_WSWAN
memory.wsCartROM[0xfffec]=0x20; memory.wsCartROM[0xfffec]=0x20;
} }
rotate = header[6] & 1;
if(header[6] & 0x1)
{
//MDFNGameInfo->rotated = MDFN_ROTATE90;
}
//MDFNMP_Init(16384, (1 << 20) / 1024);
memory.Init(settings); memory.Init(settings);
@ -229,7 +234,7 @@ namespace MDFN_IEN_WSWAN
{ {
} }
int System::SaveRamSize() int System::SaveRamSize() const
{ {
return eeprom.ieeprom_size + eeprom.eeprom_size + memory.sram_size; return eeprom.ieeprom_size + eeprom.eeprom_size + memory.sram_size;
} }
@ -249,7 +254,7 @@ namespace MDFN_IEN_WSWAN
return true; return true;
} }
bool System::SaveRamSave(uint8 *dest, int maxsize) bool System::SaveRamSave(uint8 *dest, int maxsize) const
{ {
if (maxsize != SaveRamSize()) if (maxsize != SaveRamSize())
return false; return false;
@ -280,14 +285,16 @@ namespace MDFN_IEN_WSWAN
s->Reset(); s->Reset();
} }
EXPORT void bizswan_advance(System *s, uint16 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int *soundbuffsize) EXPORT int bizswan_advance(System *s, uint16 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int *soundbuffsize)
{ {
s->Advance(buttons, novideo, surface, soundbuff, *soundbuffsize); return s->Advance(buttons, novideo, surface, soundbuff, *soundbuffsize);
} }
EXPORT int bizswan_load(System *s, const uint8 *data, int length, const SyncSettings *settings) EXPORT int bizswan_load(System *s, const uint8 *data, int length, const SyncSettings *settings, int *IsRotated)
{ {
return s->Load(data, length, *settings); bool ret = s->Load(data, length, *settings);
*IsRotated = s->rotate;
return ret;
} }
EXPORT int bizswan_saveramsize(System *s) EXPORT int bizswan_saveramsize(System *s)

View File

@ -30,12 +30,12 @@ public:
static void* operator new(std::size_t size); static void* operator new(std::size_t size);
void Reset(); void Reset();
void Advance(uint16 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int &soundbuffsize); bool Advance(uint16 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int &soundbuffsize);
bool Load(const uint8 *data, int length, const SyncSettings &s); bool Load(const uint8 *data, int length, const SyncSettings &s);
int SaveRamSize(); int SaveRamSize() const;
bool SaveRamLoad(const uint8 *data, int size); bool SaveRamLoad(const uint8 *data, int size);
bool SaveRamSave(uint8 *dest, int maxsize); bool SaveRamSave(uint8 *dest, int maxsize) const;
public: public:
GFX gfx; GFX gfx;
@ -45,6 +45,8 @@ public:
Sound sound; Sound sound;
V30MZ cpu; V30MZ cpu;
Interrupt interrupt; Interrupt interrupt;
bool rotate; // rotate screen and controls left 90
}; };
struct SyncSettings struct SyncSettings
@ -56,7 +58,6 @@ struct SyncSettings
uint8 language; // 0 = J, 1 = E; only affects "Digimon Tamers - Battle Spirit" uint8 language; // 0 = J, 1 = E; only affects "Digimon Tamers - Battle Spirit"
uint8 sex; // sex, 1 = male, 2 = female uint8 sex; // sex, 1 = male, 2 = female
uint8 blood; // 1 = a, 2 = b, 3 = o, 4 = ab uint8 blood; // 1 = a, 2 = b, 3 = o, 4 = ab
bool rotateinput; // true to rotate input and dpads, sync setting because of this
bool color; // true if wonderswan is in color mode bool color; // true if wonderswan is in color mode
bool userealtime; // true to use the system's actual clock; false to use an emulation pegged clock bool userealtime; // true to use the system's actual clock; false to use an emulation pegged clock
uint64 initialtime; // when userealtime is false, the initial time in unix format uint64 initialtime; // when userealtime is false, the initial time in unix format