2021-07-16 10:54:45 -04:00
|
|
|
#include "ChdImageStream.h"
|
2021-07-16 11:02:35 -04:00
|
|
|
#include <cstring>
|
|
|
|
#include <cassert>
|
|
|
|
#include <stdexcept>
|
2023-07-06 11:45:07 -04:00
|
|
|
#include "maybe_unused.h"
|
2023-01-06 13:47:25 -05:00
|
|
|
#include <libchdr/chd.h>
|
2021-07-21 09:35:11 -04:00
|
|
|
#include "ChdStreamSupport.h"
|
2021-07-16 10:54:45 -04:00
|
|
|
|
2022-12-31 12:19:04 -05:00
|
|
|
//Should probably take a shared_ptr instead of raw
|
|
|
|
CChdImageStream::CChdImageStream(std::unique_ptr<Framework::CStream> baseStream)
|
|
|
|
: m_baseStream(std::move(baseStream))
|
2021-07-16 10:54:45 -04:00
|
|
|
{
|
2022-12-31 12:19:04 -05:00
|
|
|
m_file = ChdStreamSupport::CreateFileFromStream(m_baseStream.get());
|
2022-09-28 09:31:49 -04:00
|
|
|
chd_error result = chd_open_core_file(m_file, CHD_OPEN_READ, nullptr, &m_chd);
|
2021-07-16 10:54:45 -04:00
|
|
|
if(result != CHDERR_NONE)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Failed to open CHD file.");
|
|
|
|
}
|
|
|
|
auto header = chd_get_header(m_chd);
|
2024-12-04 19:23:54 -05:00
|
|
|
m_unitCount = header->unitcount;
|
2022-12-31 11:57:40 -05:00
|
|
|
m_unitSize = header->unitbytes;
|
2021-07-16 10:54:45 -04:00
|
|
|
m_hunkSize = header->hunkbytes;
|
|
|
|
m_hunkBuffer.resize(m_hunkSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
CChdImageStream::~CChdImageStream()
|
|
|
|
{
|
|
|
|
chd_close(m_chd);
|
|
|
|
}
|
|
|
|
|
2022-12-31 11:57:40 -05:00
|
|
|
uint32 CChdImageStream::GetUnitSize() const
|
2022-04-29 10:03:58 -04:00
|
|
|
{
|
2022-12-31 11:57:40 -05:00
|
|
|
return m_unitSize;
|
2022-04-29 10:03:58 -04:00
|
|
|
}
|
|
|
|
|
2021-07-16 10:54:45 -04:00
|
|
|
void CChdImageStream::Seek(int64 position, Framework::STREAM_SEEK_DIRECTION origin)
|
|
|
|
{
|
|
|
|
switch(origin)
|
|
|
|
{
|
|
|
|
case Framework::STREAM_SEEK_CUR:
|
|
|
|
m_position += position;
|
|
|
|
break;
|
|
|
|
case Framework::STREAM_SEEK_SET:
|
|
|
|
m_position = position;
|
|
|
|
break;
|
|
|
|
case Framework::STREAM_SEEK_END:
|
|
|
|
m_position = GetTotalSize() + position;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 CChdImageStream::Tell()
|
|
|
|
{
|
|
|
|
return m_position;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CChdImageStream::IsEOF()
|
|
|
|
{
|
|
|
|
return m_position >= GetTotalSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 CChdImageStream::Read(void* buffer, uint64 size)
|
|
|
|
{
|
|
|
|
uint32 hunkPosition = m_position % m_hunkSize;
|
|
|
|
assert((hunkPosition + size) <= m_hunkSize);
|
|
|
|
uint32 hunkIdx = m_position / m_hunkSize;
|
|
|
|
if(hunkIdx != m_hunkBufferIdx)
|
|
|
|
{
|
2023-07-06 11:45:07 -04:00
|
|
|
FRAMEWORK_MAYBE_UNUSED chd_error error = chd_read(m_chd, hunkIdx, m_hunkBuffer.data());
|
2022-12-31 11:57:40 -05:00
|
|
|
assert(error == CHDERR_NONE);
|
2021-07-16 10:54:45 -04:00
|
|
|
m_hunkBufferIdx = hunkIdx;
|
|
|
|
}
|
|
|
|
memcpy(buffer, m_hunkBuffer.data() + hunkPosition, size);
|
|
|
|
m_position += size;
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 CChdImageStream::Write(const void* buffer, uint64 size)
|
|
|
|
{
|
|
|
|
throw std::runtime_error("Not supported.");
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64 CChdImageStream::GetTotalSize() const
|
|
|
|
{
|
2025-01-03 19:06:50 -05:00
|
|
|
return m_unitCount * static_cast<uint64>(m_unitSize);
|
2021-07-16 10:54:45 -04:00
|
|
|
}
|