Skip to content

Commit 1d3584a

Browse files
authored
iso9660: Fix streaming DMA alignment and data corruption. (KallistiOS#1173)
- Fixed DMA Crash: Replaced `malloc` with `aligned_alloc` in `iso_open` to ensure the file handle's internal DMA buffer is always 32-byte aligned, preventing "Unaligned memory" errors. - Fixed Data Corruption: Corrected the logic in `iso_read` to properly handle leftover data in the stream buffer between reads. This prevents data from being skipped when a small read is followed by a larger one.
1 parent e36c939 commit 1d3584a

1 file changed

Lines changed: 31 additions & 15 deletions

File tree

kernel/arch/dreamcast/fs/fs_iso9660.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,7 @@ static inline void iso_abort_stream(bool lock) {
616616
mutex_lock(&fh_mutex);
617617

618618
cdrom_stream_stop(false);
619+
stream_fd->stream_part = 0;
619620
stream_fd = NULL;
620621

621622
if(lock)
@@ -652,7 +653,7 @@ static void * iso_open(vfs_handler_t * vfs, const char *fn, int mode) {
652653
return 0;
653654
}
654655

655-
fd = malloc(sizeof(*fd));
656+
fd = aligned_alloc(32, sizeof(*fd));
656657
if(!fd) {
657658
errno = ENOMEM;
658659
return 0;
@@ -694,7 +695,8 @@ static int iso_close(void * h) {
694695

695696
/* Read from a file */
696697
static ssize_t iso_read(void * h, void *buf, size_t bytes) {
697-
int rv, toread, thissect, c;
698+
int rv, c;
699+
size_t toread, thissect;
698700
uint8 * outbuf;
699701
size_t remain_size = 0, req_size;
700702
uint32_t sector;
@@ -717,6 +719,23 @@ static ssize_t iso_read(void * h, void *buf, size_t bytes) {
717719

718720
if(toread == 0) break;
719721

722+
/* If we have partial data from a stream, use it */
723+
if(fd->stream_part > 0) {
724+
size_t avail = 32 - fd->stream_part;
725+
size_t given = (toread > avail) ? avail : toread;
726+
727+
memcpy(outbuf, &fd->stream_data[fd->stream_part], given);
728+
fd->stream_part = (fd->stream_part + given) & 31;
729+
730+
outbuf += given;
731+
fd->ptr += given;
732+
bytes -= given;
733+
rv += given;
734+
toread -= given;
735+
736+
if(toread == 0) continue;
737+
}
738+
720739
/* How much more can we read in the current sector? */
721740
thissect = 2048 - (fd->ptr % 2048);
722741
sector = fd->first_extent + (fd->ptr / 2048);
@@ -778,21 +797,18 @@ static ssize_t iso_read(void * h, void *buf, size_t bytes) {
778797

779798
toread = (toread > thissect) ? thissect : toread;
780799

781-
if(fd->stream_part > 0) {
782-
memcpy(outbuf, &fd->stream_data[fd->stream_part - 1], toread);
783-
fd->stream_part = 0;
800+
c = cdrom_stream_request(fd->stream_data, 32, 0);
801+
if(c) {
802+
goto read_error;
784803
}
785-
else {
786-
c = cdrom_stream_request(fd->stream_data, 32, 0);
787-
if(c) {
788-
goto read_error;
789-
}
790-
fd->stream_part = toread;
791-
while(cdrom_stream_progress(&remain_size) == 1) {
792-
thd_pass();
793-
}
794-
memcpy(outbuf, fd->stream_data, toread);
804+
805+
while(cdrom_stream_progress(&remain_size) == 1) {
806+
thd_pass();
795807
}
808+
809+
memcpy(outbuf, fd->stream_data, toread);
810+
fd->stream_part = toread & 31;
811+
796812
// dbglog(DBG_DEBUG, "Stream request: read=%d remain=%d part=%d out=%p fd=%p\n",
797813
// toread, remain_size, fd->stream_part, outbuf, fd);
798814

0 commit comments

Comments
 (0)