Skip to content

Commit

Permalink
- Properly enforce command delay.
Browse files Browse the repository at this point in the history
  • Loading branch information
Extrems committed Sep 8, 2021
1 parent 027ca08 commit f144537
Show file tree
Hide file tree
Showing 12 changed files with 111 additions and 118 deletions.
16 changes: 8 additions & 8 deletions cube/patches/Makefile
Expand Up @@ -46,10 +46,10 @@ stub.bin:
sd.bin:
@echo Building SD Patch ...
@$(CC) -Os $(OPTS) -c base/base.S
@$(CC) -Os $(OPTS) -c base/emulator.c -DDVD_MATH -DISR
@$(CC) -Os $(OPTS) -c base/emulator.c -DISR
@$(CC) -Os $(OPTS) -c base/emulator_dvd.c -DREAD_SPEED_TIER=2
@$(CC) -Os $(OPTS) -c base/igr.c
@$(CC) -Os $(OPTS) -c base/blockdevice.c -DASYNC_READ
@$(CC) -Os $(OPTS) -c base/blockdevice.c -DASYNC_READ -DDVD_MATH
@$(CC) -Os $(OPTS) -c sdgecko/sd.c -DISR_READ=1
@$(CC) -Os $(OPTS) -c sdgecko/sd_isr.S
@$(CC) -Os $(OPTS) -c base/frag.c
Expand Down Expand Up @@ -107,10 +107,10 @@ sd.dtk.bin:
ideexi-v1.bin:
@echo Building IDE-EXI-v1 Patch ...
@$(CC) -Os $(OPTS) -c base/base.S
@$(CC) -Os $(OPTS) -c base/emulator.c -DDVD_MATH -DISR
@$(CC) -Os $(OPTS) -c base/emulator.c -DISR
@$(CC) -Os $(OPTS) -c base/emulator_dvd.c -DREAD_SPEED_TIER=2
@$(CC) -Os $(OPTS) -c base/igr.c
@$(CC) -Os $(OPTS) -c base/blockdevice.c -DASYNC_READ
@$(CC) -Os $(OPTS) -c base/blockdevice.c -DASYNC_READ -DDVD_MATH
@$(CC) -Os $(OPTS) -c ide-exi/ata.c -DDMA_READ=0 -DISR_READ=1
@$(CC) -Os $(OPTS) -c ide-exi/ata_isr.S
@$(CC) -Os $(OPTS) -c base/frag.c
Expand Down Expand Up @@ -168,10 +168,10 @@ ideexi-v1.dtk.bin:
ideexi-v2.bin:
@echo Building IDE-EXI-v2 Patch ...
@$(CC) -Os $(OPTS) -c base/base.S
@$(CC) -Os $(OPTS) -c base/emulator.c -DDVD_MATH -DISR
@$(CC) -Os $(OPTS) -c base/emulator.c -DISR
@$(CC) -Os $(OPTS) -c base/emulator_dvd.c -DREAD_SPEED_TIER=2
@$(CC) -Os $(OPTS) -c base/igr.c
@$(CC) -Os $(OPTS) -c base/blockdevice.c -DASYNC_READ
@$(CC) -Os $(OPTS) -c base/blockdevice.c -DASYNC_READ -DDVD_MATH
@$(CC) -Os $(OPTS) -c ide-exi/ata.c -DDMA_READ=1 -DISR_READ=1
@$(CC) -Os $(OPTS) -c ide-exi/ata_isr.S -DDMA
@$(CC) -Os $(OPTS) -c base/frag.c
Expand Down Expand Up @@ -356,10 +356,10 @@ fsp.bin:
gcloader.bin:
@echo Building GCLoader Patch ...
@$(CC) -Os $(OPTS) -c base/base.S
@$(CC) -Os $(OPTS) -c base/emulator.c -DDI_PASSTHROUGH -DDVD_MATH -DGCODE -DISR
@$(CC) -Os $(OPTS) -c base/emulator.c -DDI_PASSTHROUGH -DGCODE -DISR
@$(CC) -Os $(OPTS) -c base/emulator_dvd.c -DREAD_SPEED_TIER=1
@$(CC) -Os $(OPTS) -c base/igr.c
@$(CC) -Os $(OPTS) -c dvd/dvd.c -DASYNC_READ -DGCODE
@$(CC) -Os $(OPTS) -c dvd/dvd.c -DASYNC_READ -DDVD_MATH -DGCODE
@$(CC) -Os $(OPTS) -c sdgecko/sd.c -DISR_READ=1
@$(CC) -Os $(OPTS) -c sdgecko/sd_isr.S
@$(CC) -Os $(OPTS) -c base/frag.c -DDEVICE_PATCHES=1
Expand Down
16 changes: 14 additions & 2 deletions cube/patches/base/blockdevice.c
Expand Up @@ -49,7 +49,7 @@ void schedule_read(OSTick ticks)
dvd.offset += length;
dvd.read = !!dvd.length;

