Godzil ee50803d33 Remove all useless filter and some dead code.
That streamline greatly the emulation code and remove all of that non-sense of code in headers included here and there.
Still lot to be done on that point.
Also update some times to use C99 instead of random from wherever it come from.
2020-01-15 17:49:52 +00:00

526 lines
12 KiB
C++

////////////////////////////////////////////////////////////////////////////////
// Wonderswan emulator
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
// 07.04.2002: speed problems partially fixed
// 13.04.2002: Set cycles by line to 256 (according to toshi)
// this seems to work well in most situations with
// the new nec v30 cpu core
//
//
//
////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include "log.h"
#include "rom.h"
#include "./nec/nec.h"
#include "./nec/necintrf.h"
#include "memory.h"
#include "gpu.h"
#include "io.h"
#include "audio.h"
#include "ws.h"
#ifndef O_BINARY
// silly windows systems with their CR/LF screwiness...
#define O_BINARY 0
#endif
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
uint32 ws_cycles;
uint32 ws_skip;
uint32 ws_cyclesByLine=0;
uint32 vblank_count=0;
char *ws_sram_path = NULL;
extern int ws_sram_dirty;
extern int ws_gpu_forceColorSystemBool;
extern int ws_gpu_forceMonoSystemBool;
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_patchRom(void)
{
uint8 *rom=memory_getRom();
uint32 romSize=memory_getRomSize();
fprintf(log_get(),"developper Id: 0x%.2x\nGame Id: 0x%.2x\n",rom[romSize-10],rom[romSize-8]);
/*
if((rom[romSize-10]==0x01)&&(rom[romSize-8]==0x27)) // Detective Conan
{
// WS cpu is using cache/pipeline or
// there's protected ROM bank where
// pointing CS
rom[0xfffe8]=0xea;
rom[0xfffe9]=0x00;
rom[0xfffea]=0x00;
rom[0xfffeb]=0x00;
rom[0xfffec]=0x20;
}*/
if (!ws_cyclesByLine)
{
ws_cyclesByLine=256;
}
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int ws_init(char *rompath)
{
uint8 *rom;
uint32 romSize;
if ((rom=ws_rom_load(rompath,&romSize))==NULL)
{
printf("Error: cannot load %s\n",rompath);
return(0);
}
if ((ws_gpu_forceColorSystemBool == 0) && (ws_gpu_forceMonoSystemBool == 0))
{
/* Nothing forced try to "auto detect" */
if (rompath[strlen(rompath)-1]=='c')
{
ws_gpu_operatingInColor=1;
}
else
{
ws_gpu_operatingInColor=0;
}
}
ws_memory_init(rom,romSize);
ws_patchRom();
ws_sram_load(ws_sram_path);
ws_io_init();
ws_audio_init();
ws_gpu_init();
if (ws_rotated())
{
ws_io_flipControls();
}
return(1);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_reset(void)
{
ws_memory_reset();
ws_io_reset();
ws_audio_reset();
ws_gpu_reset();
nec_reset(NULL);
nec_set_reg(NEC_SP,0x2000);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int ws_executeLine(int16 *framebuffer, int renderLine)
{
int drawWholeScreen=0;
ws_audio_process();
// update scanline register
ws_ioRam[2]=ws_gpu_scanline;
ws_cycles=nec_execute((ws_cyclesByLine>>1)+(rand()&7));
ws_cycles+=nec_execute((ws_cyclesByLine>>1)+(rand()&7));
if(ws_cycles>=ws_cyclesByLine+ws_cyclesByLine)
{
ws_skip=ws_cycles/ws_cyclesByLine;
}
else
{
ws_skip=1;
}
ws_cycles%=ws_cyclesByLine;
for(uint32 uI=0; uI<ws_skip; uI++)
{
if (renderLine)
{
ws_gpu_renderScanline(framebuffer);
}
ws_gpu_scanline++;
if(ws_gpu_scanline==144)
{
drawWholeScreen=1;
}
}
if(ws_gpu_scanline>158)
{
ws_gpu_scanline=0;
{
if((ws_ioRam[0xb2]&32)) /* VBLANK Timer */
{
/* TODO: REPAIR THAT SHIT */
ws_ioRam[0xb6]&=~32;
nec_int((ws_ioRam[0xb0]+5)*4);
}
}
}
ws_ioRam[2]=ws_gpu_scanline;
if(drawWholeScreen)
{
if(ws_ioRam[0xb2]&64) /* VBLANK INT */
{
ws_ioRam[0xb6]&=~64;
nec_int((ws_ioRam[0xb0]+6)*4);
}
vblank_count++;
}
if(ws_ioRam[0xa4]&&(ws_ioRam[0xb2]&128)) /*HBLANK TMR*/
{
/* TODO: Check that shit */
if(!ws_ioRam[0xa5])
{
ws_ioRam[0xa5]=ws_ioRam[0xa4];
}
if(ws_ioRam[0xa5])
{
ws_ioRam[0xa5]--;
}
if((!ws_ioRam[0xa5])&&(ws_ioRam[0xb2]&128))
{
ws_ioRam[0xb6]&=~128;
nec_int((ws_ioRam[0xb0]+7)*4);
}
}
if((ws_ioRam[0x2]==ws_ioRam[0x3])&&(ws_ioRam[0xb2]&16)) /*SCANLINE INT*/
{
ws_ioRam[0xb6]&=~16;
nec_int((ws_ioRam[0xb0]+4)*4);
}
if (drawWholeScreen && ws_sram_dirty)
{
ws_sram_save(ws_sram_path);
ws_sram_dirty = 0;
}
return(drawWholeScreen);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_done(void)
{
ws_memory_done();
ws_io_done();
ws_audio_done();
ws_gpu_done();
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_set_colour_scheme(int scheme)
{
ws_gpu_set_colour_scheme(scheme);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
void ws_set_system(int system)
{
if (system==WS_SYSTEM_COLOR)
{
ws_gpu_forceColorSystem();
}
else if (system==WS_SYSTEM_MONO)
{
ws_gpu_forceMonoSystem();
}
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
#define MacroLoadNecRegisterFromFile(F,R) \
read(fp,&value,sizeof(value)); \
nec_set_reg(R,value);
int ws_loadState(char *statepath)
{
fprintf(log_get(),"loading %s\n",statepath);
uint16_t crc=memory_getRomCrc();
uint16_t newCrc;
unsigned value;
uint8_t ws_newVideoMode;
int fp = open(statepath,O_BINARY|O_RDONLY);
if (fp == -1)
{
return(0);
}
read(fp, &newCrc, 2);
if (newCrc!=crc)
{
return(-1);
}
MacroLoadNecRegisterFromFile(fp,NEC_IP);
MacroLoadNecRegisterFromFile(fp,NEC_AW);
MacroLoadNecRegisterFromFile(fp,NEC_BW);
MacroLoadNecRegisterFromFile(fp,NEC_CW);
MacroLoadNecRegisterFromFile(fp,NEC_DW);
MacroLoadNecRegisterFromFile(fp,NEC_CS);
MacroLoadNecRegisterFromFile(fp,NEC_DS);
MacroLoadNecRegisterFromFile(fp,NEC_ES);
MacroLoadNecRegisterFromFile(fp,NEC_SS);
MacroLoadNecRegisterFromFile(fp,NEC_IX);
MacroLoadNecRegisterFromFile(fp,NEC_IY);
MacroLoadNecRegisterFromFile(fp,NEC_BP);
MacroLoadNecRegisterFromFile(fp,NEC_SP);
MacroLoadNecRegisterFromFile(fp,NEC_FLAGS);
MacroLoadNecRegisterFromFile(fp,NEC_VECTOR);
MacroLoadNecRegisterFromFile(fp,NEC_PENDING);
MacroLoadNecRegisterFromFile(fp,NEC_NMI_STATE);
MacroLoadNecRegisterFromFile(fp,NEC_IRQ_STATE);
read(fp,internalRam,65536);
read(fp,ws_staticRam,65536);
read(fp,ws_ioRam,256);
read(fp,ws_paletteColors,8);
read(fp,ws_palette,16*4*2);
read(fp,wsc_palette,16*16*2);
read(fp,&ws_newVideoMode,1);
read(fp,&ws_gpu_scanline,1);
read(fp,externalEeprom,131072);
ws_audio_readState(fp);
close(fp);
// force a video mode change to make all tiles dirty
ws_gpu_clearCache();
return(1);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
#define MacroStoreNecRegisterToFile(F,R) \
value=nec_get_reg(R); \
write(fp,&value,sizeof(value));
int ws_saveState(char *statepath)
{
uint16 crc=memory_getRomCrc();
unsigned value;
char *newPath;
fprintf(log_get(),"saving %s\n",statepath);
newPath=new char[1024];
if (strlen(statepath)<4)
{
sprintf(newPath,"%s.wss",statepath);
}
else
{
int len=strlen(statepath);
if ((statepath[len-1]!='s')&&(statepath[len-1]!='S'))
{
sprintf(newPath,"%s.wss",statepath);
}
else if ((statepath[len-2]!='s')&&(statepath[len-2]!='S'))
{
sprintf(newPath,"%s.wss",statepath);
}
else if ((statepath[len-3]!='w')&&(statepath[len-3]!='w'))
{
sprintf(newPath,"%s.wss",statepath);
}
else if (statepath[len-4]!='.')
{
sprintf(newPath,"%s.wss",statepath);
}
else
{
sprintf(newPath,"%s",statepath);
}
}
int fp=open(newPath,O_BINARY|O_RDWR|O_CREAT);
delete newPath;
if (fp==-1)
{
return(0);
}
write(fp,&crc,2);
MacroStoreNecRegisterToFile(fp,NEC_IP);
MacroStoreNecRegisterToFile(fp,NEC_AW);
MacroStoreNecRegisterToFile(fp,NEC_BW);
MacroStoreNecRegisterToFile(fp,NEC_CW);
MacroStoreNecRegisterToFile(fp,NEC_DW);
MacroStoreNecRegisterToFile(fp,NEC_CS);
MacroStoreNecRegisterToFile(fp,NEC_DS);
MacroStoreNecRegisterToFile(fp,NEC_ES);
MacroStoreNecRegisterToFile(fp,NEC_SS);
MacroStoreNecRegisterToFile(fp,NEC_IX);
MacroStoreNecRegisterToFile(fp,NEC_IY);
MacroStoreNecRegisterToFile(fp,NEC_BP);
MacroStoreNecRegisterToFile(fp,NEC_SP);
MacroStoreNecRegisterToFile(fp,NEC_FLAGS);
MacroStoreNecRegisterToFile(fp,NEC_VECTOR);
MacroStoreNecRegisterToFile(fp,NEC_PENDING);
MacroStoreNecRegisterToFile(fp,NEC_NMI_STATE);
MacroStoreNecRegisterToFile(fp,NEC_IRQ_STATE);
write(fp,internalRam,65536);
write(fp,ws_staticRam,65536);
write(fp,ws_ioRam,256);
write(fp,ws_paletteColors,8);
write(fp,ws_palette,16*4*2);
write(fp,wsc_palette,16*16*2);
write(fp,&ws_videoMode,1);
write(fp,&ws_gpu_scanline,1);
write(fp,externalEeprom,131072);
ws_audio_writeState(fp);
close(fp);
return(1);
}
////////////////////////////////////////////////////////////////////////////////
//
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
int ws_rotated(void)
{
uint8_t *rom=memory_getRom();
uint32_t romSize=memory_getRomSize();
return(rom[romSize-4]&1);
}