2014-11-20 03:28:28 +00:00
# include <stdarg.h>
2012-06-03 15:48:14 +00:00
# include "mednafen/mednafen.h"
# include "mednafen/git.h"
# include "mednafen/general.h"
# include "libretro.h"
2014-06-18 20:10:07 +00:00
# include "thread.h"
2012-06-03 15:48:14 +00:00
2014-11-20 03:28:28 +00:00
# include "mednafen/FileWrapper.h"
2014-06-19 21:34:42 +00:00
2014-06-19 21:10:59 +00:00
# include "mednafen/pce_fast/pce.h"
# include "mednafen/pce_fast/vdc.h"
# include "mednafen/pce_fast/psg.h"
# include "mednafen/pce_fast/input.h"
# include "mednafen/pce_fast/huc.h"
# include "mednafen/pce_fast/pcecd.h"
# include "mednafen/pce_fast/pcecd_drive.h"
# include "mednafen/hw_misc/arcade_card/arcade_card.h"
# include "mednafen/cdrom/cdromif.h"
2014-06-19 21:34:42 +00:00
# include "mednafen/cdrom/CDUtility.h"
# ifdef _MSC_VER
2014-06-24 23:57:10 +00:00
# include "mednafen/msvc_compat.h"
2014-06-19 21:34:42 +00:00
# endif
2014-06-20 20:49:22 +00:00
static bool old_cdimagecache = false ;
2014-06-19 21:34:42 +00:00
extern MDFNGI EmulatedPCE_Fast ;
2014-11-20 03:28:28 +00:00
MDFNGI * MDFNGameInfo = & EmulatedPCE_Fast ;
2014-06-19 21:10:59 +00:00
/* Mednafen - Multi-system Emulator
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
2014-11-20 03:28:28 +00:00
extern " C " unsigned long crc32 ( unsigned long crc , const unsigned char * buf ,
unsigned int len ) ;
2014-06-19 21:10:59 +00:00
namespace PCE_Fast
{
2014-11-20 03:28:28 +00:00
static PCEFast_PSG * psg = NULL ;
extern ArcadeCard * arcade_card ; // Bah, lousy globals.
2014-06-19 21:10:59 +00:00
static Blip_Buffer sbuf [ 2 ] ;
bool PCE_ACEnabled ;
int pce_overclocked ;
// Statically allocated for speed...or something.
2014-11-20 03:28:28 +00:00
uint8 ROMSpace [ 0x88 * 8192 + 8192 ] ; // + 8192 for PC-as-pointer safety padding
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
uint8 BaseRAM [ 32768 +
8192 ] ; // 8KB for PCE, 32KB for Super Grafx // + 8192 for PC-as-pointer safety padding
2014-06-19 21:10:59 +00:00
uint8 PCEIODataBuffer ;
readfunc PCERead [ 0x100 ] ;
writefunc PCEWrite [ 0x100 ] ;
static DECLFR ( PCEBusRead )
{
2014-11-20 03:28:28 +00:00
//printf("BUS Read: %02x %04x\n", A >> 13, A);
return ( 0xFF ) ;
2014-06-19 21:10:59 +00:00
}
static DECLFW ( PCENullWrite )
{
2014-11-20 03:28:28 +00:00
//printf("Null Write: %02x, %08x %02x\n", A >> 13, A, V);
2014-06-19 21:10:59 +00:00
}
static DECLFR ( BaseRAMRead )
{
2014-11-20 03:28:28 +00:00
return ( ( BaseRAM - ( 0xF8 * 8192 ) ) [ A ] ) ;
2014-06-19 21:10:59 +00:00
}
static DECLFR ( BaseRAMRead_Mirrored )
{
2014-11-20 03:28:28 +00:00
return ( BaseRAM [ A & 0x1FFF ] ) ;
2014-06-19 21:10:59 +00:00
}
static DECLFW ( BaseRAMWrite )
{
2014-11-20 03:28:28 +00:00
( BaseRAM - ( 0xF8 * 8192 ) ) [ A ] = V ;
2014-06-19 21:10:59 +00:00
}
static DECLFW ( BaseRAMWrite_Mirrored )
{
2014-11-20 03:28:28 +00:00
BaseRAM [ A & 0x1FFF ] = V ;
2014-06-19 21:10:59 +00:00
}
static DECLFR ( IORead )
{
2014-11-20 03:28:28 +00:00
# include "mednafen/pce_fast/ioread.inc"
2014-06-19 21:10:59 +00:00
}
static DECLFW ( IOWrite )
{
2014-11-20 03:28:28 +00:00
A & = 0x1FFF ;
switch ( A > > 10 )
{
case 0 :
HuC6280_StealCycle ( ) ;
VDC_Write ( A , V ) ;
break ;
case 1 :
HuC6280_StealCycle ( ) ;
VCE_Write ( A , V ) ;
break ;
case 2 :
PCEIODataBuffer = V ;
psg - > Write ( HuCPU . timestamp / pce_overclocked , A , V ) ;
break ;
case 3 :
PCEIODataBuffer = V ;
HuC6280_TimerWrite ( A , V ) ;
break ;
case 4 :
PCEIODataBuffer = V ;
INPUT_Write ( A , V ) ;
break ;
case 5 :
PCEIODataBuffer = V ;
HuC6280_IRQStatusWrite ( A , V ) ;
break ;
case 6 :
if ( ! PCE_IsCD )
break ;
if ( ( A & 0x1E00 ) = = 0x1A00 )
{
if ( arcade_card )
arcade_card - > Write ( A & 0x1FFF , V ) ;
}
else
PCECD_Write ( HuCPU . timestamp * 3 , A , V ) ;
break ;
case 7 :
break ; // Expansion.
}
2014-06-19 21:10:59 +00:00
}
static void PCECDIRQCB ( bool asserted )
{
2014-11-20 03:28:28 +00:00
if ( asserted )
HuC6280_IRQBegin ( MDFN_IQIRQ2 ) ;
else
HuC6280_IRQEnd ( MDFN_IQIRQ2 ) ;
2014-06-19 21:10:59 +00:00
}
bool PCE_InitCD ( void )
{
2014-11-20 03:28:28 +00:00
PCECD_Settings cd_settings ;
memset ( & cd_settings , 0 , sizeof ( PCECD_Settings ) ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
cd_settings . CDDA_Volume = ( double ) MDFN_GetSettingUI ( " pce_fast.cddavolume " ) /
100 ;
cd_settings . CD_Speed = MDFN_GetSettingUI ( " pce_fast.cdspeed " ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
cd_settings . ADPCM_Volume = ( double ) MDFN_GetSettingUI ( " pce_fast.adpcmvolume " ) /
100 ;
cd_settings . ADPCM_LPF = MDFN_GetSettingB ( " pce_fast.adpcmlp " ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( cd_settings . CDDA_Volume ! = 1.0 )
MDFN_printf ( ( " CD-DA Volume: %d%% \n " ) , ( int ) ( 100 * cd_settings . CDDA_Volume ) ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( cd_settings . ADPCM_Volume ! = 1.0 )
MDFN_printf ( ( " ADPCM Volume: %d%% \n " ) , ( int ) ( 100 * cd_settings . ADPCM_Volume ) ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
return ( PCECD_Init ( & cd_settings , PCECDIRQCB , PCE_MASTER_CLOCK , pce_overclocked ,
& sbuf [ 0 ] , & sbuf [ 1 ] ) ) ;
2014-06-19 21:10:59 +00:00
}
static int LoadCommon ( void ) ;
static void LoadCommonPre ( void ) ;
2014-11-20 03:28:28 +00:00
static int Load ( const char * name , MDFNFILE * fp )
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
uint32 headerlen = 0 ;
uint32 r_size ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
LoadCommonPre ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
{
if ( GET_FSIZE_PTR ( fp ) & 0x200 ) // 512 byte header!
headerlen = 512 ;
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
r_size = GET_FSIZE_PTR ( fp ) - headerlen ;
if ( r_size > 4096 * 1024 ) r_size = 4096 * 1024 ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
for ( int x = 0 ; x < 0x100 ; x + + )
{
PCERead [ x ] = PCEBusRead ;
PCEWrite [ x ] = PCENullWrite ;
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
uint32 crc = crc32 ( 0 , GET_FDATA_PTR ( fp ) + headerlen ,
GET_FSIZE_PTR ( fp ) - headerlen ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
HuCLoad ( GET_FDATA_PTR ( fp ) + headerlen , GET_FSIZE_PTR ( fp ) - headerlen , crc ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
return ( LoadCommon ( ) ) ;
2014-06-19 21:10:59 +00:00
}
static void LoadCommonPre ( void )
{
2014-11-20 03:28:28 +00:00
// FIXME: Make these globals less global!
pce_overclocked = MDFN_GetSettingUI ( " pce_fast.ocmultiplier " ) ;
PCE_ACEnabled = MDFN_GetSettingB ( " pce_fast.arcadecard " ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( pce_overclocked > 1 )
MDFN_printf ( ( " CPU overclock: %dx \n " ) , pce_overclocked ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( MDFN_GetSettingUI ( " pce_fast.cdspeed " ) > 1 )
MDFN_printf ( ( " CD-ROM speed: %ux \n " ) ,
( unsigned int ) MDFN_GetSettingUI ( " pce_fast.cdspeed " ) ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
memset ( HuCPUFastMap , 0 , sizeof ( HuCPUFastMap ) ) ;
for ( int x = 0 ; x < 0x100 ; x + + )
{
PCERead [ x ] = PCEBusRead ;
PCEWrite [ x ] = PCENullWrite ;
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
// MDFNMP_Init(1024, (1 << 21) / 1024);
2014-06-19 21:10:59 +00:00
}
static int LoadCommon ( void )
2014-11-20 03:28:28 +00:00
{
VDC_Init ( false ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
{
PCERead [ 0xF8 ] = BaseRAMRead ;
PCERead [ 0xF9 ] = PCERead [ 0xFA ] = PCERead [ 0xFB ] = BaseRAMRead_Mirrored ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
PCEWrite [ 0xF8 ] = BaseRAMWrite ;
PCEWrite [ 0xF9 ] = PCEWrite [ 0xFA ] = PCEWrite [ 0xFB ] = BaseRAMWrite_Mirrored ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
for ( int x = 0xf8 ; x < 0xfb ; x + + )
HuCPUFastMap [ x ] = BaseRAM - x * 8192 ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
PCERead [ 0xFF ] = IORead ;
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
// MDFNMP_AddRAM(8192, 0xf8 * 8192, BaseRAM);
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
PCEWrite [ 0xFF ] = IOWrite ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
HuC6280_Init ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
psg = new PCEFast_PSG ( & sbuf [ 0 ] , & sbuf [ 1 ] ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
psg - > SetVolume ( 1.0 ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( PCE_IsCD )
{
unsigned int cdpsgvolume = MDFN_GetSettingUI ( " pce_fast.cdpsgvolume " ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( cdpsgvolume ! = 100 )
MDFN_printf ( ( " CD PSG Volume: %d%% \n " ) , cdpsgvolume ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
psg - > SetVolume ( 0.678 * cdpsgvolume / 100 ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
PCEINPUT_Init ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
PCE_Power ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
MDFNGameInfo - > LayerNames = " Background \0 Sprites \0 " ;
MDFNGameInfo - > fps = ( uint32 ) ( ( double ) 7159090.90909090 / 455 / 263 * 65536 *
256 ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
// Clean this up:
if ( ! MDFN_GetSettingB ( " pce_fast.correct_aspect " ) )
MDFNGameInfo - > fb_width = 682 ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
MDFNGameInfo - > nominal_width = MDFN_GetSettingB ( " pce_fast.correct_aspect " ) ?
288 : 341 ;
MDFNGameInfo - > nominal_height = MDFN_GetSettingUI ( " pce_fast.slend " ) -
MDFN_GetSettingUI ( " pce_fast.slstart " ) + 1 ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
MDFNGameInfo - > lcm_width = MDFN_GetSettingB ( " pce_fast.correct_aspect " ) ? 1024 :
341 ;
MDFNGameInfo - > lcm_height = MDFNGameInfo - > nominal_height ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
return ( 1 ) ;
2014-06-19 21:10:59 +00:00
}
2014-11-20 03:28:28 +00:00
static bool TestMagicCD ( std : : vector < CDIF * > * CDInterfaces )
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
static const uint8 magic_test [ 0x20 ] = { 0x82 , 0xB1 , 0x82 , 0xCC , 0x83 , 0x76 , 0x83 , 0x8D , 0x83 , 0x4F , 0x83 , 0x89 , 0x83 , 0x80 , 0x82 , 0xCC ,
0x92 , 0x98 , 0x8D , 0xEC , 0x8C , 0xA0 , 0x82 , 0xCD , 0x8A , 0x94 , 0x8E , 0xAE , 0x89 , 0xEF , 0x8E , 0xD0
} ;
uint8 sector_buffer [ 2048 ] ;
CDIF * cdiface = ( * CDInterfaces ) [ 0 ] ;
CDUtility : : TOC toc ;
bool ret = FALSE ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
memset ( sector_buffer , 0 , sizeof ( sector_buffer ) ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
cdiface - > ReadTOC ( & toc ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
for ( int32 track = toc . first_track ; track < = toc . last_track ; track + + )
{
if ( toc . tracks [ track ] . control & 0x4 )
{
cdiface - > ReadSector ( sector_buffer , toc . tracks [ track ] . lba , 1 ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( ! memcmp ( ( char * ) sector_buffer , ( char * ) magic_test , 0x20 ) )
ret = TRUE ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
// PCE CD BIOS apparently only looks at the first data track.
break ;
}
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
// If it's a PC-FX CD(Battle Heat), return false.
// This is very kludgy.
for ( int32 track = toc . first_track ; track < = toc . last_track ; track + + )
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
if ( toc . tracks [ track ] . control & 0x4 )
{
cdiface - > ReadSector ( sector_buffer , toc . tracks [ track ] . lba , 1 ) ;
if ( ! strncmp ( " PC-FX:Hu_CD-ROM " , ( char * ) sector_buffer ,
strlen ( " PC-FX:Hu_CD-ROM " ) ) )
return ( false ) ;
}
2014-06-19 21:10:59 +00:00
}
2014-11-20 03:28:28 +00:00
// Now, test for the Games Express CD games. The GE BIOS seems to always look at sector 0x10, but only if the first track is a
// data track.
if ( toc . first_track = = 1 & & ( toc . tracks [ 1 ] . control & 0x4 ) )
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
if ( cdiface - > ReadSector ( sector_buffer , 0x10 , 1 ) )
{
if ( ! memcmp ( ( char * ) sector_buffer + 0x8 , " HACKER CD ROM SYSTEM " , 0x14 ) )
ret = TRUE ;
}
2014-06-19 21:10:59 +00:00
}
2014-11-20 03:28:28 +00:00
return ( ret ) ;
2014-06-19 21:10:59 +00:00
}
2014-11-20 03:28:28 +00:00
static int LoadCD ( std : : vector < CDIF * > * CDInterfaces )
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
std : : string bios_path = MDFN_MakeFName ( MDFNMKF_FIRMWARE , 0 ,
MDFN_GetSettingS ( " pce_fast.cdbios " ) . c_str ( ) ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
LoadCommonPre ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( ! HuCLoadCD ( bios_path . c_str ( ) ) )
return ( 0 ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
PCECD_Drive_SetDisc ( true , NULL , true ) ;
PCECD_Drive_SetDisc ( false , ( * CDInterfaces ) [ 0 ] , true ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
return ( LoadCommon ( ) ) ;
2014-06-19 21:10:59 +00:00
}
2014-06-20 21:11:19 +00:00
static void Cleanup_PCE ( void )
{
HuC_Close ( ) ;
VDC_Close ( ) ;
2014-11-20 03:28:28 +00:00
if ( psg )
2014-06-20 21:11:19 +00:00
delete psg ;
psg = NULL ;
}
2014-06-19 21:10:59 +00:00
static void CloseGame ( void )
{
2014-06-20 21:11:19 +00:00
Cleanup_PCE ( ) ;
2014-06-19 21:10:59 +00:00
}
2014-11-20 03:28:28 +00:00
static void Emulate ( EmulateSpecStruct * espec )
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
INPUT_Frame ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( espec - > SoundFormatChanged )
{
for ( int y = 0 ; y < 2 ; y + + )
{
sbuf [ y ] . set_sample_rate ( espec - > SoundRate ? espec - > SoundRate : 44100 , 50 ) ;
sbuf [ y ] . clock_rate ( ( long ) ( PCE_MASTER_CLOCK / 3 ) ) ;
sbuf [ y ] . bass_freq ( 10 ) ;
}
}
2014-11-19 00:31:56 +00:00
2014-11-20 03:28:28 +00:00
RETRO_PERFORMANCE_INIT ( VDC_RunFrame_time ) ;
RETRO_PERFORMANCE_START ( VDC_RunFrame_time ) ;
2014-11-19 00:31:56 +00:00
# if defined(DUMP_FRAME_TIMES) && defined(PERF_TEST)
2014-11-20 03:28:28 +00:00
retro_perf_tick_t start_ticks = VDC_RunFrame_time . total ;
2014-11-19 00:31:56 +00:00
# endif
2014-11-20 03:28:28 +00:00
PSPPROF_START ;
// if (VDC_RunFrame_time.call_cnt == 44)
// printf("halt\n");
VDC_RunFrame ( espec , false ) ;
PSPPROF_STOP ;
RETRO_PERFORMANCE_STOP ( VDC_RunFrame_time ) ;
2014-11-19 00:31:56 +00:00
# if defined(DUMP_FRAME_TIMES) && defined(PERF_TEST)
2014-11-20 03:28:28 +00:00
printf ( " %u : %u ticks \n " , ( uint32_t ) VDC_RunFrame_time . call_cnt ,
( uint32_t ) ( VDC_RunFrame_time . total - start_ticks ) ) ;
fflush ( stdout ) ;
2014-11-19 00:31:56 +00:00
# endif
2014-11-13 15:53:14 +00:00
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( PCE_IsCD )
PCECD_Run ( HuCPU . timestamp * 3 ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
psg - > EndFrame ( HuCPU . timestamp / pce_overclocked ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( espec - > SoundBuf )
{
for ( int y = 0 ; y < 2 ; y + + )
{
sbuf [ y ] . end_frame ( HuCPU . timestamp / pce_overclocked ) ;
espec - > SoundBufSize = sbuf [ y ] . read_samples ( espec - > SoundBuf + y ,
espec - > SoundBufMaxSize ) ;
}
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
espec - > MasterCycles = HuCPU . timestamp * 3 ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
INPUT_FixTS ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
HuC6280_ResetTS ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( PCE_IsCD )
PCECD_ResetTS ( ) ;
2014-06-19 21:10:59 +00:00
}
2014-11-20 03:28:28 +00:00
static int StateAction ( StateMem * sm , int load , int data_only )
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
SFORMAT StateRegs [ ] =
{
SFARRAY ( BaseRAM , 8192 ) ,
SFVAR ( PCEIODataBuffer ) ,
SFEND
} ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
//for(int i = 8192; i < 32768; i++)
// if(BaseRAM[i] != 0xFF)
// printf("%d %02x\n", i, BaseRAM[i]);
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
int ret = MDFNSS_StateAction ( sm , load , data_only , StateRegs , " MAIN " ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
ret & = HuC6280_StateAction ( sm , load , data_only ) ;
ret & = VDC_StateAction ( sm , load , data_only ) ;
ret & = psg - > StateAction ( sm , load , data_only ) ;
ret & = INPUT_StateAction ( sm , load , data_only ) ;
ret & = HuC_StateAction ( sm , load , data_only ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( load )
{
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
}
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
return ( ret ) ;
2014-06-19 21:10:59 +00:00
}
void PCE_Power ( void )
{
2014-11-20 03:28:28 +00:00
memset ( BaseRAM , 0x00 , sizeof ( BaseRAM ) ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
for ( int i = 8192 ; i < 32768 ; i + + )
BaseRAM [ i ] = 0xFF ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
PCEIODataBuffer = 0xFF ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
HuC6280_Power ( ) ;
VDC_Power ( ) ;
psg - > Power ( HuCPU . timestamp / pce_overclocked ) ;
HuC_Power ( ) ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
if ( PCE_IsCD )
PCECD_Power ( HuCPU . timestamp * 3 ) ;
2014-06-19 21:10:59 +00:00
}
static void DoSimpleCommand ( int cmd )
{
2014-11-20 03:28:28 +00:00
switch ( cmd )
{
case MDFN_MSC_RESET :
PCE_Power ( ) ;
break ;
case MDFN_MSC_POWER :
PCE_Power ( ) ;
break ;
}
2014-06-19 21:10:59 +00:00
}
2014-11-20 03:28:28 +00:00
static MDFNSetting PCESettings [ ] =
2014-06-19 21:10:59 +00:00
{
2014-11-20 03:28:28 +00:00
{ " pce_fast.correct_aspect " , MDFNSF_CAT_VIDEO , ( " Correct the aspect ratio. " ) , NULL , MDFNST_BOOL , " 1 " } ,
{ " pce_fast.slstart " , MDFNSF_NOFLAGS , ( " First rendered scanline. " ) , NULL , MDFNST_UINT , " 4 " , " 0 " , " 239 " } ,
{ " pce_fast.slend " , MDFNSF_NOFLAGS , ( " Last rendered scanline. " ) , NULL , MDFNST_UINT , " 235 " , " 0 " , " 239 " } ,
{ " pce_fast.mouse_sensitivity " , MDFNSF_NOFLAGS , ( " Mouse sensitivity. " ) , NULL , MDFNST_FLOAT , " 0.50 " , NULL , NULL , NULL , PCEINPUT_SettingChanged } ,
{ " pce_fast.disable_softreset " , MDFNSF_NOFLAGS , ( " If set, when RUN+SEL are pressed simultaneously, disable both buttons temporarily. " ) , NULL , MDFNST_BOOL , " 0 " , NULL , NULL , NULL , PCEINPUT_SettingChanged } ,
{ " pce_fast.arcadecard " , MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE , ( " Enable Arcade Card emulation. " ) , NULL , MDFNST_BOOL , " 1 " } ,
{ " pce_fast.ocmultiplier " , MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE , ( " CPU overclock multiplier. " ) , NULL , MDFNST_UINT , " 1 " , " 1 " , " 100 " } ,
{ " pce_fast.cdspeed " , MDFNSF_EMU_STATE | MDFNSF_UNTRUSTED_SAFE , ( " CD-ROM data transfer speed multiplier. " ) , NULL , MDFNST_UINT , " 1 " , " 1 " , " 100 " } ,
{ " pce_fast.nospritelimit " , MDFNSF_NOFLAGS , ( " Remove 16-sprites-per-scanline hardware limit. " ) , NULL , MDFNST_BOOL , " 0 " } ,
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
{ " pce_fast.cdbios " , MDFNSF_EMU_STATE , ( " Path to the CD BIOS " ) , NULL , MDFNST_STRING , " syscard3.pce " } ,
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
{ " pce_fast.adpcmlp " , MDFNSF_NOFLAGS , ( " Enable dynamic ADPCM lowpass filter. " ) , NULL , MDFNST_BOOL , " 0 " } ,
{ " pce_fast.cdpsgvolume " , MDFNSF_NOFLAGS , ( " PSG volume when playing a CD game. " ) , NULL , MDFNST_UINT , " 100 " , " 0 " , " 200 " } ,
{ " pce_fast.cddavolume " , MDFNSF_NOFLAGS , ( " CD-DA volume. " ) , NULL , MDFNST_UINT , " 100 " , " 0 " , " 200 " } ,
{ " pce_fast.adpcmvolume " , MDFNSF_NOFLAGS , ( " ADPCM volume. " ) , NULL , MDFNST_UINT , " 100 " , " 0 " , " 200 " } ,
{ NULL }
2014-06-19 21:10:59 +00:00
} ;
static uint8 MemRead ( uint32 addr )
{
2014-11-20 03:28:28 +00:00
return ( PCERead [ ( addr / 8192 ) & 0xFF ] ( addr ) ) ;
2014-06-19 21:10:59 +00:00
}
static const FileExtensionSpecStruct KnownExtensions [ ] =
{
2014-11-20 03:28:28 +00:00
{ " .pce " , ( " PC Engine ROM Image " ) } ,
{ NULL , NULL }
2014-06-19 21:10:59 +00:00
} ;
2014-06-20 17:54:30 +00:00
static const uint8 BRAM_Init_String [ 8 ] = { ' H ' , ' U ' , ' B ' , ' M ' , 0x00 , 0x88 , 0x10 , 0x80 } ; //"HUBM\x00\x88\x10\x80";
2014-11-20 03:28:28 +00:00
ArcadeCard * arcade_card = NULL ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
static uint8 * HuCROM = NULL ;
2014-06-20 17:54:30 +00:00
static bool IsPopulous ;
bool PCE_IsCD ;
uint8 SaveRAM [ 2048 ] ;
static DECLFW ( ACPhysWrite )
{
2014-11-20 03:28:28 +00:00
arcade_card - > PhysWrite ( A , V ) ;
2014-06-20 17:54:30 +00:00
}
static DECLFR ( ACPhysRead )
{
2014-11-20 03:28:28 +00:00
return ( arcade_card - > PhysRead ( A ) ) ;
2014-06-20 17:54:30 +00:00
}
static DECLFR ( SaveRAMRead )
{
2014-11-20 03:28:28 +00:00
if ( ( ! PCE_IsCD | | PCECD_IsBRAMEnabled ( ) ) & & ( A & 8191 ) < 2048 )
return ( SaveRAM [ A & 2047 ] ) ;
else
return ( 0xFF ) ;
2014-06-20 17:54:30 +00:00
}
static DECLFW ( SaveRAMWrite )
{
2014-11-20 03:28:28 +00:00
if ( ( ! PCE_IsCD | | PCECD_IsBRAMEnabled ( ) ) & & ( A & 8191 ) < 2048 )
SaveRAM [ A & 2047 ] = V ;
2014-06-20 17:54:30 +00:00
}
static DECLFR ( HuCRead )
{
2014-11-20 03:28:28 +00:00
return ROMSpace [ A ] ;
2014-06-20 17:54:30 +00:00
}
static DECLFW ( HuCRAMWrite )
{
2014-11-20 03:28:28 +00:00
ROMSpace [ A ] = V ;
2014-06-20 17:54:30 +00:00
}
static DECLFW ( HuCRAMWriteCDSpecial ) // Hyper Dyne Special hack
{
2014-11-20 03:28:28 +00:00
BaseRAM [ 0x2000 | ( A & 0x1FFF ) ] = V ;
ROMSpace [ A ] = V ;
2014-06-20 17:54:30 +00:00
}
static uint8 HuCSF2Latch = 0 ;
static DECLFR ( HuCSF2Read )
{
2014-11-20 03:28:28 +00:00
return ( HuCROM [ ( A & 0x7FFFF ) + 0x80000 + HuCSF2Latch *
0x80000 ] ) ; // | (HuCSF2Latch << 19) ]);
2014-06-20 17:54:30 +00:00
}
static DECLFW ( HuCSF2Write )
{
2014-11-20 03:28:28 +00:00
if ( ( A & 0x1FFC ) = = 0x1FF0 )
HuCSF2Latch = ( A & 0x3 ) ;
2014-06-20 17:54:30 +00:00
}
2014-06-20 21:11:19 +00:00
static void Cleanup ( void )
{
2014-11-20 03:28:28 +00:00
if ( arcade_card )
2014-06-20 21:11:19 +00:00
delete arcade_card ;
arcade_card = NULL ;
2014-11-20 03:28:28 +00:00
if ( PCE_IsCD )
2014-06-20 21:11:19 +00:00
PCECD_Close ( ) ;
2014-11-20 03:28:28 +00:00
if ( HuCROM )
2014-06-20 21:11:19 +00:00
MDFN_free ( HuCROM ) ;
HuCROM = NULL ;
}
2014-11-20 03:28:28 +00:00
int HuCLoad ( const uint8 * data , uint32 len , uint32 crc32 )
{
uint32 sf2_threshold = 2048 * 1024 ;
uint32 sf2_required_size = 2048 * 1024 + 512 * 1024 ;
uint32 m_len = ( len + 8191 ) & ~ 8191 ;
bool sf2_mapper = FALSE ;
if ( m_len > = sf2_threshold )
{
sf2_mapper = TRUE ;
if ( m_len ! = sf2_required_size )
m_len = sf2_required_size ;
}
IsPopulous = 0 ;
PCE_IsCD = 0 ;
MDFN_printf ( ( " ROM: %dKiB \n " ) , ( len + 1023 ) / 1024 ) ;
MDFN_printf ( ( " ROM CRC32: 0x%04x \n " ) , crc32 ) ;
if ( ! ( HuCROM = ( uint8 * ) MDFN_malloc ( m_len , ( " HuCard ROM " ) ) ) )
return ( 0 ) ;
memset ( HuCROM , 0xFF , m_len ) ;
memcpy ( HuCROM , data , ( m_len < len ) ? m_len : len ) ;
memset ( ROMSpace , 0xFF , 0x88 * 8192 + 8192 ) ;
if ( m_len = = 0x60000 )
{
memcpy ( ROMSpace + 0x00 * 8192 , HuCROM , 0x20 * 8192 ) ;
memcpy ( ROMSpace + 0x20 * 8192 , HuCROM , 0x20 * 8192 ) ;
memcpy ( ROMSpace + 0x40 * 8192 , HuCROM + 0x20 * 8192 , 0x10 * 8192 ) ;
memcpy ( ROMSpace + 0x50 * 8192 , HuCROM + 0x20 * 8192 , 0x10 * 8192 ) ;
memcpy ( ROMSpace + 0x60 * 8192 , HuCROM + 0x20 * 8192 , 0x10 * 8192 ) ;
memcpy ( ROMSpace + 0x70 * 8192 , HuCROM + 0x20 * 8192 , 0x10 * 8192 ) ;
}
else if ( m_len = = 0x80000 )
{
memcpy ( ROMSpace + 0x00 * 8192 , HuCROM , 0x40 * 8192 ) ;
memcpy ( ROMSpace + 0x40 * 8192 , HuCROM + 0x20 * 8192 , 0x20 * 8192 ) ;
memcpy ( ROMSpace + 0x60 * 8192 , HuCROM + 0x20 * 8192 , 0x20 * 8192 ) ;
}
else
memcpy ( ROMSpace + 0x00 * 8192 , HuCROM ,
( m_len < 1024 * 1024 ) ? m_len : 1024 * 1024 ) ;
for ( int x = 0x00 ; x < 0x80 ; x + + )
{
HuCPUFastMap [ x ] = ROMSpace ;
PCERead [ x ] = HuCRead ;
}
if ( ! memcmp ( HuCROM + 0x1F26 , " POPULOUS " , strlen ( " POPULOUS " ) ) )
{
uint8 * PopRAM = ROMSpace + 0x40 * 8192 ;
memset ( PopRAM , 0xFF , 32768 ) ;
IsPopulous = 1 ;
MDFN_printf ( " Populous \n " ) ;
for ( int x = 0x40 ; x < 0x44 ; x + + )
{
HuCPUFastMap [ x ] = & PopRAM [ ( x & 3 ) * 8192 ] - x * 8192 ;
PCERead [ x ] = HuCRead ;
PCEWrite [ x ] = HuCRAMWrite ;
}
// MDFNMP_AddRAM(32768, 0x40 * 8192, PopRAM);
}
else
{
memset ( SaveRAM , 0x00 , 2048 ) ;
memcpy ( SaveRAM , BRAM_Init_String ,
8 ) ; // So users don't have to manually intialize the file cabinet
// in the CD BIOS screen.
PCEWrite [ 0xF7 ] = SaveRAMWrite ;
PCERead [ 0xF7 ] = SaveRAMRead ;
// MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM);
}
// 0x1A558
//if(len >= 0x20000 && !memcmp(HuCROM + 0x1A558, "STREET FIGHTER#", strlen("STREET FIGHTER#")))
if ( sf2_mapper )
{
for ( int x = 0x40 ; x < 0x80 ; x + + )
{
// FIXME: PCE_FAST
HuCPUFastMap [ x ] =
NULL ; // Make sure our reads go through our read function, and not a table lookup
PCERead [ x ] = HuCSF2Read ;
}
PCEWrite [ 0 ] = HuCSF2Write ;
MDFN_printf ( " Street Fighter 2 Mapper \n " ) ;
HuCSF2Latch = 0 ;
}
return ( 1 ) ;
}
2014-06-20 17:54:30 +00:00
bool IsBRAMUsed ( void )
{
2014-11-20 03:28:28 +00:00
if ( memcmp ( SaveRAM , BRAM_Init_String , 8 ) ) // HUBM string is modified/missing
return ( 1 ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
for ( int x = 8 ; x < 2048 ; x + + )
if ( SaveRAM [ x ] ) return ( 1 ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
return ( 0 ) ;
2014-06-20 17:54:30 +00:00
}
2014-11-20 03:28:28 +00:00
int HuCLoadCD ( const char * bios_path )
2014-06-20 17:54:30 +00:00
{
2014-11-20 03:28:28 +00:00
static const FileExtensionSpecStruct KnownBIOSExtensions [ ] =
{
{ " .pce " , ( " PC Engine ROM Image " ) } ,
{ " .bin " , ( " PC Engine ROM Image " ) } ,
{ " .bios " , ( " BIOS Image " ) } ,
{ NULL , NULL }
} ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
MDFNFILE fp = { 0 } ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
if ( ! MDFNFILE_Open ( & fp , bios_path , KnownBIOSExtensions , ( " CD BIOS " ) ) )
return ( 0 ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
memset ( ROMSpace , 0xFF , 262144 ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
memcpy ( ROMSpace , GET_FDATA ( fp ) + ( GET_FSIZE ( fp ) & 512 ) ,
( ( GET_FSIZE ( fp ) & ~ 512 ) > 262144 ) ? 262144 : ( GET_FSIZE ( fp ) & ~ 512 ) ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
MDFNFILE_Close ( & fp ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
PCE_IsCD = 1 ;
PCE_InitCD ( ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
MDFN_printf ( ( " Arcade Card Emulation: %s \n " ) ,
PCE_ACEnabled ? ( " Enabled " ) : ( " Disabled " ) ) ;
for ( int x = 0 ; x < 0x40 ; x + + )
{
HuCPUFastMap [ x ] = ROMSpace ;
PCERead [ x ] = HuCRead ;
}
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
for ( int x = 0x68 ; x < 0x88 ; x + + )
{
HuCPUFastMap [ x ] = ROMSpace ;
PCERead [ x ] = HuCRead ;
PCEWrite [ x ] = HuCRAMWrite ;
}
PCEWrite [ 0x80 ] = HuCRAMWriteCDSpecial ; // Hyper Dyne Special hack
// MDFNMP_AddRAM(262144, 0x68 * 8192, ROMSpace + 0x68 * 8192);
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
if ( PCE_ACEnabled )
{
if ( ! ( arcade_card = new ArcadeCard ( ) ) )
{
MDFN_PrintError ( ( " Error creating %s object. \n " ) , " ArcadeCard " ) ;
Cleanup ( ) ;
return ( 0 ) ;
}
2014-06-20 21:11:19 +00:00
2014-11-20 03:28:28 +00:00
for ( int x = 0x40 ; x < 0x44 ; x + + )
{
HuCPUFastMap [ x ] = NULL ;
PCERead [ x ] = ACPhysRead ;
PCEWrite [ x ] = ACPhysWrite ;
}
}
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
memset ( SaveRAM , 0x00 , 2048 ) ;
memcpy ( SaveRAM , BRAM_Init_String ,
8 ) ; // So users don't have to manually intialize the file cabinet
// in the CD BIOS screen.
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
PCEWrite [ 0xF7 ] = SaveRAMWrite ;
PCERead [ 0xF7 ] = SaveRAMRead ;
// MDFNMP_AddRAM(2048, 0xF7 * 8192, SaveRAM);
return ( 1 ) ;
2014-06-20 17:54:30 +00:00
}
2014-11-20 03:28:28 +00:00
int HuC_StateAction ( StateMem * sm , int load , int data_only )
2014-06-20 17:54:30 +00:00
{
2014-11-20 03:28:28 +00:00
SFORMAT StateRegs [ ] =
{
SFARRAY ( ROMSpace + 0x40 * 8192 , IsPopulous ? 32768 : 0 ) ,
SFARRAY ( SaveRAM , IsPopulous ? 0 : 2048 ) ,
SFARRAY ( ROMSpace + 0x68 * 8192 , PCE_IsCD ? 262144 : 0 ) ,
SFVAR ( HuCSF2Latch ) ,
SFEND
} ;
int ret = MDFNSS_StateAction ( sm , load , data_only , StateRegs , " HuC " ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
if ( load )
HuCSF2Latch & = 0x3 ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
if ( PCE_IsCD )
{
ret & = PCECD_StateAction ( sm , load , data_only ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
if ( arcade_card )
ret & = arcade_card - > StateAction ( sm , load , data_only ) ;
}
return ( ret ) ;
2014-06-20 17:54:30 +00:00
}
2014-06-20 21:11:19 +00:00
void HuC_Close ( void )
2014-06-20 17:54:30 +00:00
{
2014-06-20 21:11:19 +00:00
Cleanup ( ) ;
2014-06-20 17:54:30 +00:00
}
void HuC_Power ( void )
{
2014-11-20 03:28:28 +00:00
if ( PCE_IsCD )
memset ( ROMSpace + 0x68 * 8192 , 0x00 , 262144 ) ;
2014-06-20 17:54:30 +00:00
2014-11-20 03:28:28 +00:00
if ( arcade_card )
arcade_card - > Power ( ) ;
2014-06-20 17:54:30 +00:00
}
2014-06-19 21:10:59 +00:00
} ;
MDFNGI EmulatedPCE_Fast =
{
2014-11-20 03:28:28 +00:00
" pce_fast " ,
" PC Engine (CD)/TurboGrafx 16 (CD)/SuperGrafx " ,
KnownExtensions ,
MODPRIO_INTERNAL_LOW ,
NULL ,
& PCEInputInfo ,
Load ,
LoadCD ,
TestMagicCD ,
CloseGame ,
VDC_SetLayerEnableMask ,
NULL ,
NULL ,
NULL ,
NULL ,
NULL ,
MemRead ,
false ,
StateAction ,
Emulate ,
PCEINPUT_SetInput ,
DoSimpleCommand ,
PCESettings ,
MDFN_MASTERCLOCK_FIXED ( PCE_MASTER_CLOCK ) ,
0 ,
true , // Multires possible?
0 , // lcm_width
0 , // lcm_height
NULL , // Dummy
288 , // Nominal width
232 , // Nominal height
512 , // Framebuffer width
242 , // Framebuffer height
2 , // Number of output sound channels
2014-06-19 21:10:59 +00:00
} ;
2014-11-20 03:28:28 +00:00
static void ReadM3U ( std : : vector < std : : string > & file_list , std : : string path ,
unsigned depth = 0 )
2014-06-19 21:34:42 +00:00
{
2014-11-20 03:28:28 +00:00
std : : vector < std : : string > ret ;
FileWrapper m3u_file ( path . c_str ( ) , FileWrapper : : MODE_READ , ( " M3U CD Set " ) ) ;
std : : string dir_path ;
char linebuf [ 2048 ] ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
MDFN_GetFilePathComponents ( path , & dir_path ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
while ( m3u_file . get_line ( linebuf , sizeof ( linebuf ) ) )
{
std : : string efp ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
if ( linebuf [ 0 ] = = ' # ' ) continue ;
MDFN_rtrim ( linebuf ) ;
if ( linebuf [ 0 ] = = 0 ) continue ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
efp = MDFN_EvalFIP ( dir_path , std : : string ( linebuf ) ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
if ( efp . size ( ) > = 4 & & efp . substr ( efp . size ( ) - 4 ) = = " .m3u " )
{
assert ( efp ! = path ) ;
// throw(MDFN_Error(0, ("M3U at \"%s\" references self."), efp.c_str()));
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
assert ( depth ! = 99 ) ;
// throw(MDFN_Error(0, ("M3U load recursion too deep!")));
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
ReadM3U ( file_list , efp , depth + + ) ;
}
else
file_list . push_back ( efp ) ;
}
2014-06-19 21:34:42 +00:00
}
2014-11-20 03:28:28 +00:00
static std : : vector < CDIF * > CDInterfaces ; // FIXME: Cleanup on error out.
2014-06-19 21:34:42 +00:00
// TODO: LoadCommon()
2014-11-20 03:28:28 +00:00
MDFNGI * MDFNI_LoadCD ( const char * force_module , const char * devicename )
2014-06-19 21:34:42 +00:00
{
2014-11-20 03:28:28 +00:00
uint8 LayoutMD5 [ 16 ] ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
MDFN_printf ( ( " Loading %s... \n \n " ) , devicename ? devicename : ( " PHYSICAL CD " ) ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
try
{
if ( devicename & & strlen ( devicename ) > 4
& & ! strcasecmp ( devicename + strlen ( devicename ) - 4 , " .m3u " ) )
{
std : : vector < std : : string > file_list ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
ReadM3U ( file_list , devicename ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
for ( unsigned i = 0 ; i < file_list . size ( ) ; i + + )
CDInterfaces . push_back ( CDIF_Open ( file_list [ i ] . c_str ( ) , false ,
old_cdimagecache ) ) ;
}
else
CDInterfaces . push_back ( CDIF_Open ( devicename , false , old_cdimagecache ) ) ;
}
catch ( std : : exception & e )
{
MDFND_PrintError ( e . what ( ) ) ;
MDFN_PrintError ( ( " Error opening CD. " ) ) ;
return ( 0 ) ;
}
//
// Print out a track list for all discs.
//
MDFN_indent ( 1 ) ;
for ( unsigned i = 0 ; i < CDInterfaces . size ( ) ; i + + )
2014-06-19 21:34:42 +00:00
{
2014-11-20 03:28:28 +00:00
CDUtility : : TOC toc ;
CDInterfaces [ i ] - > ReadTOC ( & toc ) ;
MDFN_printf ( ( " CD %d Layout: \n " ) , i + 1 ) ;
MDFN_indent ( 1 ) ;
for ( int32 track = toc . first_track ; track < = toc . last_track ; track + + )
MDFN_printf ( ( " Track %2d, LBA: %6d %s \n " ) , track , toc . tracks [ track ] . lba ,
( toc . tracks [ track ] . control & 0x4 ) ? " DATA " : " AUDIO " ) ;
MDFN_printf ( " Leadout: %6d \n " , toc . tracks [ 100 ] . lba ) ;
MDFN_indent ( - 1 ) ;
MDFN_printf ( " \n " ) ;
2014-06-19 21:34:42 +00:00
}
2014-11-20 03:28:28 +00:00
MDFN_indent ( - 1 ) ;
// This if statement will be true if force_module references a system without CDROM support.
if ( ! MDFNGameInfo - > LoadCD )
{
MDFN_PrintError ( ( " Specified system \" %s \" doesn't support CDs! " ) , force_module ) ;
return ( 0 ) ;
}
MDFN_printf ( ( " Using module: %s(%s) \n \n " ) , MDFNGameInfo - > shortname ,
MDFNGameInfo - > fullname ) ;
// TODO: include module name in hash
memcpy ( MDFNGameInfo - > MD5 , LayoutMD5 , 16 ) ;
if ( ! ( MDFNGameInfo - > LoadCD ( & CDInterfaces ) ) )
{
for ( unsigned i = 0 ; i < CDInterfaces . size ( ) ; i + + )
delete CDInterfaces [ i ] ;
CDInterfaces . clear ( ) ;
MDFNGameInfo = NULL ;
return ( 0 ) ;
}
//MDFNI_SetLayerEnableMask(~0ULL);
// MDFN_LoadGameCheats(NULL);
// MDFNMP_InstallReadPatches();
return ( MDFNGameInfo ) ;
}
MDFNGI * MDFNI_LoadGame ( const char * force_module , const char * name )
{
MDFNFILE GameFile = { 0 } ;
std : : vector < FileExtensionSpecStruct > valid_iae ;
2014-06-19 21:34:42 +00:00
MDFNGameInfo = & EmulatedPCE_Fast ;
2014-11-20 03:28:28 +00:00
if ( strlen ( name ) > 4 & & ( ! strcasecmp ( name + strlen ( name ) - 4 , " .cue " )
| | ! strcasecmp ( name + strlen ( name ) - 4 , " .ccd " )
| | ! strcasecmp ( name + strlen ( name ) - 4 , " .toc " )
| | ! strcasecmp ( name + strlen ( name ) - 4 , " .m3u " ) ) )
return ( MDFNI_LoadCD ( force_module , name ) ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
MDFN_printf ( ( " Loading %s... \n " ) , name ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
MDFN_indent ( 1 ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
// Construct a NULL-delimited list of known file extensions for MDFN_fopen()
const FileExtensionSpecStruct * curexts = MDFNGameInfo - > FileExtensions ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
while ( curexts - > extension & & curexts - > description )
2014-06-19 21:34:42 +00:00
{
valid_iae . push_back ( * curexts ) ;
curexts + + ;
}
2014-11-20 03:28:28 +00:00
if ( ! MDFNFILE_Open ( & GameFile , name , & valid_iae [ 0 ] , ( " game " ) ) )
2014-06-19 21:34:42 +00:00
{
MDFNGameInfo = NULL ;
return 0 ;
}
2014-11-20 03:28:28 +00:00
MDFN_printf ( ( " Using module: %s(%s) \n \n " ) , MDFNGameInfo - > shortname ,
MDFNGameInfo - > fullname ) ;
MDFN_indent ( 1 ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
//
// Load per-game settings
//
// Maybe we should make a "pgcfg" subdir, and automatically load all files in it?
// End load per-game settings
//
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
if ( MDFNGameInfo - > Load ( name , & GameFile ) < = 0 )
2014-06-19 21:34:42 +00:00
{
2014-11-20 03:28:28 +00:00
MDFNFILE_Close ( & GameFile ) ;
2014-06-19 21:34:42 +00:00
MDFN_indent ( - 2 ) ;
MDFNGameInfo = NULL ;
2014-11-20 03:28:28 +00:00
return ( 0 ) ;
2014-06-19 21:34:42 +00:00
}
2014-11-20 03:28:28 +00:00
// MDFN_LoadGameCheats(NULL);
// MDFNMP_InstallReadPatches();
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
MDFN_indent ( - 2 ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
if ( ! MDFNGameInfo - > name )
2014-06-19 21:34:42 +00:00
{
unsigned int x ;
2014-11-20 03:28:28 +00:00
char * tmp ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
MDFNGameInfo - > name = ( UTF8 * ) strdup ( GetFNComponent ( name ) ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
for ( x = 0 ; x < strlen ( ( char * ) MDFNGameInfo - > name ) ; x + + )
2014-06-19 21:34:42 +00:00
{
2014-11-20 03:28:28 +00:00
if ( MDFNGameInfo - > name [ x ] = = ' _ ' )
2014-06-19 21:34:42 +00:00
MDFNGameInfo - > name [ x ] = ' ' ;
}
2014-11-20 03:28:28 +00:00
if ( ( tmp = strrchr ( ( char * ) MDFNGameInfo - > name , ' . ' ) ) )
* tmp = 0 ;
2014-06-19 21:34:42 +00:00
}
2014-11-20 03:28:28 +00:00
return ( MDFNGameInfo ) ;
2014-06-19 21:34:42 +00:00
}
static int curindent = 0 ;
void MDFN_indent ( int indent )
{
2014-11-20 03:28:28 +00:00
curindent + = indent ;
2014-06-19 21:34:42 +00:00
}
static uint8 lastchar = 0 ;
2014-06-19 21:10:59 +00:00
2014-11-20 03:28:28 +00:00
static MDFNGI * game ;
2014-04-21 22:25:50 +00:00
struct retro_perf_callback perf_cb ;
retro_get_cpu_features_t perf_get_cpu_features_cb = NULL ;
2014-04-20 14:32:46 +00:00
retro_log_printf_t log_cb ;
2012-06-03 15:48:14 +00:00
static retro_video_refresh_t video_cb ;
static retro_audio_sample_t audio_cb ;
static retro_audio_sample_batch_t audio_batch_cb ;
static retro_environment_t environ_cb ;
static retro_input_poll_t input_poll_cb ;
static retro_input_state_t input_state_cb ;
2013-02-25 19:39:39 +00:00
static bool overscan ;
2012-11-16 14:12:25 +00:00
static double last_sound_rate ;
2014-11-20 03:28:28 +00:00
static MDFN_Surface surf = { NULL , 0 , 0 , 0 } ;
2012-06-03 15:48:14 +00:00
2012-06-15 23:00:17 +00:00
static bool failed_init ;
2012-06-03 15:48:14 +00:00
2012-10-13 13:31:49 +00:00
std : : string retro_base_directory ;
std : : string retro_base_name ;
2014-02-07 07:16:01 +00:00
std : : string retro_save_directory ;
2012-10-13 13:31:49 +00:00
2014-11-20 03:28:28 +00:00
static void set_basename ( const char * path )
2013-04-27 14:40:24 +00:00
{
2014-11-20 03:28:28 +00:00
const char * base = strrchr ( path , ' / ' ) ;
2013-04-27 14:40:24 +00:00
if ( ! base )
base = strrchr ( path , ' \\ ' ) ;
if ( base )
retro_base_name = base + 1 ;
else
retro_base_name = path ;
retro_base_name = retro_base_name . substr ( 0 , retro_base_name . find_last_of ( ' . ' ) ) ;
}
2014-06-18 20:01:17 +00:00
# include "mednafen/pce_fast/pcecd.h"
2014-06-18 19:55:15 +00:00
2012-10-20 23:47:02 +00:00
# define MEDNAFEN_CORE_NAME_MODULE "pce_fast"
2012-10-20 21:32:28 +00:00
# define MEDNAFEN_CORE_NAME "Mednafen PCE Fast"
2014-06-23 12:52:11 +00:00
# define MEDNAFEN_CORE_VERSION "v0.9.36.1"
2014-06-22 03:57:12 +00:00
# define MEDNAFEN_CORE_EXTENSIONS "pce|cue|ccd"
2012-10-20 23:47:02 +00:00
# define MEDNAFEN_CORE_TIMING_FPS 59.82
2014-06-20 22:31:52 +00:00
# define MEDNAFEN_CORE_GEOMETRY_BASE_W 288
# define MEDNAFEN_CORE_GEOMETRY_BASE_H 232
2012-10-20 23:47:02 +00:00
# define MEDNAFEN_CORE_GEOMETRY_MAX_W 512
# define MEDNAFEN_CORE_GEOMETRY_MAX_H 242
# define MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO (4.0 / 3.0)
# define FB_WIDTH 512
# define FB_HEIGHT 242
2012-10-22 12:34:14 +00:00
2013-10-01 12:28:59 +00:00
# define FB_MAX_HEIGHT FB_HEIGHT
2012-10-20 21:32:28 +00:00
static void check_system_specs ( void )
{
2014-06-23 01:12:05 +00:00
unsigned level = 5 ;
2012-10-22 12:34:14 +00:00
environ_cb ( RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL , & level ) ;
2012-10-20 21:32:28 +00:00
}
2014-04-21 22:25:50 +00:00
void retro_init ( void )
2012-06-03 15:48:14 +00:00
{
2014-01-02 01:50:09 +00:00
struct retro_log_callback log ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_LOG_INTERFACE , & log ) )
log_cb = log . log ;
2014-11-20 03:28:28 +00:00
else
2014-01-02 01:50:09 +00:00
log_cb = NULL ;
2014-06-19 21:34:42 +00:00
CDUtility : : CDUtility_Init ( ) ;
2012-06-03 15:48:14 +00:00
2014-11-20 03:28:28 +00:00
const char * dir = NULL ;
2012-06-15 23:00:17 +00:00
2012-06-11 23:03:09 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY , & dir ) & & dir )
{
2012-10-13 13:31:49 +00:00
retro_base_directory = dir ;
2012-11-10 01:20:13 +00:00
// Make sure that we don't have any lingering slashes, etc, as they break Windows.
2012-11-10 11:59:05 +00:00
size_t last = retro_base_directory . find_last_not_of ( " / \\ " ) ;
if ( last ! = std : : string : : npos )
last + + ;
retro_base_directory = retro_base_directory . substr ( 0 , last ) ;
2012-06-11 23:03:09 +00:00
}
2012-06-15 23:00:17 +00:00
else
2012-06-11 23:03:09 +00:00
{
2013-12-17 01:24:08 +00:00
/* TODO: Add proper fallback */
if ( log_cb )
2014-11-20 03:28:28 +00:00
log_cb ( RETRO_LOG_WARN ,
" System directory is not defined. Fallback on using same dir as ROM for system directory later ... \n " ) ;
2012-06-15 23:00:17 +00:00
failed_init = true ;
2012-06-11 23:03:09 +00:00
}
2014-02-07 07:07:58 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY , & dir ) & & dir )
{
2014-11-20 03:28:28 +00:00
// If save directory is defined use it, otherwise use system directory
2014-02-07 22:34:14 +00:00
retro_save_directory = * dir ? dir : retro_base_directory ;
2014-02-07 07:07:58 +00:00
// Make sure that we don't have any lingering slashes, etc, as they break Windows.
size_t last = retro_save_directory . find_last_not_of ( " / \\ " ) ;
if ( last ! = std : : string : : npos )
last + + ;
2014-11-20 03:28:28 +00:00
retro_save_directory = retro_save_directory . substr ( 0 , last ) ;
2014-02-07 07:07:58 +00:00
}
else
{
/* TODO: Add proper fallback */
if ( log_cb )
2014-11-20 03:28:28 +00:00
log_cb ( RETRO_LOG_WARN ,
" Save directory is not defined. Fallback on using SYSTEM directory ... \n " ) ;
retro_save_directory = retro_base_directory ;
}
2012-06-09 22:46:41 +00:00
2012-10-22 12:34:14 +00:00
enum retro_pixel_format rgb565 = RETRO_PIXEL_FORMAT_RGB565 ;
2013-12-17 01:24:08 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_SET_PIXEL_FORMAT , & rgb565 ) & & log_cb )
2014-11-20 03:28:28 +00:00
log_cb ( RETRO_LOG_INFO ,
" Frontend supports RGB565 - will use that instead of XRGB1555. \n " ) ;
2012-10-22 12:34:14 +00:00
2014-04-21 22:25:50 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_PERF_INTERFACE , & perf_cb ) )
perf_get_cpu_features_cb = perf_cb . get_cpu_features ;
else
perf_get_cpu_features_cb = NULL ;
2014-11-20 03:28:28 +00:00
2014-06-25 18:16:22 +00:00
setting_initial_scanline = 0 ;
setting_last_scanline = 242 ;
2014-04-21 22:25:50 +00:00
2012-10-20 21:32:28 +00:00
check_system_specs ( ) ;
2014-11-18 22:14:37 +00:00
# ifdef PSP
PSPPROF_INIT ;
# endif
2012-06-03 15:48:14 +00:00
}
2014-04-20 14:32:46 +00:00
void retro_reset ( void )
2012-06-03 15:48:14 +00:00
{
2014-06-20 20:49:22 +00:00
DoSimpleCommand ( MDFN_MSC_RESET ) ;
2012-06-03 15:48:14 +00:00
}
2014-11-20 03:28:28 +00:00
bool retro_load_game_special ( unsigned , const struct retro_game_info * , size_t )
2012-06-03 15:48:14 +00:00
{
return false ;
}
2014-11-20 03:28:28 +00:00
static void set_volume ( uint32_t * ptr , unsigned number )
2013-05-24 15:26:57 +00:00
{
2014-11-20 03:28:28 +00:00
switch ( number )
2013-05-24 15:26:57 +00:00
{
2014-11-20 03:28:28 +00:00
default :
* ptr = number ;
break ;
2013-05-24 15:26:57 +00:00
}
}
2014-06-20 20:49:22 +00:00
2013-04-09 02:05:18 +00:00
static void check_variables ( void )
{
struct retro_variable var = { 0 } ;
2014-06-20 20:49:22 +00:00
var . key = " pce_fast_cdimagecache " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
{
bool cdimage_cache = true ;
if ( strcmp ( var . value , " enabled " ) = = 0 )
cdimage_cache = true ;
else if ( strcmp ( var . value , " disabled " ) = = 0 )
cdimage_cache = false ;
if ( cdimage_cache ! = old_cdimagecache )
old_cdimagecache = cdimage_cache ;
}
2013-04-09 02:05:18 +00:00
var . key = " pce_nospritelimit " ;
2014-06-20 20:49:22 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-04-09 02:05:18 +00:00
{
if ( strcmp ( var . value , " disabled " ) = = 0 )
setting_pce_fast_nospritelimit = 0 ;
else if ( strcmp ( var . value , " enabled " ) = = 0 )
setting_pce_fast_nospritelimit = 1 ;
}
2013-05-24 15:26:57 +00:00
2013-05-24 15:37:36 +00:00
var . key = " pce_keepaspect " ;
2014-06-20 20:49:22 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-05-24 15:37:36 +00:00
{
if ( strcmp ( var . value , " disabled " ) = = 0 )
{
setting_pce_keepaspect = 0 ;
2014-06-20 20:49:22 +00:00
EmulatedPCE_Fast . fb_width = 512 ;
EmulatedPCE_Fast . nominal_width = 341 ;
EmulatedPCE_Fast . lcm_width = 341 ;
2013-05-24 15:37:36 +00:00
}
else if ( strcmp ( var . value , " enabled " ) = = 0 )
{
setting_pce_keepaspect = 1 ;
2014-06-20 20:49:22 +00:00
EmulatedPCE_Fast . fb_width = 682 ;
EmulatedPCE_Fast . nominal_width = 288 ;
EmulatedPCE_Fast . lcm_width = 1024 ;
2013-05-24 15:37:36 +00:00
}
}
2014-06-25 18:03:28 +00:00
var . key = " pce_initial_scanline " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2014-06-25 18:16:22 +00:00
setting_initial_scanline = atoi ( var . value ) ;
2014-06-25 18:03:28 +00:00
var . key = " pce_last_scanline " ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2014-06-25 18:16:22 +00:00
setting_last_scanline = atoi ( var . value ) ;
2014-06-25 18:03:28 +00:00
2013-05-24 15:26:57 +00:00
bool do_cdsettings = false ;
var . key = " pce_cddavolume " ;
2014-06-20 20:49:22 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-05-24 15:26:57 +00:00
{
do_cdsettings = true ;
setting_pce_fast_cddavolume = atoi ( var . value ) ;
}
var . key = " pce_adpcmvolume " ;
2014-06-20 20:49:22 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-05-24 15:26:57 +00:00
{
do_cdsettings = true ;
setting_pce_fast_adpcmvolume = atoi ( var . value ) ;
}
var . key = " pce_cdpsgvolume " ;
2014-06-20 20:49:22 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-05-24 15:26:57 +00:00
{
do_cdsettings = true ;
setting_pce_fast_cdpsgvolume = atoi ( var . value ) ;
}
var . key = " pce_cdspeed " ;
2014-06-20 20:49:22 +00:00
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE , & var ) & & var . value )
2013-05-24 15:26:57 +00:00
{
do_cdsettings = true ;
setting_pce_fast_cdspeed = atoi ( var . value ) ;
}
if ( do_cdsettings )
{
2014-04-21 22:31:36 +00:00
PCE_Fast : : PCECD_Settings settings = { 0 } ;
2014-06-05 16:06:15 +00:00
settings . CDDA_Volume = ( double ) setting_pce_fast_cddavolume / 100 ;
2013-05-24 15:26:57 +00:00
settings . CD_Speed = setting_pce_fast_cdspeed ;
2014-06-05 16:06:15 +00:00
settings . ADPCM_Volume = ( double ) setting_pce_fast_adpcmvolume / 100 ;
2013-05-24 15:26:57 +00:00
2013-12-17 01:24:08 +00:00
if ( PCECD_SetSettings ( & settings ) & & log_cb )
log_cb ( RETRO_LOG_INFO , " PCE CD Audio settings changed. \n " ) ;
2013-05-24 15:26:57 +00:00
}
2013-04-09 02:05:18 +00:00
}
2013-04-09 03:23:42 +00:00
# define MAX_PLAYERS 5
# define MAX_BUTTONS 13
static uint8_t input_buf [ MAX_PLAYERS ] [ 2 ] = { 0 } ;
2014-11-20 03:28:28 +00:00
bool retro_load_game ( const struct retro_game_info * info )
2012-06-03 15:48:14 +00:00
{
2012-06-15 23:00:17 +00:00
if ( failed_init )
return false ;
2013-02-25 19:39:39 +00:00
overscan = false ;
environ_cb ( RETRO_ENVIRONMENT_GET_OVERSCAN , & overscan ) ;
2013-04-27 14:40:24 +00:00
set_basename ( info - > path ) ;
2012-10-13 13:31:49 +00:00
2014-06-20 20:49:22 +00:00
check_variables ( ) ;
2012-10-20 23:47:02 +00:00
game = MDFNI_LoadGame ( MEDNAFEN_CORE_NAME_MODULE , info - > path ) ;
2012-09-23 09:52:47 +00:00
if ( ! game )
return false ;
2014-11-20 00:55:26 +00:00
surf . w = FB_WIDTH ;
surf . h = FB_HEIGHT ;
surf . pitchinpix = FB_WIDTH ;
2014-11-20 03:28:28 +00:00
surf . pixels16 = ( uint16 * ) calloc ( FB_WIDTH * FB_HEIGHT , sizeof ( uint16 ) ) ;
2014-11-20 00:55:26 +00:00
2012-10-13 13:31:49 +00:00
2013-09-17 00:03:54 +00:00
2014-06-18 20:20:38 +00:00
// Possible endian bug ...
for ( unsigned i = 0 ; i < MAX_PLAYERS ; i + + )
2014-06-19 22:08:27 +00:00
PCEINPUT_SetInput ( i , " gamepad " , & input_buf [ i ] [ 0 ] ) ;
2014-06-18 20:20:38 +00:00
2012-06-03 15:48:14 +00:00
return game ;
}
2014-06-19 21:34:42 +00:00
void retro_unload_game ( void )
2012-06-03 15:48:14 +00:00
{
2014-11-20 03:28:28 +00:00
if ( ! MDFNGameInfo )
2013-01-19 09:22:57 +00:00
return ;
2012-11-29 22:21:44 +00:00
2014-11-20 03:28:28 +00:00
// MDFN_FlushGameCheats(0);
2014-06-19 21:34:42 +00:00
MDFNGameInfo - > CloseGame ( ) ;
2014-11-20 03:28:28 +00:00
if ( MDFNGameInfo - > name )
2014-06-19 21:34:42 +00:00
free ( MDFNGameInfo - > name ) ;
MDFNGameInfo - > name = NULL ;
2012-06-03 15:48:14 +00:00
2014-11-20 03:28:28 +00:00
// MDFNMP_Kill();
2013-04-09 03:23:42 +00:00
2014-06-19 21:34:42 +00:00
MDFNGameInfo = NULL ;
2014-11-20 03:28:28 +00:00
for ( unsigned i = 0 ; i < CDInterfaces . size ( ) ; i + + )
2014-06-19 21:34:42 +00:00
delete CDInterfaces [ i ] ;
CDInterfaces . clear ( ) ;
}
2012-07-25 01:17:14 +00:00
2012-10-20 21:32:28 +00:00
static void update_input ( void )
2012-06-03 16:58:46 +00:00
{
2014-11-20 03:28:28 +00:00
static unsigned map [ ] =
{
2012-11-22 20:03:38 +00:00
RETRO_DEVICE_ID_JOYPAD_A ,
2012-10-20 23:47:02 +00:00
RETRO_DEVICE_ID_JOYPAD_B ,
RETRO_DEVICE_ID_JOYPAD_SELECT ,
RETRO_DEVICE_ID_JOYPAD_START ,
RETRO_DEVICE_ID_JOYPAD_UP ,
RETRO_DEVICE_ID_JOYPAD_RIGHT ,
RETRO_DEVICE_ID_JOYPAD_DOWN ,
RETRO_DEVICE_ID_JOYPAD_LEFT ,
2012-11-22 20:03:38 +00:00
RETRO_DEVICE_ID_JOYPAD_Y ,
2012-10-20 23:47:02 +00:00
RETRO_DEVICE_ID_JOYPAD_X ,
RETRO_DEVICE_ID_JOYPAD_L ,
RETRO_DEVICE_ID_JOYPAD_R ,
RETRO_DEVICE_ID_JOYPAD_L2
} ;
2013-04-09 03:23:42 +00:00
for ( unsigned j = 0 ; j < MAX_PLAYERS ; j + + )
2012-10-20 23:47:02 +00:00
{
2013-04-09 03:23:42 +00:00
uint16_t input_state = 0 ;
for ( unsigned i = 0 ; i < MAX_BUTTONS ; i + + )
input_state | = input_state_cb ( j , RETRO_DEVICE_JOYPAD , 0 , map [ i ] ) ? ( 1 < < i ) : 0 ;
2012-10-20 23:47:02 +00:00
2013-04-09 03:23:42 +00:00
// Input data must be little endian.
input_buf [ j ] [ 0 ] = ( input_state > > 0 ) & 0xff ;
input_buf [ j ] [ 1 ] = ( input_state > > 8 ) & 0xff ;
2012-10-20 23:47:02 +00:00
}
2012-06-03 15:48:14 +00:00
}
2012-09-20 19:38:19 +00:00
static uint64_t video_frames , audio_frames ;
2014-06-18 19:55:15 +00:00
void retro_run ( void )
2012-06-03 15:48:14 +00:00
{
2014-11-20 03:28:28 +00:00
MDFNGI * curgame = ( MDFNGI * ) game ;
2012-11-29 22:21:44 +00:00
2012-06-03 15:48:14 +00:00
input_poll_cb ( ) ;
2012-06-03 16:58:46 +00:00
update_input ( ) ;
2012-06-03 15:48:14 +00:00
static int16_t sound_buf [ 0x10000 ] ;
2014-06-20 21:11:19 +00:00
static int32_t rects [ FB_MAX_HEIGHT ] ;
rects [ 0 ] = ~ 0 ;
2012-06-03 15:48:14 +00:00
2012-07-25 01:17:14 +00:00
EmulateSpecStruct spec = { 0 } ;
2014-11-20 00:55:26 +00:00
spec . surface = & surf ;
2012-06-03 15:48:14 +00:00
spec . SoundRate = 44100 ;
spec . SoundBuf = sound_buf ;
spec . LineWidths = rects ;
spec . SoundBufMaxSize = sizeof ( sound_buf ) / 2 ;
spec . SoundVolume = 1.0 ;
spec . soundmultiplier = 1.0 ;
2012-11-16 14:12:25 +00:00
spec . SoundBufSize = 0 ;
2013-01-19 09:22:57 +00:00
if ( spec . SoundRate ! = last_sound_rate )
2012-11-16 14:12:25 +00:00
{
spec . SoundFormatChanged = true ;
last_sound_rate = spec . SoundRate ;
}
2014-11-05 10:03:17 +00:00
# ifdef PSP
2014-11-14 20:38:35 +00:00
# ifndef DISABLE_SW_RENDER
2014-11-20 03:28:28 +00:00
pce_do_hw_render = ! input_state_cb ( 0 , RETRO_DEVICE_JOYPAD , 0 ,
RETRO_DEVICE_ID_JOYPAD_X ) ;
2014-11-14 20:38:35 +00:00
# endif
2014-11-05 10:03:17 +00:00
setting_last_scanline = 241 ;
# endif
2014-06-19 22:08:27 +00:00
Emulate ( & spec ) ;
2012-11-16 14:12:25 +00:00
2014-11-20 03:28:28 +00:00
int16 * const SoundBuf = spec . SoundBuf + spec . SoundBufSizeALMS *
curgame - > soundchan ;
2012-11-16 14:12:25 +00:00
int32 SoundBufSize = spec . SoundBufSize - spec . SoundBufSizeALMS ;
const int32 SoundBufMaxSize = spec . SoundBufMaxSize - spec . SoundBufSizeALMS ;
2012-06-03 15:48:14 +00:00
2012-11-16 14:12:25 +00:00
spec . SoundBufSize = spec . SoundBufSizeALMS + SoundBufSize ;
2012-06-03 15:48:14 +00:00
2014-06-21 21:26:47 +00:00
unsigned width = spec . DisplayRect . w & ~ 0x1 ;
2012-11-21 01:27:23 +00:00
unsigned height = spec . DisplayRect . h ;
2012-10-20 21:56:43 +00:00
2014-11-05 10:03:17 +00:00
# ifdef PSP
2014-11-14 20:38:35 +00:00
# ifndef DISABLE_SW_RENDER
2014-11-20 03:28:28 +00:00
if ( pce_do_hw_render )
2014-11-14 20:38:35 +00:00
# endif
2014-11-14 01:40:14 +00:00
video_cb ( RETRO_HW_FRAME_BUFFER_VALID , width , height , 1024 ) ;
2014-11-14 20:38:35 +00:00
# ifndef DISABLE_SW_RENDER
2014-11-05 10:03:17 +00:00
else
2014-11-20 03:28:28 +00:00
// video_cb(surf->pixels16 , MEDNAFEN_CORE_GEOMETRY_BASE_W, MEDNAFEN_CORE_GEOMETRY_BASE_H, FB_WIDTH << 1);
video_cb ( surf . pixels16 + surf . pitchinpix * spec . DisplayRect . y , width , height ,
FB_WIDTH < < 1 ) ;
2014-11-14 20:38:35 +00:00
# endif
2014-11-05 10:03:17 +00:00
# else
2014-11-20 03:28:28 +00:00
video_cb ( surf . pixels16 + surf . pitchinpix * spec . DisplayRect . y , width , height ,
FB_WIDTH < < 1 ) ;
2014-11-05 10:03:17 +00:00
# endif
2012-06-03 15:48:14 +00:00
2012-09-20 19:38:19 +00:00
video_frames + + ;
audio_frames + = spec . SoundBufSize ;
2012-06-03 15:48:14 +00:00
audio_batch_cb ( spec . SoundBuf , spec . SoundBufSize ) ;
2013-04-09 02:05:18 +00:00
bool updated = false ;
if ( environ_cb ( RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE , & updated ) & & updated )
check_variables ( ) ;
2014-11-13 15:53:14 +00:00
# ifdef RUN_FOR_X_FRAMES
if ( video_frames = = RUN_FOR_X_FRAMES )
environ_cb ( RETRO_ENVIRONMENT_SHUTDOWN , NULL ) ;
# endif
2012-06-03 15:48:14 +00:00
}
2014-11-20 03:28:28 +00:00
void retro_get_system_info ( struct retro_system_info * info )
2012-06-03 15:48:14 +00:00
{
memset ( info , 0 , sizeof ( * info ) ) ;
2012-10-20 21:32:28 +00:00
info - > library_name = MEDNAFEN_CORE_NAME ;
2012-10-22 12:34:14 +00:00
info - > library_version = MEDNAFEN_CORE_VERSION ;
2012-06-03 15:48:14 +00:00
info - > need_fullpath = true ;
2012-10-20 21:56:43 +00:00
info - > valid_extensions = MEDNAFEN_CORE_EXTENSIONS ;
2012-10-20 23:47:02 +00:00
info - > block_extract = false ;
2012-06-03 15:48:14 +00:00
}
2014-11-20 03:28:28 +00:00
void retro_get_system_av_info ( struct retro_system_av_info * info )
2012-06-03 15:48:14 +00:00
{
memset ( info , 0 , sizeof ( * info ) ) ;
2013-10-01 12:28:59 +00:00
info - > timing . fps = MEDNAFEN_CORE_TIMING_FPS ;
2012-06-03 15:48:14 +00:00
info - > timing . sample_rate = 44100 ;
2012-10-20 21:56:43 +00:00
info - > geometry . base_width = MEDNAFEN_CORE_GEOMETRY_BASE_W ;
info - > geometry . base_height = MEDNAFEN_CORE_GEOMETRY_BASE_H ;
info - > geometry . max_width = MEDNAFEN_CORE_GEOMETRY_MAX_W ;
info - > geometry . max_height = MEDNAFEN_CORE_GEOMETRY_MAX_H ;
info - > geometry . aspect_ratio = MEDNAFEN_CORE_GEOMETRY_ASPECT_RATIO ;
2012-06-03 15:48:14 +00:00
}
2012-09-20 19:38:19 +00:00
void retro_deinit ( )
{
2014-11-20 00:55:26 +00:00
if ( surf . pixels16 )
{
free ( surf . pixels16 ) ;
surf . pixels16 = NULL ;
}
2012-09-20 19:38:19 +00:00
2013-12-17 01:24:08 +00:00
if ( log_cb )
{
log_cb ( RETRO_LOG_INFO , " [%s]: Samples / Frame: %.5f \n " ,
2014-11-20 03:28:28 +00:00
MEDNAFEN_CORE_NAME , ( double ) audio_frames / video_frames ) ;
2013-12-17 01:24:08 +00:00
log_cb ( RETRO_LOG_INFO , " [%s]: Estimated FPS: %.5f \n " ,
2014-11-20 03:28:28 +00:00
MEDNAFEN_CORE_NAME , ( double ) video_frames * 44100 / audio_frames ) ;
2013-12-17 01:24:08 +00:00
}
2014-11-06 12:25:09 +00:00
2014-11-19 00:31:56 +00:00
# ifdef PERF_TEST
2014-11-06 12:25:09 +00:00
perf_cb . perf_log ( ) ;
2014-11-19 00:31:56 +00:00
# endif
# ifdef PSP
2014-11-18 22:14:37 +00:00
PSPPROF_DUMP ;
2014-11-06 12:25:09 +00:00
# endif
2012-09-20 19:38:19 +00:00
}
2012-06-03 15:48:14 +00:00
unsigned retro_get_region ( void )
{
2013-10-01 12:28:59 +00:00
return RETRO_REGION_NTSC ; // FIXME: Regions for other cores.
2012-06-03 15:48:14 +00:00
}
unsigned retro_api_version ( void )
{
return RETRO_API_VERSION ;
}
2012-07-25 01:17:14 +00:00
void retro_set_controller_port_device ( unsigned in_port , unsigned device )
{
2014-11-20 03:28:28 +00:00
MDFNGI * currgame = ( MDFNGI * ) game ;
2014-05-01 00:17:23 +00:00
if ( ! currgame )
2012-08-17 21:01:08 +00:00
return ;
2014-11-20 03:28:28 +00:00
switch ( device )
2014-05-01 00:32:39 +00:00
{
2014-11-20 03:28:28 +00:00
case RETRO_DEVICE_JOYPAD :
PCEINPUT_SetInput ( in_port , " gamepad " , & input_buf [ in_port ] [ 0 ] ) ;
break ;
case RETRO_DEVICE_MOUSE :
PCEINPUT_SetInput ( in_port , " mouse " , & input_buf [ in_port ] [ 0 ] ) ;
break ;
2014-05-01 00:32:39 +00:00
}
2012-07-25 01:17:14 +00:00
}
2012-06-03 15:48:14 +00:00
void retro_set_environment ( retro_environment_t cb )
{
environ_cb = cb ;
2013-04-09 02:05:18 +00:00
2014-11-20 03:28:28 +00:00
static const struct retro_variable vars [ ] =
{
2014-06-20 20:49:22 +00:00
{ " pce_fast_cdimagecache " , " CD Image Cache (Restart); disabled|enabled " } ,
2013-04-09 02:05:18 +00:00
{ " pce_nospritelimit " , " No Sprite Limit; disabled|enabled " } ,
2013-05-24 15:37:36 +00:00
{ " pce_keepaspect " , " Keep Aspect; enabled|disabled " } ,
2014-06-25 18:03:28 +00:00
{ " pce_initial_scanline " , " Initial scanline; 0|1|2|3|4|5|6|7|8|9|10|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40 " } ,
2014-06-25 18:53:52 +00:00
{ " pce_last_scanline " , " Last scanline; 242|241|240|239|238|237|236|235|234|232|231|230|229|228|227|226|225|224|223|222|221|220|219|218|217|216|215|214|213|212|211|210 " } ,
2014-08-17 15:51:25 +00:00
{ " pce_cddavolume " , " (CD) CDDA Volume; 100|90|80|70|60|50|40|30|20|10|0 " } ,
{ " pce_adpcmvolume " , " (CD) ADPCM Volume; 100|90|80|70|60|50|40|30|20|10|0 " } ,
{ " pce_cdpsgvolume " , " (CD) CD PSG Volume; 100|90|80|70|60|50|40|30|20|10|0 " } ,
2013-05-24 15:26:57 +00:00
{ " pce_cdspeed " , " (CD) CD Speed; 1|2|4|8 " } ,
2013-04-09 02:05:18 +00:00
{ NULL , NULL } ,
} ;
2014-05-01 00:43:04 +00:00
2014-11-20 03:28:28 +00:00
static const struct retro_controller_description pads [ ] =
{
2014-05-01 00:43:04 +00:00
{ " PCE Joypad " , RETRO_DEVICE_JOYPAD } ,
{ " Mouse " , RETRO_DEVICE_MOUSE } ,
} ;
2014-11-20 03:28:28 +00:00
static const struct retro_controller_info ports [ ] =
{
2014-05-01 00:43:04 +00:00
{ pads , 2 } ,
{ pads , 2 } ,
{ 0 } ,
} ;
2013-05-19 17:55:15 +00:00
cb ( RETRO_ENVIRONMENT_SET_VARIABLES , ( void * ) vars ) ;
2014-05-01 00:43:04 +00:00
environ_cb ( RETRO_ENVIRONMENT_SET_CONTROLLER_INFO , ( void * ) ports ) ;
2012-06-03 15:48:14 +00:00
}
void retro_set_audio_sample ( retro_audio_sample_t cb )
{
audio_cb = cb ;
}
void retro_set_audio_sample_batch ( retro_audio_sample_batch_t cb )
{
audio_batch_cb = cb ;
}
void retro_set_input_poll ( retro_input_poll_t cb )
{
input_poll_cb = cb ;
}
void retro_set_input_state ( retro_input_state_t cb )
{
input_state_cb = cb ;
}
void retro_set_video_refresh ( retro_video_refresh_t cb )
{
video_cb = cb ;
}
2012-10-20 23:47:02 +00:00
static size_t serialize_size ;
2012-06-03 15:48:14 +00:00
size_t retro_serialize_size ( void )
{
2014-11-20 03:28:28 +00:00
MDFNGI * curgame = ( MDFNGI * ) game ;
2012-10-21 01:46:12 +00:00
//if (serialize_size)
// return serialize_size;
2014-06-20 20:49:22 +00:00
if ( ! StateAction )
2012-10-21 01:46:12 +00:00
{
2013-12-17 01:24:08 +00:00
if ( log_cb )
2014-11-20 03:28:28 +00:00
log_cb ( RETRO_LOG_WARN , " [mednafen]: Module %s doesn't support save states. \n " ,
EmulatedPCE_Fast . shortname ) ;
2012-10-21 01:46:12 +00:00
return 0 ;
}
StateMem st ;
memset ( & st , 0 , sizeof ( st ) ) ;
2012-11-14 00:41:02 +00:00
if ( ! MDFNSS_SaveSM ( & st , 0 , 0 , NULL , NULL , NULL ) )
2012-10-21 01:46:12 +00:00
{
2013-12-17 01:24:08 +00:00
if ( log_cb )
2014-11-20 03:28:28 +00:00
log_cb ( RETRO_LOG_WARN , " [mednafen]: Module %s doesn't support save states. \n " ,
EmulatedPCE_Fast . shortname ) ;
2012-10-21 01:46:12 +00:00
return 0 ;
}
free ( st . data ) ;
return serialize_size = st . len ;
2012-06-03 15:48:14 +00:00
}
2014-11-20 03:28:28 +00:00
bool retro_serialize ( void * data , size_t size )
2012-06-03 15:48:14 +00:00
{
2012-10-21 01:46:12 +00:00
StateMem st ;
memset ( & st , 0 , sizeof ( st ) ) ;
st . data = ( uint8_t * ) data ;
st . malloced = size ;
2012-11-14 00:41:02 +00:00
return MDFNSS_SaveSM ( & st , 0 , 0 , NULL , NULL , NULL ) ;
2012-06-03 15:48:14 +00:00
}
2014-11-20 03:28:28 +00:00
bool retro_unserialize ( const void * data , size_t size )
2012-06-03 15:48:14 +00:00
{
2012-10-21 01:46:12 +00:00
StateMem st ;
memset ( & st , 0 , sizeof ( st ) ) ;
st . data = ( uint8_t * ) data ;
st . len = size ;
2012-11-14 00:41:02 +00:00
return MDFNSS_LoadSM ( & st , 0 , 0 ) ;
2012-06-03 15:48:14 +00:00
}
2014-11-20 03:28:28 +00:00
void * retro_get_memory_data ( unsigned type )
2012-06-03 15:48:14 +00:00
{
2014-11-20 03:28:28 +00:00
uint8_t * data ;
2014-06-20 17:54:30 +00:00
switch ( type )
{
2014-11-20 03:28:28 +00:00
case RETRO_MEMORY_SAVE_RAM :
if ( IsPopulous )
data = ( uint8_t * ) ( ROMSpace + 0x40 * 8192 ) ;
else
data = ( uint8_t * ) SaveRAM ;
break ;
default :
data = NULL ;
break ;
2014-06-20 17:54:30 +00:00
}
return data ;
2012-06-03 15:48:14 +00:00
}
2014-06-20 17:54:30 +00:00
size_t retro_get_memory_size ( unsigned type )
2012-06-03 15:48:14 +00:00
{
2014-06-20 17:54:30 +00:00
unsigned size ;
switch ( type )
{
2014-11-20 03:28:28 +00:00
case RETRO_MEMORY_SAVE_RAM :
if ( IsPopulous )
size = 32768 ;
else
size = 2048 ;
break ;
default :
size = 0 ;
break ;
2014-06-20 17:54:30 +00:00
}
return size ;
2012-06-03 15:48:14 +00:00
}
void retro_cheat_reset ( void )
{ }
2014-11-20 03:28:28 +00:00
void retro_cheat_set ( unsigned , bool , const char * )
2012-06-03 15:48:14 +00:00
{ }
2014-06-18 20:10:07 +00:00
2014-11-20 03:28:28 +00:00
MDFN_Thread * MDFND_CreateThread ( int ( * fn ) ( void * ) , void * data )
2014-06-18 20:10:07 +00:00
{
return ( MDFN_Thread * ) sthread_create ( ( void ( * ) ( void * ) ) fn , data ) ;
}
2014-11-20 03:28:28 +00:00
void MDFND_WaitThread ( MDFN_Thread * thr , int * val )
2014-06-18 20:10:07 +00:00
{
sthread_join ( ( sthread_t * ) thr ) ;
if ( val )
{
* val = 0 ;
fprintf ( stderr , " WaitThread relies on return value. \n " ) ;
}
}
2014-11-20 03:28:28 +00:00
void MDFND_KillThread ( MDFN_Thread * )
2014-06-18 20:10:07 +00:00
{
fprintf ( stderr , " Killing a thread is a BAD IDEA! \n " ) ;
}
2014-11-20 03:28:28 +00:00
MDFN_Mutex * MDFND_CreateMutex ( void )
2014-06-18 20:10:07 +00:00
{
return ( MDFN_Mutex * ) slock_new ( ) ;
}
2014-11-20 03:28:28 +00:00
void MDFND_DestroyMutex ( MDFN_Mutex * lock )
2014-06-18 20:10:07 +00:00
{
slock_free ( ( slock_t * ) lock ) ;
}
2014-11-20 03:28:28 +00:00
int MDFND_LockMutex ( MDFN_Mutex * lock )
2014-06-18 20:10:07 +00:00
{
slock_lock ( ( slock_t * ) lock ) ;
return 0 ;
}
2014-11-20 03:28:28 +00:00
int MDFND_UnlockMutex ( MDFN_Mutex * lock )
2014-06-18 20:10:07 +00:00
{
slock_unlock ( ( slock_t * ) lock ) ;
return 0 ;
}
2014-11-20 03:28:28 +00:00
MDFN_Cond * MDFND_CreateCond ( void )
2014-06-22 19:58:50 +00:00
{
return ( MDFN_Cond * ) scond_new ( ) ;
}
2014-11-20 03:28:28 +00:00
void MDFND_DestroyCond ( MDFN_Cond * cond )
2014-06-22 19:58:50 +00:00
{
scond_free ( ( scond_t * ) cond ) ;
}
2014-11-20 03:28:28 +00:00
int MDFND_WaitCond ( MDFN_Cond * cond , MDFN_Mutex * mutex )
2014-06-22 19:58:50 +00:00
{
scond_wait ( ( scond_t * ) cond , ( slock_t * ) mutex ) ;
return 0 ; // not sure about this return
}
2014-11-20 03:28:28 +00:00
int MDFND_SignalCond ( MDFN_Cond * cond )
2014-06-22 19:58:50 +00:00
{
scond_signal ( ( scond_t * ) cond ) ;
return 0 ; // not sure about this return
}
2014-06-18 20:10:07 +00:00
# ifdef _WIN32
static void sanitize_path ( std : : string & path )
{
size_t size = path . size ( ) ;
for ( size_t i = 0 ; i < size ; i + + )
if ( path [ i ] = = ' / ' )
path [ i ] = ' \\ ' ;
}
# endif
// Use a simpler approach to make sure that things go right for libretro.
2014-11-20 03:28:28 +00:00
std : : string MDFN_MakeFName ( MakeFName_Type type , int id1 , const char * cd1 )
2014-06-18 20:10:07 +00:00
{
char slash ;
# ifdef _WIN32
slash = ' \\ ' ;
# else
slash = ' / ' ;
# endif
std : : string ret ;
switch ( type )
{
2014-11-20 03:28:28 +00:00
case MDFNMKF_SAV :
ret = retro_save_directory + slash + retro_base_name +
2014-06-18 20:10:07 +00:00
std : : string ( " . " ) +
std : : string ( cd1 ) ;
2014-11-20 03:28:28 +00:00
break ;
case MDFNMKF_FIRMWARE :
ret = retro_base_directory + slash + std : : string ( cd1 ) ;
2014-06-18 20:10:07 +00:00
# ifdef _WIN32
2014-11-20 03:28:28 +00:00
sanitize_path ( ret ) ; // Because Windows path handling is mongoloid.
2014-06-18 20:10:07 +00:00
# endif
2014-11-20 03:28:28 +00:00
break ;
default :
break ;
2014-06-18 20:10:07 +00:00
}
if ( log_cb )
log_cb ( RETRO_LOG_INFO , " MDFN_MakeFName: %s \n " , ret . c_str ( ) ) ;
return ret ;
}
2014-11-20 03:28:28 +00:00
void MDFND_Message ( const char * str )
2014-06-18 20:10:07 +00:00
{
if ( log_cb )
log_cb ( RETRO_LOG_INFO , " %s \n " , str ) ;
}
2014-11-20 03:28:28 +00:00
void MDFND_MidSync ( const EmulateSpecStruct * )
2014-06-18 20:10:07 +00:00
{ }
2014-11-20 03:28:28 +00:00
void MDFN_MidLineUpdate ( EmulateSpecStruct * espec , int y )
2014-06-18 20:10:07 +00:00
{
2014-11-20 03:28:28 +00:00
//MDFND_MidLineUpdate(espec, y);
2014-06-18 20:10:07 +00:00
}
void MDFND_PrintError ( const char * err )
{
if ( log_cb )
log_cb ( RETRO_LOG_ERROR , " %s \n " , err ) ;
}
void MDFND_Sleep ( unsigned int time )
{
retro_sleep ( time ) ;
}
2014-06-19 21:34:42 +00:00
/* forward declarations */
2014-11-20 03:28:28 +00:00
extern void MDFND_DispMessage ( unsigned char * str ) ;
2014-06-19 21:34:42 +00:00
2014-11-20 03:28:28 +00:00
void MDFND_DispMessage ( unsigned char * str )
2014-06-19 21:34:42 +00:00
{
2014-11-20 03:28:28 +00:00
const char * strc = ( const char * ) str ;
2014-06-19 21:34:42 +00:00
struct retro_message msg =
{
strc ,
180
} ;
environ_cb ( RETRO_ENVIRONMENT_SET_MESSAGE , & msg ) ;
}
void MDFN_ResetMessages ( void )
{
}