schedule_read(COMMAND_LATENCY_TICKS);
schedule_read(0);
}
#else
OSCancelAlarm(&read_alarm);
Expand All @@ -74,7 +74,19 @@ void perform_read(uint32_t address, uint32_t length, uint32_t offset)
dvd.offset = offset | *VAR_CURRENT_DISC << 31;
dvd.read = true;

schedule_read(COMMAND_LATENCY_TICKS);
#ifdef DVD_MATH
void alarm_handler(OSAlarm *alarm, OSContext *context)
{
schedule_read(0);
}

if (*VAR_EMU_READ_SPEED) {
dvd_schedule_read(offset, length, alarm_handler);
return;
}
#endif

schedule_read(0);
}

void trickle_read(void)
Expand Down
26 changes: 7 additions & 19 deletions cube/patches/base/emulator.c
Expand Up @@ -509,7 +509,7 @@ void di_close_cover(void)
di_update_interrupts();
}

OSAlarm di_alarm = {0};
OSAlarm di_alarm = {0}, cover_alarm = {0};

#ifndef DI_PASSTHROUGH
static void di_execute_command(void)
Expand Down Expand Up @@ -603,7 +603,7 @@ static void di_execute_command(void)
{
if (di.status == 0 && change_disc()) {
di_open_cover();
OSSetAlarm(&di_alarm, OSSecondsToTicks(1.5), (OSAlarmHandler)di_close_cover);
OSSetAlarm(&cover_alarm, OSSecondsToTicks(1.5), (OSAlarmHandler)di_close_cover);
}
break;
}
Expand Down Expand Up @@ -722,24 +722,11 @@ static void di_write(unsigned index, uint32_t value)
di.regs[index] = value & 0b111;

if (value & 0b001) {
#ifdef DVD_MATH
if (*VAR_EMU_READ_SPEED) {
switch (di.reg.cmdbuf0 >> 24) {
case 0xA8:
{
dvd_schedule_read(di.reg.cmdbuf1 << 2, di.reg.cmdbuf2, (OSAlarmHandler)di_execute_command);
return;
}
case 0xAB:
{
dvd_schedule_read(di.reg.cmdbuf1 << 2, 0, (OSAlarmHandler)di_execute_command);
return;
}
}
}
#endif

#ifndef DVD
OSSetAlarm(&di_alarm, COMMAND_LATENCY_TICKS, (OSAlarmHandler)di_execute_command);
#else
di_execute_command();
#endif
}
break;
}
Expand Down Expand Up @@ -1071,6 +1058,7 @@ void init(void **arenaLo, void **arenaHi)
OSCreateAlarm(&bba_alarm);
#endif
OSCreateAlarm(&di_alarm);
OSCreateAlarm(&cover_alarm);
OSCreateAlarm(&read_alarm);

memzero(irq.handler, sizeof(irq.handler));
Expand Down
1 change: 1 addition & 0 deletions cube/patches/base/emulator.h
Expand Up @@ -28,6 +28,7 @@

extern OSAlarm bba_alarm;
extern OSAlarm di_alarm;
extern OSAlarm cover_alarm;
extern OSAlarm read_alarm;

typedef struct {
Expand Down
133 changes: 57 additions & 76 deletions cube/patches/base/emulator_dvd.c
Expand Up @@ -56,108 +56,89 @@ static uint32_t dvd_buffer_size(void)
return (*VAR_EMU_READ_SPEED == 1 ? id->streaming ? 5 : 15 : 32) * DVD_ECC_BLOCK_SIZE;
}

