Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Libretro
hatari
Commits
f19bc118
Unverified
Commit
f19bc118
authored
Oct 28, 2020
by
Libretro-Admin
Committed by
GitHub
Oct 28, 2020
Browse files
Merge pull request #66 from bbbradsmith/memory_savestate
use in-memory savestates instead of intermediate file
parents
f605173e
67728dc9
Pipeline
#4628
passed with stages
in 6 minutes and 29 seconds
Changes
6
Pipelines
7
Hide whitespace changes
Inline
Side-by-side
libretro/hatari-mapper.c
View file @
f19bc118
...
...
@@ -34,9 +34,6 @@ extern int Reset_Cold(void);
#include <time.h>
#endif
long
frame
=
0
;
static
unsigned
long
Ktime
=
0
,
LastFPSTime
=
0
;
//VIDEO
extern
SDL_Surface
*
sdlscrn
;
unsigned
short
int
bmp
[
1024
*
1024
];
...
...
@@ -52,9 +49,10 @@ char RPATH[512];
//EMU FLAGS
int
NPAGE
=-
1
,
KCOL
=
1
,
BKGCOLOR
=
0
,
MAXPAS
=
6
;
int
SHIFTON
=-
1
,
MOUSEMODE
=-
1
,
SHOWKEY
=-
1
,
PAS
=
4
,
STATUTON
=-
1
;
int
SND
;
//SOUND ON/OFF
int
SND
=
1
;
//SOUND ON/OFF
static
int
firstps
=
0
;
int
pauseg
=
0
;
//enter_gui
int
slowdown
=
0
;
//JOY
int
al
[
2
];
//left analog1
...
...
@@ -80,6 +78,69 @@ extern int LEDA,LEDB,LEDC;
int
BOXDEC
=
32
+
2
;
int
STAT_BASEY
;
// savestate serialization
static
bool
serialize_forward
;
static
char
*
serialize_data
;
#define SERIALIZE_STEP \
if
(
serialize_forward
)
memcpy
(
serialize_data
,
x
,
sizeof
(
*
x
));
\
else
memcpy
(
x
,
serialize_data
,
sizeof
(
*
x
));
\
serialize_data
+=
sizeof
(
*
x
);
void
serialize_char
(
char
*
x
)
{
SERIALIZE_STEP
}
void
serialize_int
(
int
*
x
)
{
SERIALIZE_STEP
}
int
hatari_mapper_serialize_size
()
{
return
1023
;
}
static
bool
hatari_mapper_serialize_bidi
(
char
*
data
,
char
version
)
{
// ignoring version, there is only one version so far
serialize_data
=
data
;
serialize_int
(
&
NPAGE
);
serialize_int
(
&
KCOL
);
serialize_int
(
&
BKGCOLOR
);
serialize_int
(
&
MAXPAS
);
serialize_int
(
&
SHIFTON
);
serialize_int
(
&
MOUSEMODE
);
serialize_int
(
&
SHOWKEY
);
serialize_int
(
&
PAS
);
serialize_int
(
&
STATUTON
);
serialize_int
(
&
SND
);
serialize_int
(
&
pauseg
);
serialize_int
(
&
slowdown
);
serialize_int
(
&
fmousex
);
serialize_int
(
&
fmousey
);
serialize_int
(
&
gmx
);
serialize_int
(
&
gmy
);
if
((
int
)(
data
-
serialize_data
)
>
hatari_mapper_serialize_size
())
{
fprintf
(
stderr
,
"hatari_mapper_serialize_size()=%d insufficient! (Needs: %d)
\n
"
,
hatari_mapper_serialize_size
(),
(
int
)(
data
-
serialize_data
));
return
false
;
}
return
true
;
}
bool
hatari_mapper_serialize
(
char
*
data
,
char
version
)
{
serialize_forward
=
true
;
return
hatari_mapper_serialize_bidi
(
data
,
version
);
}
bool
hatari_mapper_unserialize
(
const
char
*
data
,
char
version
)
{
serialize_forward
=
false
;
int
pauseg_old
=
pauseg
;
bool
result
=
hatari_mapper_serialize_bidi
((
char
*
)
data
,
version
);
if
(
pauseg_old
)
pauseg
=
pauseg_old
;
// because of the co-thread implementation there's really no way to save-state out of the GUI, so: stay paused
return
result
;
}
// input state
static
retro_input_state_t
input_state_cb
;
static
retro_input_poll_t
input_poll_cb
;
...
...
@@ -124,37 +185,11 @@ long GetTicks(void)
}
#ifdef WIIU
#include <features/features_cpu.h>
retro_time_t
current_tus
=
0
,
last_tus
=
0
;
#endif
int
slowdown
=
0
;
//NO SURE FIND BETTER WAY TO COME BACK IN MAIN THREAD IN HATARI GUI
void
gui_poll_events
(
void
)
{
#ifdef WIIU
current_tus
=
cpu_features_get_time_usec
();
current_tus
/=
1000
;
if
(
current_tus
-
last_tus
>=
1000
/
50
)
{
slowdown
=
0
;
frame
++
;
last_tus
=
current_tus
;
co_switch
(
mainThread
);
}
#else
Ktime
=
GetTicks
();
if
(
Ktime
-
LastFPSTime
>=
1000
/
50
)
{
slowdown
=
0
;
frame
++
;
LastFPSTime
=
Ktime
;
co_switch
(
mainThread
);
}
#endif
slowdown
=
0
;
co_switch
(
mainThread
);
}
//save bkg for screenshot
...
...
libretro/libretro-common/include/features/features_cpu.h
deleted
100644 → 0
View file @
f605173e
/* Copyright (C) 2010-2020 The RetroArch team
*
* ---------------------------------------------------------------------------------------
* The following license statement only applies to this file (features_cpu.h).
* ---------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _LIBRETRO_SDK_CPU_INFO_H
#define _LIBRETRO_SDK_CPU_INFO_H
#include <retro_common_api.h>
#include <stdint.h>
#include <libretro.h>
RETRO_BEGIN_DECLS
/**
* cpu_features_get_perf_counter:
*
* Gets performance counter.
*
* Returns: performance counter.
**/
retro_perf_tick_t
cpu_features_get_perf_counter
(
void
);
/**
* cpu_features_get_time_usec:
*
* Gets time in microseconds, from an undefined epoch.
* The epoch may change between computers or across reboots.
*
* Returns: time in microseconds
**/
retro_time_t
cpu_features_get_time_usec
(
void
);
/**
* cpu_features_get:
*
* Gets CPU features.
*
* Returns: bitmask of all CPU features available.
**/
uint64_t
cpu_features_get
(
void
);
/**
* cpu_features_get_core_amount:
*
* Gets the amount of available CPU cores.
*
* Returns: amount of CPU cores available.
**/
unsigned
cpu_features_get_core_amount
(
void
);
void
cpu_features_get_model_name
(
char
*
name
,
int
len
);
RETRO_END_DECLS
#endif
libretro/libretro.c
View file @
f19bc118
...
...
@@ -60,10 +60,10 @@ unsigned int video_config = 0;
int
CHANGE_RATE
=
0
,
CHANGEAV_TIMING
=
0
;
float
FRAMERATE
=
50
.
0
,
SAMPLERATE
=
44100
.
0
;
extern
bool
UseNonPolarizedLowPassFilter
;
bool
hatari_fastfdc
=
true
;
bool
hatari_borders
=
true
;
char
hatari_frameskips
[
2
];
int
firstpass
=
1
;
char
savestate_fname
[
RETRO_PATH_MAX
];
static
struct
retro_input_descriptor
input_descriptors
[]
=
{
...
...
@@ -115,6 +115,18 @@ void retro_set_environment(retro_environment_t cb)
},
"true"
},
// Audio
{
"hatari_polarized_filter"
,
"Polarized audio filter"
,
"Uses hatari's polarized lowpass filters on audio to simulate distortion"
,
{
{
"false"
,
"disabled"
},
{
"true"
,
"enabled"
},
{
NULL
,
NULL
},
},
"false"
},
// Video
{
"hatari_video_hires"
,
...
...
@@ -212,6 +224,16 @@ static void update_variables(void)
ConfigureParams
.
DiskImage
.
FastFloppy
=
hatari_fastfdc
;
}
// Audio
var
.
key
=
"hatari_polarized_filter"
;
var
.
value
=
NULL
;
UseNonPolarizedLowPassFilter
=
true
;
if
(
environ_cb
(
RETRO_ENVIRONMENT_GET_VARIABLE
,
&
var
)
&&
var
.
value
)
{
if
(
strcmp
(
var
.
value
,
"true"
)
==
0
)
UseNonPolarizedLowPassFilter
=
false
;
}
// Video
var
.
key
=
"hatari_video_hires"
;
var
.
value
=
NULL
;
...
...
@@ -661,9 +683,6 @@ void retro_run(void)
if
(
MidiRetroInterface
&&
MidiRetroInterface
->
output_enabled
())
MidiRetroInterface
->
flush
();
if
(
firstpass
)
firstpass
=
0
;
}
#define M3U_FILE_EXT "m3u"
...
...
@@ -740,64 +759,48 @@ bool retro_load_game_special(unsigned type, const struct retro_game_info *info,
return
false
;
}
const
char
RETRO_SAVE_VERSION
=
1
;
char
*
retro_save_buffer
=
NULL
;
int
retro_save_pos
=
0
;
int
retro_save_size
=
0
;
int
retro_save_head
=
1
;
// bytes reserved for libretro header/state
int
retro_save_max
=
0
;
int
retro_save_error
=
0
;
extern
int
hatari_mapper_serialize_size
();
extern
bool
hatari_mapper_serialize
(
char
*
data
,
char
version
);
extern
bool
hatari_mapper_unserialize
(
const
char
*
data
,
char
version
);
size_t
retro_serialize_size
(
void
)
{
if
(
firstpass
!=
1
)
{
snprintf
(
savestate_fname
,
sizeof
(
savestate_fname
),
"%s%shatari_tempsave.uss"
,
retro_save_directory
,
RETRO_PATH_SEPARATOR
);
MemorySnapShot_Capture
(
savestate_fname
,
false
);
FILE
*
file
=
fopen
(
savestate_fname
,
"rb"
);
if
(
file
)
{
size_t
size
=
0
;
fseek
(
file
,
0L
,
SEEK_END
);
size
=
ftell
(
file
);
fclose
(
file
);
return
size
;
}
}
return
0
;
return
10
*
1024
*
1024
;
// Hatari uncompressed savestates seem to be about 6MB
}
bool
retro_serialize
(
void
*
data_
,
size_t
size
)
{
if
(
firstpass
!=
1
)
{
snprintf
(
savestate_fname
,
sizeof
(
savestate_fname
),
"%s%shatari_tempsave.uss"
,
retro_save_directory
,
RETRO_PATH_SEPARATOR
);
MemorySnapShot_Capture
(
savestate_fname
,
false
);
FILE
*
file
=
fopen
(
savestate_fname
,
"rb"
);
if
(
file
)
{
if
(
fread
(
data_
,
size
,
1
,
file
)
==
1
)
{
fclose
(
file
);
return
true
;
}
fclose
(
file
);
}
}
return
false
;
retro_save_max
=
size
;
retro_save_head
=
hatari_mapper_serialize_size
()
+
1
;
if
(
size
<
retro_save_head
)
return
false
;
retro_save_buffer
=
data_
;
memset
(
retro_save_buffer
,
0
,
size
);
retro_save_buffer
[
0
]
=
RETRO_SAVE_VERSION
;
retro_save_error
=
hatari_mapper_serialize
(
data_
+
1
,
retro_save_buffer
[
0
])
?
0
:
1
;
retro_save_size
=
retro_save_head
;
MemorySnapShot_Capture
(
""
,
false
);
return
retro_save_error
==
0
;
}
bool
retro_unserialize
(
const
void
*
data_
,
size_t
size
)
{
if
(
firstpass
!=
1
)
{
snprintf
(
savestate_fname
,
sizeof
(
savestate_fname
),
"%s%shatari_tempsave.uss"
,
retro_save_directory
,
RETRO_PATH_SEPARATOR
);
FILE
*
file
=
fopen
(
savestate_fname
,
"wb"
);
if
(
file
)
{
if
(
fwrite
(
data_
,
size
,
1
,
file
)
==
1
)
{
fclose
(
file
);
MemorySnapShot_Restore
(
savestate_fname
,
false
);
return
true
;
}
else
fclose
(
file
);
}
}
return
false
;
retro_save_max
=
size
;
retro_save_head
=
hatari_mapper_serialize_size
()
+
1
;
if
(
size
<
retro_save_head
)
return
false
;
retro_save_buffer
=
(
void
*
)
data_
;
// discarding const
if
(
retro_save_buffer
[
0
]
!=
RETRO_SAVE_VERSION
)
return
false
;
// unknown version
retro_save_error
=
hatari_mapper_unserialize
(
data_
+
1
,
retro_save_buffer
[
0
])
?
0
:
1
;
retro_save_size
=
size
;
MemorySnapShot_Restore
(
""
,
false
);
return
retro_save_error
==
0
;
}
void
*
retro_get_memory_data
(
unsigned
id
)
...
...
src/main.c
View file @
f19bc118
...
...
@@ -330,7 +330,9 @@ return;
// FrameDuration_micro = (Sint64) ( 1000000.0 / nScreenRefreshRate + 0.5 ); /* round to closest integer */
FrameDuration_micro
=
ClocksTimings_GetVBLDuration_micro
(
ConfigureParams
.
System
.
nMachineType
,
nScreenRefreshRate
);
FrameDuration_micro
*=
nVBLSlowdown
;
#ifndef __LIBRETRO__
CurrentTicks
=
Time_GetTicks
();
#endif
if
(
DestTicks
==
0
)
/* on first call, init DestTicks */
{
...
...
@@ -339,6 +341,12 @@ return;
DestTicks
+=
pulse_swallowing_count
;
/* audio.c - Audio_CallBack() */
#ifdef __LIBRETRO__
/* Libretro is responsible for synchronizing the timing, allowing it to drive fast-forward, etc. Every time this point
is reached, we must assume we're ready for exactly the next frame. */
CurrentTicks
=
DestTicks
;
#endif
nDelay
=
DestTicks
-
CurrentTicks
;
/* Do not wait if we are in fast forward mode or if we are totally out of sync */
...
...
src/memorySnapShot.c
View file @
f19bc118
...
...
@@ -58,9 +58,11 @@ const char MemorySnapShot_fileid[] = "Hatari memorySnapShot.c : " __DATE__ " " _
#define VERSION_STRING "1.8.1"
/* Version number of compatible memory snapshots - Always 6 bytes (inc' NULL) */
#define SNAPSHOT_MAGIC 0xDeadBeef
#ifndef __LIBRETRO__
/* snapshot sizes are not allowed to increase over time in libretro, so compression should not be used */
#if HAVE_LIBZ
#define COMPRESS_MEMORYSNAPSHOT
/* Compress snapshots to reduce disk space used */
#endif
#endif
#ifdef COMPRESS_MEMORYSNAPSHOT
...
...
@@ -69,6 +71,17 @@ const char MemorySnapShot_fileid[] = "Hatari memorySnapShot.c : " __DATE__ " " _
#include <zlib.h>
typedef
gzFile
MSS_File
;
#elif defined(__LIBRETRO__)
/* Libretro will write to a memory buffer rather than a file. */
typedef
void
*
MSS_File
;
extern
char
*
retro_save_buffer
;
/* allocated and managed by libretro */
extern
int
retro_save_pos
;
/* current read/write position */
extern
int
retro_save_size
;
/* highest used file position */
extern
int
retro_save_head
;
/* reserved space for libretro header */
extern
int
retro_save_max
;
/* maximum size of retro_save_buffer */
extern
int
retro_save_error
;
/* 0 if no error */
#else
typedef
FILE
*
MSS_File
;
...
...
@@ -88,6 +101,15 @@ static MSS_File MemorySnapShot_fopen(const char *pszFileName, const char *pszMod
{
#ifdef COMPRESS_MEMORYSNAPSHOT
return
gzopen
(
pszFileName
,
pszMode
);
#elif defined(__LIBRETRO__)
retro_save_pos
=
retro_save_head
;
if
(
retro_save_pos
>
retro_save_size
)
retro_save_size
=
retro_save_pos
;
if
(
retro_save_buffer
==
NULL
)
{
retro_save_error
=
1
;
return
NULL
;
}
return
(
void
*
)
-
1
;
#else
return
fopen
(
pszFileName
,
pszMode
);
#endif
...
...
@@ -102,6 +124,8 @@ static void MemorySnapShot_fclose(MSS_File fhndl)
{
#ifdef COMPRESS_MEMORYSNAPSHOT
gzclose
(
fhndl
);
#elif defined(__LIBRETRO__)
/* Nothing to do. */
#else
fclose
(
fhndl
);
#endif
...
...
@@ -116,6 +140,18 @@ static int MemorySnapShot_fread(MSS_File fhndl, char *buf, int len)
{
#ifdef COMPRESS_MEMORYSNAPSHOT
return
gzread
(
fhndl
,
buf
,
len
);
#elif defined(__LIBRETRO__)
if
(
retro_save_pos
+
len
<=
retro_save_size
)
{
memcpy
(
buf
,
retro_save_buffer
+
retro_save_pos
,
len
);
retro_save_pos
+=
len
;
return
len
;
}
else
{
retro_save_error
=
1
;
return
0
;
}
#else
return
fread
(
buf
,
1
,
len
,
fhndl
);
#endif
...
...
@@ -130,6 +166,19 @@ static int MemorySnapShot_fwrite(MSS_File fhndl, const char *buf, int len)
{
#ifdef COMPRESS_MEMORYSNAPSHOT
return
gzwrite
(
fhndl
,
buf
,
len
);
#elif defined(__LIBRETRO__)
if
(
retro_save_pos
+
len
<=
retro_save_max
)
{
memcpy
(
retro_save_buffer
+
retro_save_pos
,
buf
,
len
);
retro_save_pos
+=
len
;
if
(
retro_save_pos
>
retro_save_size
)
retro_save_size
=
retro_save_pos
;
return
len
;
}
else
{
retro_save_error
=
1
;
return
0
;
}
#else
return
fwrite
(
buf
,
1
,
len
,
fhndl
);
#endif
...
...
@@ -144,6 +193,9 @@ static int MemorySnapShot_fseek(MSS_File fhndl, int pos)
{
#ifdef COMPRESS_MEMORYSNAPSHOT
return
(
int
)
gzseek
(
fhndl
,
pos
,
SEEK_CUR
);
/* return -1 if error, new position >=0 if OK */
#elif defined(__LIBRETRO__)
retro_save_pos
=
retro_save_head
+
pos
;
return
0
;
#else
return
fseek
(
fhndl
,
pos
,
SEEK_CUR
);
/* return -1 if error, 0 if OK */
#endif
...
...
src/sound.c
View file @
f19bc118
...
...
@@ -221,6 +221,9 @@ Uint8 SoundRegs[ 14 ];
int
YmVolumeMixing
=
YM_TABLE_MIXING
;
bool
UseLowPassFilter
=
false
;
#ifdef __LIBRETRO__
bool
UseNonPolarizedLowPassFilter
=
true
;
#endif
bool
bEnvelopeFreqFlag
;
/* Cleared each frame for YM saving */
...
...
@@ -381,7 +384,18 @@ static ymsample PWMaliasFilter(ymsample x0)
return
y0
;
}
#ifdef __LIBRETRO__
// A more "normal" alternative to the lowpass filters above,
// which affects rising and falling waves the same way rather than unequally.
// Removes a lot of unpleasant distortion.
static
ymsample
NonPolarizedLowPassFilter
(
ymsample
x0
)
{
static
yms32
y0
=
0
,
x1
=
0
;
y0
=
(
3
*
(
x0
+
x1
)
+
(
y0
<<
1
))
>>
3
;
x1
=
x0
;
return
y0
;
}
#endif
/*--------------------------------------------------------------*/
/* Build the volume conversion table used to simulate the */
...
...
@@ -972,6 +986,11 @@ static ymsample YM2149_NextSample(void)
if
(
envPos
>=
(
3
*
32
)
<<
24
)
/* blocks 0, 1 and 2 were used (envPos 0 to 95) */
envPos
-=
(
2
*
32
)
<<
24
;
/* replay/loop blocks 1 and 2 (envPos 32 to 95) */
#ifdef __LIBRETRO__
if
(
UseNonPolarizedLowPassFilter
)
return
NonPolarizedLowPassFilter
(
sample
);
#endif
/* Apply low pass filter ? */
if
(
UseLowPassFilter
)
return
LowPassFilter
(
sample
);
...
...
@@ -1041,6 +1060,11 @@ static ymsample YM2149_NextSample(void)
if
(
envPos
>=
(
3
*
32
)
<<
24
)
/* blocks 0, 1 and 2 were used (envPos 0 to 95) */
envPos
-=
(
2
*
32
)
<<
24
;
/* replay/loop blocks 1 and 2 (envPos 32 to 95) */
#ifdef __LIBRETRO__
if
(
UseNonPolarizedLowPassFilter
)
return
NonPolarizedLowPassFilter
(
sample
);
#endif
/* Apply low pass filter ? */
if
(
UseLowPassFilter
)
return
LowPassFilter
(
sample
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment