CHD: Fix CD by detecting sector offset

Kind of annoying to do this here, but our current CD/DVD detection
requires us to know what the media is unless I misunderstand
This commit is contained in:
Ziemas 2020-12-29 13:23:01 +01:00
parent 8e4d8cc709
commit 1b7377330d
2 changed files with 65 additions and 22 deletions

View file

@ -1,6 +1,6 @@
#include "chd_reader.hpp"
#include <cstring>
#include <cassert>
#include <cstring>
bool CHD_Reader::open(std::string name)
{
@ -21,6 +21,8 @@ bool CHD_Reader::open(std::string name)
printf("chd: hunk size %d\n", m_header->hunkbytes);
printf("chd: unitbytes %d\n", m_header->unitbytes);
find_offset();
// read first hunk
err = chd_read(m_file, 0, m_buf.get());
if (err != CHDERR_NONE)
@ -32,14 +34,52 @@ bool CHD_Reader::open(std::string name)
return true;
}
void CHD_Reader::find_offset()
{
// TODO: If we want to eventually read multiple tracks they each have separate metadata.
char metadata_str[256];
uint32_t metadata_len;
chd_error err = chd_get_metadata(m_file, CDROM_TRACK_METADATA2_TAG, 0, metadata_str, sizeof(metadata_str), &metadata_len, nullptr, nullptr);
if (err != CHDERR_NONE)
{
fprintf(stderr, "chd: read_metadata: %s\n", chd_error_string(err));
}
char type_str[256];
char subtype_str[256];
char pgtype_str[256];
char pgsub_str[256];
int track_num = 0, frames = 0, pregap_frames = 0, postgap_frames = 0;
std::sscanf(metadata_str, CDROM_TRACK_METADATA2_FORMAT, &track_num, type_str, subtype_str, &frames,
&pregap_frames, pgtype_str, pgsub_str, &postgap_frames);
if (std::strncmp(type_str, "MODE2_FORM_MIX", 14) == 0)
m_sector_offset = 8;
else if (std::strncmp(type_str, "MODE2_FORM1", 10) == 0)
m_sector_offset = 0;
else if (std::strncmp(type_str, "MODE2_FORM2", 10) == 0)
m_sector_offset = 0;
else if (std::strncmp(type_str, "MODE2_RAW", 9) == 0)
m_sector_offset = 24;
else if (std::strncmp(type_str, "MODE1_RAW", 9) == 0)
m_sector_offset = 16;
else if (std::strncmp(type_str, "MODE1", 5) == 0)
m_sector_offset = 0;
else if (std::strncmp(type_str, "MODE2", 5) == 0)
m_sector_offset = 0; // IDK
else if (std::strncmp(type_str, "AUDIO", 5) == 0)
m_sector_offset = 0; // IDK
}
void CHD_Reader::close()
{
printf("chd: close");
chd_close(m_file);
delete(m_header);
delete (m_header);
}
size_t CHD_Reader::read(uint8_t *buff, size_t bytes)
size_t CHD_Reader::read(uint8_t* buff, size_t bytes)
{
assert(bytes);
assert(m_virtptr + bytes <= m_size);
@ -60,14 +100,13 @@ size_t CHD_Reader::read(uint8_t *buff, size_t bytes)
for (uint32_t i = (uint32_t)start_hunk; i <= end_hunk; i++)
{
//printf("chd: in the loop\n");
if (i != m_current_hunk)
{
printf("chd: grabbing new hunk %d\n", i);
chd_error err = chd_read(m_file, i, m_buf.get());
if (err != CHDERR_NONE)
{
printf("chd: read %s\n", chd_error_string(err));
fprintf(stderr, "chd: read %s\n", chd_error_string(err));
return total_read;
}
@ -88,9 +127,13 @@ size_t CHD_Reader::read(uint8_t *buff, size_t bytes)
assert(readlen <= bytes);
memcpy(buff, m_buf.get() + local_ofs, readlen);
memcpy(buff, m_buf.get() + local_ofs + m_sector_offset, readlen);
total_read += readlen;
//m_virtptr += readlen;
// Need to advance the full sector here to not get misaligned
// other cdvd containers behave inconsistently anyway regarding seek
// by read,
m_virtptr += m_header->unitbytes;
buff += readlen;
}
@ -102,21 +145,19 @@ size_t CHD_Reader::read(uint8_t *buff, size_t bytes)
void CHD_Reader::seek(size_t ofs, std::ios::seekdir whence)
{
printf("chd: seek to sector %zd, bytes %lu\n", ofs, ofs*m_header->unitbytes);
printf("chd: seek to sector %zd, bytes %lu\n", ofs, ofs * m_header->unitbytes);
ofs *= m_header->unitbytes;
if (whence == std::ios::beg)
{
if ((uint64_t)ofs < m_size)
m_virtptr = (uint64_t)ofs;
}
else
if (whence == std::ios::cur)
else if (whence == std::ios::cur)
{
if (m_virtptr + ofs < m_size)
m_virtptr = m_virtptr + ofs;
}
else
if (whence == std::ios::end)
else if (whence == std::ios::end)
{
if (m_size - ofs < m_size)
m_virtptr = m_size - ofs;
@ -125,7 +166,7 @@ void CHD_Reader::seek(size_t ofs, std::ios::seekdir whence)
bool CHD_Reader::is_open()
{
if(m_file)
if (m_file)
return true;
return false;

View file

@ -7,16 +7,6 @@
class CHD_Reader : public CDVD_Container
{
private:
chd_file *m_file {nullptr};
const chd_header *m_header {nullptr};
uint64_t m_virtptr {0};
size_t m_size {0};
uint32_t m_current_hunk {0};
std::unique_ptr<uint8_t[]> m_buf;
public:
bool open(std::string name);
void close();
@ -25,6 +15,18 @@ class CHD_Reader : public CDVD_Container
bool is_open();
size_t get_size();
private:
chd_file *m_file {nullptr};
const chd_header *m_header {nullptr};
uint32_t m_sector_offset {0};
uint64_t m_virtptr {0};
size_t m_size {0};
uint32_t m_current_hunk {0};
std::unique_ptr<uint8_t[]> m_buf;
void find_offset();
};