__attribute((noinline))
void dvd_schedule_read(uint32_t offset, uint32_t length, OSAlarmHandler handler)
{
void dvd_schedule_read(uint32_t offset, uint32_t length, OSAlarmHandler handler)
{
OSTime current_time = OSGetTime();
OSTime current_time = OSGetTime();

uint32_t head_position;
uint32_t head_position;

uint32_t buffer_start, buffer_end;
uint32_t buffer_size = dvd_buffer_size();
uint32_t buffer_start, buffer_end;
uint32_t buffer_size = dvd_buffer_size();

uint32_t dvd_offset = DVDRoundDown32KB(offset);
uint32_t dvd_offset = DVDRoundDown32KB(offset);

if (read_buffer.start_time == read_buffer.end_time) {
buffer_start = buffer_end = head_position = 0;
if (read_buffer.start_time == read_buffer.end_time) {
buffer_start = buffer_end = head_position = 0;
} else {
if (current_time >= read_buffer.end_time) {
head_position = read_buffer.end_offset;
} else {
if (current_time >= read_buffer.end_time) {
head_position = read_buffer.end_offset;
} else {
head_position = read_buffer.start_offset +
OSDiffTick(current_time, read_buffer.start_time) *
(read_buffer.end_block - read_buffer.start_block) /
OSDiffTick(read_buffer.end_time, read_buffer.start_time) *
DVD_ECC_BLOCK_SIZE;
}
head_position = read_buffer.start_offset +
OSDiffTick(current_time, read_buffer.start_time) *
(read_buffer.end_block - read_buffer.start_block) /
OSDiffTick(read_buffer.end_time, read_buffer.start_time) *
DVD_ECC_BLOCK_SIZE;
}

buffer_start = read_buffer.end_offset >= buffer_size ? read_buffer.end_offset - buffer_size : 0;
buffer_start = read_buffer.end_offset >= buffer_size ? read_buffer.end_offset - buffer_size : 0;

if (dvd_offset < buffer_start)
buffer_start = buffer_end = 0;
else buffer_end = head_position;
}
if (dvd_offset < buffer_start)
buffer_start = buffer_end = 0;
else buffer_end = head_position;
}

OSTick ticks_until_execution = 0;
OSTick ticks_until_completion = COMMAND_LATENCY_TICKS;
OSTick ticks_until_execution = 0;
OSTick ticks_until_completion = COMMAND_LATENCY_TICKS;

do {
OSTick ticks = 0;
do {
OSTick ticks = 0;

uint32_t chunk_length = MIN(length, DVD_ECC_BLOCK_SIZE - offset % DVD_ECC_BLOCK_SIZE);
uint32_t chunk_length = MIN(length, DVD_ECC_BLOCK_SIZE - offset % DVD_ECC_BLOCK_SIZE);

if (dvd_offset >= buffer_start && dvd_offset < buffer_end) {
ticks += COMMAND_LATENCY_TICKS;
ticks += OSSecondsToTicks(chunk_length / BUFFER_TRANSFER_RATE);
} else {
if (dvd_offset != head_position) {
ticks += OSSecondsToTicks(CalculateSeekTime(head_position, dvd_offset));
ticks += OSSecondsToTicks(CalculateRotationalLatency(dvd_offset,
OSTicksToSeconds((double)(current_time + ticks_until_completion + ticks))));

#if READ_SPEED_TIER == 2
ticks_until_execution += ticks;
#endif
} else {
ticks += OSSecondsToTicks(CalculateRawDiscReadTime(dvd_offset, DVD_ECC_BLOCK_SIZE));
}

#if READ_SPEED_TIER == 1
if (dvd_offset >= buffer_start && dvd_offset < buffer_end) {
ticks += COMMAND_LATENCY_TICKS;
ticks += OSSecondsToTicks(chunk_length / BUFFER_TRANSFER_RATE);
} else {
if (dvd_offset != head_position) {
ticks += OSSecondsToTicks(CalculateSeekTime(head_position, dvd_offset));
ticks += OSSecondsToTicks(CalculateRotationalLatency(dvd_offset,
OSTicksToSeconds((double)(current_time + ticks_until_completion + ticks))));

#if READ_SPEED_TIER == 2
ticks_until_execution += ticks;
#endif
head_position = dvd_offset + DVD_ECC_BLOCK_SIZE;
} else {
ticks += OSSecondsToTicks(CalculateRawDiscReadTime(dvd_offset, DVD_ECC_BLOCK_SIZE));
}

#if READ_SPEED_TIER == 0
#if READ_SPEED_TIER == 1
ticks_until_execution += ticks;
#endif
ticks_until_completion += ticks;

offset += chunk_length;
length -= chunk_length;
dvd_offset += DVD_ECC_BLOCK_SIZE;
} while (length);

if (dvd_offset != buffer_start + DVD_ECC_BLOCK_SIZE || buffer_start == buffer_end) {
read_buffer.start_offset = dvd_offset >= buffer_end ? dvd_offset : buffer_end;
read_buffer.end_offset = dvd_offset + buffer_size - DVD_ECC_BLOCK_SIZE;

read_buffer.start_time = current_time + ticks_until_completion;
read_buffer.end_time = read_buffer.start_time +
(OSTick)OSSecondsToTicks(CalculateRawDiscReadTime(read_buffer.start_offset,
read_buffer.end_offset - read_buffer.start_offset));
head_position = dvd_offset + DVD_ECC_BLOCK_SIZE;
}

OSSetAlarm(&read_alarm, ticks_until_execution, handler);
}
#if READ_SPEED_TIER == 0
ticks_until_execution += ticks;
#endif
ticks_until_completion += ticks;

static struct {
typeof(offset) offset;
typeof(length) length;
typeof(handler) handler;
} args = {0};
offset += chunk_length;
length -= chunk_length;
dvd_offset += DVD_ECC_BLOCK_SIZE;
} while (length);

args.offset = offset;
args.length = length;
args.handler = handler;
if (dvd_offset != buffer_start + DVD_ECC_BLOCK_SIZE || buffer_start == buffer_end) {
read_buffer.start_offset = dvd_offset >= buffer_end ? dvd_offset : buffer_end;
read_buffer.end_offset = dvd_offset + buffer_size - DVD_ECC_BLOCK_SIZE;

void trampoline(OSAlarm *alarm, OSContext *context)
{
dvd_schedule_read(args.offset, args.length, args.handler);
read_buffer.start_time = current_time + ticks_until_completion;
read_buffer.end_time = read_buffer.start_time +
(OSTick)OSSecondsToTicks(CalculateRawDiscReadTime(read_buffer.start_offset,
read_buffer.end_offset - read_buffer.start_offset));
}

OSSetAlarm(&read_alarm, 0, trampoline);
OSSetAlarm(&read_alarm, ticks_until_execution, handler);
}

__attribute((always_inline))
Expand Down
5 changes: 2 additions & 3 deletions cube/patches/bba/bba.c
Expand Up @@ -35,8 +35,7 @@ static struct {
bool read, patch;
} dvd = {0};

OSAlarm bba_alarm = {0};
OSAlarm read_alarm = {0};
OSAlarm bba_alarm = {0}, read_alarm = {0};

void schedule_read(OSTick ticks, bool lock);
void retry_read(void);
Expand Down Expand Up @@ -312,7 +311,7 @@ void perform_read(uint32_t address, uint32_t length, uint32_t offset)
dvd.offset = offset | *VAR_CURRENT_DISC << 31;
dvd.read = true;

schedule_read(COMMAND_LATENCY_TICKS, true);
schedule_read(0, true);
}

void trickle_read(void)
Expand Down
2 changes: 1 addition & 1 deletion cube/patches/bba/tcpip.c
Expand Up @@ -291,7 +291,7 @@ static void udp_input(bba_page_t page, eth_header_t *eth, ipv4_header_t *ipv4, u
dvd.offset += data_size;
dvd.read = !!dvd.length;

schedule_read(COMMAND_LATENCY_TICKS, false);
schedule_read(0, false);
}

bba_receive_end(page, data + data_offset, size);
Expand Down
16 changes: 14 additions & 2 deletions cube/patches/dvd/dvd.c
Expand Up @@ -102,7 +102,7 @@ void schedule_read(OSTick ticks)
dvd.offset += length;
dvd.read = !!dvd.length;

schedule_read(COMMAND_LATENCY_TICKS);
schedule_read(0);
}
#else
OSCancelAlarm(&read_alarm);
Expand Down Expand Up @@ -133,7 +133,19 @@ void perform_read(uint32_t address, uint32_t length, uint32_t offset)
dvd.offset = offset;
dvd.read = true;

schedule_read(COMMAND_LATENCY_TICKS);
#ifdef DVD_MATH
void alarm_handler(OSAlarm *alarm, OSContext *context)
{
schedule_read(0);
}

if (*VAR_EMU_READ_SPEED) {
dvd_schedule_read(offset, length, alarm_handler);
return;
}
#endif

schedule_read(0);
}

