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
beetle-saturn-libretro
Commits
97e3f0b5
Commit
97e3f0b5
authored
Aug 14, 2016
by
Libretro-Admin
Browse files
Update
parent
69eef0ee
Changes
6
Hide whitespace changes
Inline
Side-by-side
mednafen/FileStream.cpp
View file @
97e3f0b5
...
...
@@ -85,14 +85,14 @@ void FileStream::seek(int64_t offset, int whence)
filestream_seek
(
fp
,
offset
,
whence
);
}
int64_t
FileStream
::
tell
(
void
)
u
int64_t
FileStream
::
tell
(
void
)
{
if
(
!
fp
)
return
-
1
;
return
filestream_tell
(
fp
);
}
int64_t
FileStream
::
size
(
void
)
u
int64_t
FileStream
::
size
(
void
)
{
if
(
!
original_path
)
return
-
1
;
...
...
@@ -100,6 +100,14 @@ int64_t FileStream::size(void)
return
path_get_size
(
original_path
);
}
void
FileStream
::
truncate
(
uint64_t
length
)
{
}
void
FileStream
::
flush
(
void
)
{
}
void
FileStream
::
close
(
void
)
{
if
(
!
fp
)
...
...
mednafen/FileStream.h
View file @
97e3f0b5
...
...
@@ -36,8 +36,10 @@ class FileStream : public Stream
virtual
uint64_t
read
(
void
*
data
,
uint64_t
count
,
bool
error_on_eos
=
true
);
virtual
void
write
(
const
void
*
data
,
uint64_t
count
);
virtual
void
seek
(
int64_t
offset
,
int
whence
);
virtual
int64_t
tell
(
void
);
virtual
int64_t
size
(
void
);
virtual
void
truncate
(
uint64_t
length
);
virtual
void
flush
(
void
);
virtual
uint64_t
tell
(
void
);
virtual
uint64_t
size
(
void
);
virtual
void
close
(
void
);
private:
...
...
mednafen/MemoryStream.cpp
View file @
97e3f0b5
...
...
@@ -174,12 +174,12 @@ void MemoryStream::seek(int64 offset, int whence)
position
=
new_position
;
}
int64
MemoryStream
::
tell
(
void
)
u
int64
_t
MemoryStream
::
tell
(
void
)
{
return
position
;
}
int64
MemoryStream
::
size
(
void
)
u
int64
_t
MemoryStream
::
size
(
void
)
{
return
data_buffer_size
;
}
...
...
@@ -189,6 +189,9 @@ void MemoryStream::close(void)
}
void
MemoryStream
::
truncate
(
uint64_t
length
)
{
}
int
MemoryStream
::
get_line
(
std
::
string
&
str
)
{
...
...
@@ -207,3 +210,6 @@ int MemoryStream::get_line(std::string &str)
return
(
-
1
);
}
void
MemoryStream
::
flush
(
void
)
{
}
mednafen/MemoryStream.h
View file @
97e3f0b5
...
...
@@ -45,8 +45,10 @@ class MemoryStream : public Stream
virtual
uint64
read
(
void
*
data
,
uint64
count
,
bool
error_on_eos
=
true
);
virtual
void
write
(
const
void
*
data
,
uint64
count
);
virtual
void
seek
(
int64
offset
,
int
whence
);
virtual
int64
tell
(
void
);
virtual
int64
size
(
void
);
virtual
void
truncate
(
uint64_t
length
);
virtual
void
flush
(
void
);
virtual
uint64_t
tell
(
void
);
virtual
uint64_t
size
(
void
);
virtual
void
close
(
void
);
virtual
int
get_line
(
std
::
string
&
str
);
...
...
mednafen/Stream.h
View file @
97e3f0b5
...
...
@@ -33,9 +33,12 @@ class Stream
virtual
uint64_t
read
(
void
*
data
,
uint64_t
count
,
bool
error_on_eos
=
true
)
=
0
;
virtual
void
write
(
const
void
*
data
,
uint64_t
count
)
=
0
;
virtual
void
truncate
(
uint64_t
length
)
=
0
;
// Should have ftruncate()-like semantics; but avoid using it to extend files.
virtual
void
seek
(
int64_t
offset
,
int
whence
)
=
0
;
virtual
int64_t
tell
(
void
)
=
0
;
virtual
int64_t
size
(
void
)
=
0
;
virtual
uint64_t
tell
(
void
)
=
0
;
virtual
uint64_t
size
(
void
)
=
0
;
virtual
void
flush
(
void
)
=
0
;
virtual
void
close
(
void
)
=
0
;
// Flushes(in the case of writeable streams) and closes the stream.
// Necessary since this operation can fail(running out of disk space, for instance),
// and throw an exception in the destructor would be a Bad Idea(TM).
...
...
mednafen/cdrom/cdromif.cpp
View file @
97e3f0b5
...
...
@@ -25,6 +25,7 @@
#include <algorithm>
#include <boolean.h>
#include <rthreads/rthreads.h>
#include <retro_miscellaneous.h>
enum
...
...
@@ -57,6 +58,24 @@ class CDIF_Message
std
::
string
str_message
;
};
class
CDIF_Queue
{
public:
CDIF_Queue
();
~
CDIF_Queue
();
bool
Read
(
CDIF_Message
*
message
,
bool
blocking
=
true
);
void
Write
(
const
CDIF_Message
&
message
);
private:
std
::
queue
<
CDIF_Message
>
ze_queue
;
slock_t
*
ze_mutex
;
scond_t
*
ze_cond
;
};
typedef
struct
{
bool
valid
;
...
...
@@ -65,6 +84,50 @@ typedef struct
uint8_t
data
[
2352
+
96
];
}
CDIF_Sector_Buffer
;
// TODO: prohibit copy constructor
class
CDIF_MT
:
public
CDIF
{
public:
CDIF_MT
(
CDAccess
*
cda
);
virtual
~
CDIF_MT
();
virtual
void
HintReadSector
(
int32_t
lba
);
virtual
bool
ReadRawSector
(
uint8_t
*
buf
,
int32_t
lba
);
virtual
bool
ReadRawSectorPWOnly
(
uint8_t
*
pwbuf
,
int32_t
lba
,
bool
hint_fullread
);
// FIXME: Semi-private:
int
ReadThreadStart
(
void
);
private:
CDAccess
*
disc_cdaccess
;
sthread_t
*
CDReadThread
;
// Queue for messages to the read thread.
CDIF_Queue
ReadThreadQueue
;
// Queue for messages to the emu thread.
CDIF_Queue
EmuThreadQueue
;
enum
{
SBSize
=
256
};
CDIF_Sector_Buffer
SectorBuffers
[
SBSize
];
uint32_t
SBWritePos
;
slock_t
*
SBMutex
;
scond_t
*
SBCond
;
/* Read-thread-only: */
int32_t
ra_lba
;
int32_t
ra_count
;
int32_t
last_read_lba
;
};
// TODO: prohibit copy constructor
class
CDIF_ST
:
public
CDIF
{
...
...
@@ -119,6 +182,215 @@ CDIF_Message::~CDIF_Message()
}
CDIF_Queue
::
CDIF_Queue
()
{
ze_mutex
=
slock_new
();
ze_cond
=
scond_new
();
}
CDIF_Queue
::~
CDIF_Queue
()
{
slock_free
(
ze_mutex
);
scond_free
(
ze_cond
);
}
/* Returns false if message not read, true if it was read. Will always return true if "blocking" is set.
* Will throw MDFN_Error if the read message code is CDIF_MSG_FATAL_ERROR */
bool
CDIF_Queue
::
Read
(
CDIF_Message
*
message
,
bool
blocking
)
{
bool
ret
=
false
;
slock_lock
(
ze_mutex
);
if
(
blocking
)
{
while
(
ze_queue
.
size
()
==
0
)
scond_wait
(
ze_cond
,
ze_mutex
);
}
if
(
ze_queue
.
size
()
!=
0
)
{
ret
=
true
;
*
message
=
ze_queue
.
front
();
ze_queue
.
pop
();
}
slock_unlock
(
ze_mutex
);
if
(
ret
)
{
if
(
message
->
message
!=
CDIF_MSG_FATAL_ERROR
)
return
true
;
log_cb
(
RETRO_LOG_ERROR
,
"%s"
,
message
->
str_message
.
c_str
());
}
return
false
;
}
void
CDIF_Queue
::
Write
(
const
CDIF_Message
&
message
)
{
slock_lock
(
ze_mutex
);
ze_queue
.
push
(
message
);
scond_signal
(
ze_cond
);
/* Signal while the mutex is held to prevent icky race conditions */
slock_unlock
(
ze_mutex
);
}
struct
RTS_Args
{
CDIF_MT
*
cdif_ptr
;
};
static
int
ReadThreadStart_C
(
void
*
v_arg
)
{
RTS_Args
*
args
=
(
RTS_Args
*
)
v_arg
;
return
args
->
cdif_ptr
->
ReadThreadStart
();
}
int
CDIF_MT
::
ReadThreadStart
()
{
bool
Running
=
true
;
SBWritePos
=
0
;
ra_lba
=
0
;
ra_count
=
0
;
last_read_lba
=
LBA_Read_Maximum
+
1
;
disc_cdaccess
->
Read_TOC
(
&
disc_toc
);
if
(
disc_toc
.
first_track
<
1
||
disc_toc
.
last_track
>
99
||
disc_toc
.
first_track
>
disc_toc
.
last_track
)
{
log_cb
(
RETRO_LOG_ERROR
,
"TOC first(%d)/last(%d) track numbers bad.
\n
"
,
disc_toc
.
first_track
,
disc_toc
.
last_track
);
}
SBWritePos
=
0
;
ra_lba
=
0
;
ra_count
=
0
;
last_read_lba
=
LBA_Read_Maximum
+
1
;
memset
(
SectorBuffers
,
0
,
SBSize
*
sizeof
(
CDIF_Sector_Buffer
));
EmuThreadQueue
.
Write
(
CDIF_Message
(
CDIF_MSG_DONE
));
while
(
Running
)
{
CDIF_Message
msg
;
// Only do a blocking-wait for a message if we don't have any sectors to read-ahead.
// MDFN_DispMessage("%d %d %d\n", last_read_lba, ra_lba, ra_count);
if
(
ReadThreadQueue
.
Read
(
&
msg
,
ra_count
?
false
:
true
))
{
switch
(
msg
.
message
)
{
case
CDIF_MSG_DIEDIEDIE
:
Running
=
false
;
break
;
case
CDIF_MSG_READ_SECTOR
:
{
static
const
int
max_ra
=
16
;
static
const
int
initial_ra
=
1
;
static
const
int
speedmult_ra
=
2
;
int32_t
new_lba
=
msg
.
args
[
0
];
assert
((
unsigned
int
)
max_ra
<
(
SBSize
/
4
));
if
(
new_lba
==
(
last_read_lba
+
1
))
{
int
how_far_ahead
=
ra_lba
-
new_lba
;
if
(
how_far_ahead
<=
max_ra
)
ra_count
=
std
::
min
(
speedmult_ra
,
1
+
max_ra
-
how_far_ahead
);
else
ra_count
++
;
}
else
if
(
new_lba
!=
last_read_lba
)
{
ra_lba
=
new_lba
;
ra_count
=
initial_ra
;
}
last_read_lba
=
new_lba
;
}
break
;
}
}
/* Don't read beyond what the disc (image) readers can handle sanely. */
if
(
ra_count
&&
ra_lba
==
LBA_Read_Maximum
)
{
ra_count
=
0
;
//printf("Ephemeral scarabs: %d!\n", ra_lba);
}
if
(
ra_count
)
{
uint8_t
tmpbuf
[
2352
+
96
];
bool
error_condition
=
false
;
disc_cdaccess
->
Read_Raw_Sector
(
tmpbuf
,
ra_lba
);
slock_lock
(
SBMutex
);
SectorBuffers
[
SBWritePos
].
lba
=
ra_lba
;
memcpy
(
SectorBuffers
[
SBWritePos
].
data
,
tmpbuf
,
2352
+
96
);
SectorBuffers
[
SBWritePos
].
valid
=
true
;
SectorBuffers
[
SBWritePos
].
error
=
error_condition
;
SBWritePos
=
(
SBWritePos
+
1
)
%
SBSize
;
scond_signal
(
SBCond
);
slock_unlock
(
SBMutex
);
ra_lba
++
;
ra_count
--
;
}
}
return
(
1
);
}
CDIF_MT
::
CDIF_MT
(
CDAccess
*
cda
)
:
disc_cdaccess
(
cda
),
CDReadThread
(
NULL
),
SBMutex
(
NULL
),
SBCond
(
NULL
)
{
CDIF_Message
msg
;
RTS_Args
s
;
SBMutex
=
slock_new
();
SBCond
=
scond_new
();
UnrecoverableError
=
false
;
s
.
cdif_ptr
=
this
;
CDReadThread
=
sthread_create
((
void
(
*
)(
void
*
))
ReadThreadStart_C
,
&
s
);
EmuThreadQueue
.
Read
(
&
msg
);
}
CDIF_MT
::~
CDIF_MT
()
{
bool
thread_deaded_failed
=
false
;
ReadThreadQueue
.
Write
(
CDIF_Message
(
CDIF_MSG_DIEDIEDIE
));
if
(
!
thread_deaded_failed
)
sthread_join
(
CDReadThread
);
if
(
SBMutex
)
{
slock_free
(
SBMutex
);
SBMutex
=
NULL
;
}
if
(
SBCond
)
{
scond_free
(
SBCond
);
SBCond
=
NULL
;
}
}
bool
CDIF
::
ValidateRawSector
(
uint8_t
*
buf
)
{
int
mode
=
buf
[
12
+
3
];
...
...
@@ -132,6 +404,92 @@ bool CDIF::ValidateRawSector(uint8_t *buf)
return
(
true
);
}
bool
CDIF_MT
::
ReadRawSector
(
uint8_t
*
buf
,
int32_t
lba
)
{
bool
found
=
false
;
bool
error_condition
=
false
;
if
(
UnrecoverableError
)
{
memset
(
buf
,
0
,
2352
+
96
);
return
(
false
);
}
if
(
lba
<
LBA_Read_Minimum
||
lba
>
LBA_Read_Maximum
)
{
printf
(
"Attempt to read sector out of bounds; LBA=%d
\n
"
,
lba
);
memset
(
buf
,
0
,
2352
+
96
);
return
(
false
);
}
//fprintf(stderr, "%d\n", ra_lba - lba);
ReadThreadQueue
.
Write
(
CDIF_Message
(
CDIF_MSG_READ_SECTOR
,
lba
));
slock_lock
(
SBMutex
);
do
{
for
(
int
i
=
0
;
i
<
SBSize
;
i
++
)
{
if
(
SectorBuffers
[
i
].
valid
&&
SectorBuffers
[
i
].
lba
==
lba
)
{
error_condition
=
SectorBuffers
[
i
].
error
;
memcpy
(
buf
,
SectorBuffers
[
i
].
data
,
2352
+
96
);
found
=
true
;
}
}
if
(
!
found
)
scond_wait
((
scond_t
*
)
SBCond
,
(
slock_t
*
)
SBMutex
);
}
while
(
!
found
);
slock_unlock
(
SBMutex
);
return
(
!
error_condition
);
}
bool
CDIF_MT
::
ReadRawSectorPWOnly
(
uint8_t
*
pwbuf
,
int32_t
lba
,
bool
hint_fullread
)
{
if
(
UnrecoverableError
)
{
memset
(
pwbuf
,
0
,
96
);
return
(
false
);
}
if
(
lba
<
LBA_Read_Minimum
||
lba
>
LBA_Read_Maximum
)
{
printf
(
"Attempt to read sector out of bounds; LBA=%d
\n
"
,
lba
);
memset
(
pwbuf
,
0
,
96
);
return
(
false
);
}
if
(
disc_cdaccess
->
Fast_Read_Raw_PW_TSRE
(
pwbuf
,
lba
))
{
if
(
hint_fullread
)
ReadThreadQueue
.
Write
(
CDIF_Message
(
CDIF_MSG_READ_SECTOR
,
lba
));
return
(
true
);
}
else
{
uint8_t
tmpbuf
[
2352
+
96
];
bool
ret
;
ret
=
ReadRawSector
(
tmpbuf
,
lba
);
memcpy
(
pwbuf
,
tmpbuf
+
2352
,
96
);
return
ret
;
}
}
void
CDIF_MT
::
HintReadSector
(
int32_t
lba
)
{
if
(
UnrecoverableError
)
return
;
ReadThreadQueue
.
Write
(
CDIF_Message
(
CDIF_MSG_READ_SECTOR
,
lba
));
}
int
CDIF
::
ReadSector
(
uint8_t
*
buf
,
int32_t
lba
,
uint32_t
sector_count
,
bool
suppress_uncorrectable_message
)
{
int
ret
=
0
;
...
...
@@ -146,7 +504,7 @@ int CDIF::ReadSector(uint8_t* buf, int32_t lba, uint32_t sector_count, bool supp
if
(
!
ReadRawSector
(
tmpbuf
,
lba
))
{
puts
(
"CDIF Raw Read error"
);
return
false
;
return
(
false
)
;
}
if
(
!
ValidateRawSector
(
tmpbuf
))
...
...
@@ -154,7 +512,7 @@ int CDIF::ReadSector(uint8_t* buf, int32_t lba, uint32_t sector_count, bool supp
if
(
!
suppress_uncorrectable_message
)
{
MDFN_DispMessage
(
"Uncorrectable data at sector %d"
,
lba
);
log_cb
(
RETRO_LOG_ERROR
,
"Uncorrectable data at sector %d
\n
"
,
lba
);
log_cb
(
RETRO_LOG_ERROR
,
"Uncorrectable data at sector %d"
,
lba
);
}
return
(
false
);
...
...
@@ -265,9 +623,146 @@ bool CDIF_ST::ReadRawSectorPWOnly(uint8_t* pwbuf, int32_t lba, bool hint_fullrea
}
}
class
CDIF_Stream_Thing
:
public
Stream
{
public:
CDIF_Stream_Thing
(
CDIF
*
cdintf_arg
,
uint32_t
lba_arg
,
uint32_t
sector_count_arg
);
~
CDIF_Stream_Thing
();
virtual
uint64_t
attributes
(
void
)
override
;
virtual
uint64_t
read
(
void
*
data
,
uint64_t
count
,
bool
error_on_eos
=
true
)
override
;
virtual
void
write
(
const
void
*
data
,
uint64_t
count
)
override
;
virtual
void
truncate
(
uint64_t
length
)
override
;
virtual
void
seek
(
int64_t
offset
,
int
whence
)
override
;
virtual
uint64_t
tell
(
void
)
override
;
virtual
uint64_t
size
(
void
)
override
;
virtual
void
flush
(
void
)
override
;
virtual
void
close
(
void
)
override
;
private:
CDIF
*
cdintf
;
const
uint32_t
start_lba
;
const
uint32_t
sector_count
;
int64_t
position
;
};
CDIF_Stream_Thing
::
CDIF_Stream_Thing
(
CDIF
*
cdintf_arg
,
uint32_t
start_lba_arg
,
uint32_t
sector_count_arg
)
:
cdintf
(
cdintf_arg
),
start_lba
(
start_lba_arg
),
sector_count
(
sector_count_arg
)
{
}
CDIF_Stream_Thing
::~
CDIF_Stream_Thing
()
{
}
uint64_t
CDIF_Stream_Thing
::
attributes
(
void
)
{
return
(
ATTRIBUTE_READABLE
|
ATTRIBUTE_SEEKABLE
);
}
uint64_t
CDIF_Stream_Thing
::
read
(
void
*
data
,
uint64_t
count
,
bool
error_on_eos
)
{
if
(
count
>
(((
uint64_t
)
sector_count
*
2048
)
-
position
))
{
if
(
error_on_eos
)
throw
MDFN_Error
(
0
,
"EOF"
);
count
=
((
uint64_t
)
sector_count
*
2048
)
-
position
;
}
if
(
!
count
)
return
(
0
);
for
(
uint64_t
rp
=
position
;
rp
<
(
position
+
count
);
rp
=
(
rp
&~
2047
)
+
2048
)
{
uint8_t
buf
[
2048
];
if
(
!
cdintf
->
ReadSector
(
buf
,
start_lba
+
(
rp
/
2048
),
1
))
throw
MDFN_Error
(
ErrnoHolder
(
EIO
));
memcpy
((
uint8_t
*
)
data
+
(
rp
-
position
),
buf
+
(
rp
&
2047
),
std
::
min
<
uint64_t
>
(
2048
-
(
rp
&
2047
),
count
-
(
rp
-
position
)));
}
position
+=
count
;
return
count
;
}
void
CDIF_Stream_Thing
::
write
(
const
void
*
data
,
uint64_t
count
)
{
throw
MDFN_Error
(
ErrnoHolder
(
EBADF
));
}
void
CDIF_Stream_Thing
::
truncate
(
uint64_t
length
)
{
throw
MDFN_Error
(
ErrnoHolder
(
EBADF
));
}
void
CDIF_Stream_Thing
::
seek
(
int64_t
offset
,
int
whence
)
{
int64_t
new_position
;
switch
(
whence
)
{
default:
throw
MDFN_Error
(
ErrnoHolder
(
EINVAL
));
break
;
case
SEEK_SET
:
new_position
=
offset
;
break
;
case
SEEK_CUR
:
new_position
=
position
+
offset
;
break
;
case
SEEK_END
:
new_position
=
((
int64_t
)
sector_count
*
2048
)
+
offset
;
break
;
}
if
(
new_position
<
0
||
new_position
>
((
int64_t
)
sector_count
*
2048
))
throw
MDFN_Error
(
ErrnoHolder
(
EINVAL
));
position
=
new_position
;
}