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())
{
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
// file.NonArchiveExtensions = romExtensions;

View File

@ -41,8 +41,9 @@ namespace BizHawk.Emulation.Cores.WonderSwan
/// <param name="surface">uint32 video 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>
/// <returns>true if lagged</returns>
[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>
/// load rom
@ -51,9 +52,10 @@ namespace BizHawk.Emulation.Cores.WonderSwan
/// <param name="data"></param>
/// <param name="length"></param>
/// <param name="settings"></param>
/// <param name="IsRotated">(out) true if screen is rotated left 90</param>
/// <returns></returns>
[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>
/// get size of saveram
@ -95,8 +97,8 @@ namespace BizHawk.Emulation.Cores.WonderSwan
DownY = 0x0040,
LeftY = 0x0080,
Start = 0x0100,
B = 0x0200,
A = 0x0400,
A = 0x0200,
B = 0x0400,
}
public enum Language : byte
@ -131,8 +133,6 @@ namespace BizHawk.Emulation.Cores.WonderSwan
public Gender sex;
public Bloodtype blood;
[MarshalAs(UnmanagedType.U1)]
public bool rotateinput;
[MarshalAs(UnmanagedType.U1)]
public bool color; // true for color system
[MarshalAs(UnmanagedType.U1)]
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,
blood = BizSwan.Bloodtype.A,
language = BizSwan.Language.Japanese,
rotateinput = false, // TODO
bday = 5,
bmonth = 12,
byear = 1968
};
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!");
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
saverambuff = new byte[BizSwan.bizswan_saveramsize(Core)];
InitVideo(rotate);
}
catch
{
@ -94,12 +97,11 @@ namespace BizHawk.Emulation.Cores.WonderSwan
BizSwan.bizswan_reset(Core);
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)
throw new Exception();
sbuffcontains = soundbuffsize;
IsLagFrame = false; // TODO
if (IsLagFrame)
LagCount++;
}
@ -226,6 +228,20 @@ namespace BizHawk.Emulation.Cores.WonderSwan
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];
public int[] GetVideoBuffer()
@ -233,10 +249,10 @@ namespace BizHawk.Emulation.Cores.WonderSwan
return vbuff;
}
public int VirtualWidth { get { return 224; } }
public int VirtualHeight { get { return 144; } }
public int BufferWidth { get { return 224; } }
public int BufferHeight { get { return 144; } }
public int VirtualWidth { get { return BufferWidth; } }
public int VirtualHeight { get { return BufferHeight; } }
public int BufferWidth { get; private set; }
public int BufferHeight { get; private set; }
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
#endregion

Binary file not shown.

View File