void trickle_read(void)
Expand Down
4 changes: 2 additions & 2 deletions cube/patches/ide-exi/ata.c
Expand Up @@ -344,12 +344,12 @@ static void ata_read_queued(void)
else
ata.queue[0].length = 0;

OSSetAlarm(&read_alarm, COMMAND_LATENCY_TICKS, (OSAlarmHandler)ata_done_queued);
ata_done_queued();
return;
}

if (sector == ata.last_sector) {
OSSetAlarm(&read_alarm, COMMAND_LATENCY_TICKS, (OSAlarmHandler)ata_done_queued);
ata_done_queued();
return;
}

Expand Down
4 changes: 2 additions & 2 deletions cube/patches/sdgecko/sd.c
Expand Up @@ -232,12 +232,12 @@ static void mmc_read_queued(void)
mmc.next_sector = sector + 1;
mmc.write = write;

OSSetAlarm(&read_alarm, COMMAND_LATENCY_TICKS, (OSAlarmHandler)mmc_done_queued);
mmc_done_queued();
return;
}

if (sector == mmc.last_sector) {
OSSetAlarm(&read_alarm, COMMAND_LATENCY_TICKS, (OSAlarmHandler)mmc_done_queued);
mmc_done_queued();
return;
}

Expand Down

0 comments on commit f144537

Please sign in to comment.