165 lines
3.4 KiB
C++
165 lines
3.4 KiB
C++
![]() |
#include "common.h"
|
||
|
|
||
|
#include "deps/chdr/chd.h"
|
||
|
|
||
|
struct CHDDisc : Disc
|
||
|
{
|
||
|
chd_file* chd;
|
||
|
u8* hunk_mem;
|
||
|
u32 old_hunk;
|
||
|
|
||
|
u32 hunkbytes;
|
||
|
u32 sph;
|
||
|
|
||
|
CHDDisc()
|
||
|
{
|
||
|
chd=0;
|
||
|
hunk_mem=0;
|
||
|
}
|
||
|
|
||
|
bool TryOpen(wchar* file);
|
||
|
|
||
|
~CHDDisc()
|
||
|
{
|
||
|
if (hunk_mem)
|
||
|
delete [] hunk_mem;
|
||
|
if (chd)
|
||
|
chd_close(chd);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct CHDTrack : TrackFile
|
||
|
{
|
||
|
CHDDisc* disc;
|
||
|
u32 StartFAD;
|
||
|
u32 StartHunk;
|
||
|
u32 fmt;
|
||
|
|
||
|
CHDTrack(CHDDisc* disc, u32 StartFAD,u32 StartHunk, u32 fmt)
|
||
|
{
|
||
|
this->disc=disc;
|
||
|
this->StartFAD=StartFAD;
|
||
|
this->StartHunk=StartHunk;
|
||
|
this->fmt=fmt;
|
||
|
}
|
||
|
|
||
|
virtual void Read(u32 FAD,u8* dst,SectorFormat* sector_type,u8* subcode,SubcodeFormat* subcode_type)
|
||
|
{
|
||
|
u32 fad_offs=FAD-StartFAD;
|
||
|
u32 hunk=(fad_offs)/disc->sph + StartHunk;
|
||
|
if (disc->old_hunk!=hunk)
|
||
|
{
|
||
|
chd_read(disc->chd,hunk,disc->hunk_mem); //CHDERR_NONE
|
||
|
}
|
||
|
|
||
|
u32 hunk_ofs=fad_offs%disc->sph;
|
||
|
|
||
|
memcpy(dst,disc->hunk_mem+hunk_ofs*(2352+96),fmt);
|
||
|
|
||
|
*sector_type=fmt==2352?SECFMT_2352:SECFMT_2048_MODE1;
|
||
|
|
||
|
//While space is reserved for it, the images contain no actual subcodes
|
||
|
//memcpy(subcode,disc->hunk_mem+hunk_ofs*(2352+96)+2352,96);
|
||
|
*subcode_type=SUBFMT_NONE;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
bool CHDDisc::TryOpen(wchar* file)
|
||
|
{
|
||
|
chd_error err=chd_open(file,CHD_OPEN_READ,0,&chd);
|
||
|
|
||
|
if (err!=CHDERR_NONE)
|
||
|
return false;
|
||
|
|
||
|
printf("chd: parsing file %s\n",file);
|
||
|
|
||
|
const chd_header* head = chd_get_header(chd);
|
||
|
|
||
|
hunkbytes = head->hunkbytes;
|
||
|
hunk_mem = new u8[hunkbytes];
|
||
|
old_hunk=0xFFFFFFF;
|
||
|
|
||
|
sph = hunkbytes/(2352+96);
|
||
|
|
||
|
if (hunkbytes%(2352+96)!=0)
|
||
|
{
|
||
|
printf("chd: hunkbytes is invalid, %d\n",hunkbytes);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
u32 tag;
|
||
|
u8 flags;
|
||
|
char temp[512];
|
||
|
u32 temp_len;
|
||
|
u32 total_frames=150;
|
||
|
|
||
|
u32 total_secs=0;
|
||
|
u32 total_hunks=0;
|
||
|
|
||
|
for(;;)
|
||
|
{
|
||
|
char type[64],subtype[32]="NONE",pgtype[32],pgsub[32];
|
||
|
int tkid,frames,pregap=0,postgap=0;
|
||
|
err=chd_get_metadata(chd,CDROM_TRACK_METADATA2_TAG,tracks.size(),temp,sizeof(temp),&temp_len,&tag,&flags);
|
||
|
if (err==CHDERR_NONE)
|
||
|
{
|
||
|
//"TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d PREGAP:%d PGTYPE:%s PGSUB:%s POSTGAP:%d"
|
||
|
sscanf(temp,CDROM_TRACK_METADATA2_FORMAT,&tkid,type,subtype,&frames,&pregap,pgtype,pgsub,&postgap);
|
||
|
}
|
||
|
else if (CHDERR_NONE== (err=chd_get_metadata(chd,CDROM_TRACK_METADATA_TAG,tracks.size(),temp,sizeof(temp),&temp_len,&tag,&flags)) )
|
||
|
{
|
||
|
//CDROM_TRACK_METADATA_FORMAT "TRACK:%d TYPE:%s SUBTYPE:%s FRAMES:%d"
|
||
|
sscanf(temp,CDROM_TRACK_METADATA_FORMAT,&tkid,type,subtype,&frames);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("chd: Unable to find metadata, %d\n",err);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (tkid!=(tracks.size()+1) || (strcmp(type,"MODE1_RAW")!=0 && strcmp(type,"AUDIO")!=0 && strcmp(type,"MODE1")!=0) || strcmp(subtype,"NONE")!=0 || pregap!=0 || postgap!=0)
|
||
|
{
|
||
|
printf("chd: track type %s is not supported\n",type);
|
||
|
return false;
|
||
|
}
|
||
|
printf("%s\n",temp);
|
||
|
Track t;
|
||
|
t.StartFAD=total_frames;
|
||
|
total_frames+=frames;
|
||
|
t.EndFAD=total_frames-1;
|
||
|
t.ADDR=0;
|
||
|
t.CTRL=strcmp(type,"AUDIO")==0?0:4;
|
||
|
t.file = new CHDTrack(this,t.StartFAD,total_hunks,strcmp(type,"MODE1")?2352:2048);
|
||
|
|
||
|
total_hunks+=frames/sph;
|
||
|
if (frames%sph)
|
||
|
total_hunks++;
|
||
|
|
||
|
tracks.push_back(t);
|
||
|
}
|
||
|
|
||
|
if (total_frames!=549300 || tracks.size()<3)
|
||
|
{
|
||
|
printf("WARNING: chd: Total frames is wrong: %d frames in %d tracks\n",total_frames,tracks.size());
|
||
|
msgboxf("This is an improper dump!",MBX_ICONEXCLAMATION);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
FillGDSession();
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
Disc* chd_parse(wchar* file)
|
||
|
{
|
||
|
CHDDisc* rv = new CHDDisc();
|
||
|
|
||
|
if (rv->TryOpen(file))
|
||
|
return rv;
|
||
|
else
|
||
|
{
|
||
|
delete rv;
|
||
|
return 0;
|
||
|
}
|
||
|
}
|