@ -154,18 +154,17 @@ namespace MDFN_IEN_WSWAN
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;
// weppy = 0;
//WEP0: ;
ret = FALSE;
bool ret = false; // true if we finish frame here
if(wsLine < 144)
{
if(!skip)
Scanline(surface + wsLine * 224);
{
if (sys->rotate)
Scanline(surface + 223 * 144 + wsLine);
else
Scanline(surface + wsLine * 224);
}
}
sys->memory.CheckSoundDMA();
@ -183,7 +182,7 @@ namespace MDFN_IEN_WSWAN
if(wsLine == 144)
{
ret = TRUE;
ret = true;
sys->interrupt.DoInterrupt(WSINT_VBLANK);
//printf("VBlank: %d\n", wsLine);
}
@ -201,10 +200,9 @@ namespace MDFN_IEN_WSWAN
}
}
// weppy = 1;
// CPU ==========================
sys->cpu.execute(224);
// goto *WEP_Tab[weppy];
//WEP1: ;
// CPU ==========================
wsLine = (wsLine + 1) % 159;
if(wsLine == LineCompare)
@ -213,10 +211,9 @@ namespace MDFN_IEN_WSWAN
//printf("Line hit: %d\n", wsLine);
}
// weppy = 2;
// CPU ==========================
sys->cpu.execute(32);
// goto *WEP_Tab[weppy];
//WEP2: ;
// CPU ==========================
sys->rtc.Clock(256);
@ -236,8 +233,7 @@ namespace MDFN_IEN_WSWAN
wsLine = 0;
}
// weppy = 0;
return(ret);
return ret;
}
void GFX::SetLayerEnableMask(uint32 mask)
@ -248,7 +244,9 @@ namespace MDFN_IEN_WSWAN
void GFX::SetPixelFormat()
{
for(int r = 0; r < 16; r++)
{
for(int g = 0; g < 16; g++)
{
for(int b = 0; b < 16; 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;
}
}
}
}
void GFX::Scanline(uint32 *target)
@ -537,15 +537,23 @@ namespace MDFN_IEN_WSWAN
} // End sprite drawing
const int hinc = sys->rotate ? -144 : 1;
if(wsVMode)
{
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
{
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()
{
//weppy = 0;
wsLine=145; // all frames same length
SetVideo(0,TRUE);
wsLine = 145; // all frames same length
SetVideo(0, true);
memset(SpriteTable, 0, sizeof(SpriteTable));
std::memset(SpriteTable, 0, sizeof(SpriteTable));
SpriteCountCache = 0;
DispControl = 0;
BGColor = 0;
@ -592,11 +599,7 @@ namespace MDFN_IEN_WSWAN
HBCounter = 0;
VBCounter = 0;
for(int u0=0;u0<16;u0++)
for(int u1=0;u1<16;u1++)
wsCols[u0][u1]=0;
std::memset(wsCols, 0, sizeof(wsCols));
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -65,10 +65,23 @@ namespace MDFN_IEN_WSWAN
cpu.set_reg(NEC_SP,0x2000);
}
void System::Advance(uint16 buttons, bool novideo, uint32 *surface, int16 *soundbuff, int &soundbuffsize)
static uint16 RotateButtons(uint16 input)
{
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))
{
}
@ -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
// been collected, it's OK to zero. indeed, it should be done as there's no rollover protection
cpu.timestamp = 0;
return memory.Lagged;
}
// Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
// 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 >> 1;
@ -91,7 +105,6 @@ namespace MDFN_IEN_WSWAN
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
v += (v == 0);
@ -115,7 +128,6 @@ namespace MDFN_IEN_WSWAN
return false;
}
real_rom_size = (length + 0xFFFF) & ~0xFFFF;
memory.rom_size = round_up_pow2(real_rom_size);
@ -186,14 +198,7 @@ namespace MDFN_IEN_WSWAN
memory.wsCartROM[0xfffec]=0x20;
}
if(header[6] & 0x1)
{
//MDFNGameInfo->rotated = MDFN_ROTATE90;
}
//MDFNMP_Init(16384, (1 << 20) / 1024);
rotate = header[6] & 1;
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;
}
@ -249,7 +254,7 @@ namespace MDFN_IEN_WSWAN
return true;
}
bool System::SaveRamSave(uint8 *dest, int maxsize)
bool System::SaveRamSave(uint8 *dest, int maxsize) const
{
if (maxsize != SaveRamSize())
return false;
@ -280,14 +285,16 @@ namespace MDFN_IEN_WSWAN
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)

View File

@ -30,12 +30,12 @@ public:
static void* operator new(std::size_t size);
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);
int SaveRamSize();
int SaveRamSize() const;
bool SaveRamLoad(const uint8 *data, int size);
bool SaveRamSave(uint8 *dest, int maxsize);
bool SaveRamSave(uint8 *dest, int maxsize) const;
public:
GFX gfx;
@ -45,6 +45,8 @@ public:
Sound sound;
V30MZ cpu;
Interrupt interrupt;
bool rotate; // rotate screen and controls left 90
};
struct SyncSettings
@ -56,7 +58,6 @@ struct SyncSettings
uint8 language; // 0 = J, 1 = E; only affects "Digimon Tamers - Battle Spirit"
uint8 sex; // sex, 1 = male, 2 = female
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 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