+void pm_sectorsize(int length, pm_file *stream)\r
+{\r
+ // CHD reading needs to know how much binary data is in one data sector(=unit)\r
+#if defined(USE_LIBCHDR)\r
+ if (stream->type == PMT_CHD) {\r
+ struct chd_struct *chd = stream->file;\r
+ chd->sectorsize = length;\r
+ if (chd->sectorsize > chd->unitbytes)\r
+ elprintf(EL_STATUS|EL_ANOMALY, "cd: sector size %d too large for unit %d", chd->sectorsize, chd->unitbytes);\r
+ }\r
+#endif\r
+}\r
+\r
+#if defined(USE_LIBCHDR)\r
+static size_t _pm_read_chd(void *ptr, size_t bytes, pm_file *stream, int is_audio)\r
+{\r
+ int ret = 0;\r
+\r
+ if (stream->type == PMT_CHD) {\r
+ struct chd_struct *chd = stream->file;\r
+ // calculate sector and offset in sector\r
+ int sectsz = is_audio ? CD_MAX_SECTOR_DATA : chd->sectorsize;\r
+ int sector = chd->fpos / sectsz;\r
+ int offset = chd->fpos - (sector * sectsz);\r
+ // calculate hunk and sector offset in hunk\r
+ int hunknum = sector / chd->hunkunits;\r
+ int hunksec = sector - (hunknum * chd->hunkunits);\r
+ int hunkofs = hunksec * chd->unitbytes;\r
+\r
+ while (bytes != 0) {\r
+ // data left in current sector\r
+ int len = sectsz - offset;\r
+\r
+ // update hunk cache if needed\r
+ if (hunknum != chd->hunknum) {\r
+ chd_read(chd->chd, hunknum, chd->hunk);\r
+ chd->hunknum = hunknum;\r
+ }\r
+ if (len > bytes)\r
+ len = bytes;\r
+\r
+#if CPU_IS_LE\r
+ if (is_audio) {\r
+ // convert big endian audio samples\r
+ u16 *dst = ptr, v;\r
+ u8 *src = chd->hunk + hunkofs + offset;\r
+ int i;\r
+\r
+ for (i = 0; i < len; i += 4) {\r
+ v = *src++ << 8; *dst++ = v | *src++;\r
+ v = *src++ << 8; *dst++ = v | *src++;\r
+ }\r
+ } else\r
+#endif\r
+ memcpy(ptr, chd->hunk + hunkofs + offset, len);\r
+\r
+ // house keeping\r
+ ret += len;\r
+ chd->fpos += len;\r
+ bytes -= len;\r
+\r
+ // no need to advance internals if there's no more data to read\r
+ if (bytes) {\r
+ ptr += len;\r
+ offset = 0;\r
+\r
+ sector ++;\r
+ hunksec ++;\r
+ hunkofs += chd->unitbytes;\r
+ if (hunksec >= chd->hunkunits) {\r
+ hunksec = 0;\r
+ hunkofs = 0;\r
+ hunknum ++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return ret;\r
+}\r
+#endif\r
+\r