diff --git a/core/emulator.cpp b/core/emulator.cpp index 4b2db021c..66a034f6c 100644 --- a/core/emulator.cpp +++ b/core/emulator.cpp @@ -193,17 +193,8 @@ static void loadSpecialSettings() } if (prod_id == "T9512N" // The Grinch (US) || prod_id == "T9503D" // The Grinch (EU) - || prod_id == "T0000M" // Hell Gate FIXME - || prod_id == "MK-51012" // Metropolis Street Racer (US) - || prod_id == "MK-5102250" // Metropolis Street Racer (EU) - || prod_id == "T-31101N" // Psychic Force 2012 (US) - || prod_id == "T1101M" // Psychic Force 2012 (JP) - || prod_id == "T-8106D-50" // Psychic Force 2012 (EU) || prod_id == "T-9707N" // San Francisco Rush 2049 (US) || prod_id == "T-9709D-50" // San Francisco Rush 2049 (EU) - || prod_id == "MK-51146" // Sega Smashpack vol.1 (Sega Swirl) - || prod_id == "MK-51152" // World Series Baseball 2K2 - || prod_id == "T20401M" // Zero Gunner || prod_id == "12502D-50" // Caesar's palace 2000 (EU) || prod_id == "T7001D 50" // Jimmy White's 2 Cueball || prod_id == "T17717D 50" // The Next Tetris (EU) diff --git a/core/reios/gdrom_hle.cpp b/core/reios/gdrom_hle.cpp index ee7e61dfa..7b2671cbc 100644 --- a/core/reios/gdrom_hle.cpp +++ b/core/reios/gdrom_hle.cpp @@ -44,7 +44,7 @@ static void GDROM_HLE_ReadTOC() if (area == DoubleDensity && libGDR_GetDiscType() != GdRom) { // Only GD-ROM has a high-density area but no error is reported - gd_hle_state.status = BIOS_INACTIVE; + gd_hle_state.status = GDC_OK; return; } @@ -112,29 +112,29 @@ static void read_sectors_to(u32 addr, u32 sector, u32 count) static void GDROM_HLE_ReadDMA() { - u32 s = gd_hle_state.params[0]; - u32 n = gd_hle_state.params[1]; - u32 b = gd_hle_state.params[2]; - u32 u = gd_hle_state.params[3]; + u32 fad = gd_hle_state.params[0]; + u32 nsect = gd_hle_state.params[1]; + u32 buffer = gd_hle_state.params[2]; + // params[3] 0 - debugf("GDROM: DMA READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X", s, n, b, u); + debugf("GDROM: DMA READ Sector=%d, Num=%d, Buffer=%08x, zero=%x", fad, nsect, buffer, gd_hle_state.params[3]); - read_sectors_to(b, s, n); + read_sectors_to(buffer, fad, nsect); gd_hle_state.result[2] = 0; gd_hle_state.result[3] = 0; } static void GDROM_HLE_ReadPIO() { - u32 s = gd_hle_state.params[0]; - u32 n = gd_hle_state.params[1]; - u32 b = gd_hle_state.params[2]; - u32 u = gd_hle_state.params[3]; + u32 fad = gd_hle_state.params[0]; + u32 nsect = gd_hle_state.params[1]; + u32 buffer = gd_hle_state.params[2]; + // params[3] seekAhead (wince) or 0 - debugf("GDROM: PIO READ Sector=%d, Num=%d, Buffer=0x%08X, Unk01=0x%08X", s, n, b, u); + debugf("GDROM: PIO READ Sector=%d, Num=%d, Buffer=%08x, SeekAhead=%x", fad, nsect, buffer, gd_hle_state.params[3]); - read_sectors_to(b, s, n); - gd_hle_state.result[2] = n * 2048; + read_sectors_to(buffer, fad, nsect); + gd_hle_state.result[2] = nsect * 2048; gd_hle_state.result[3] = 0; } @@ -142,13 +142,14 @@ static void GDCC_HLE_GETSCD() { u32 format = gd_hle_state.params[0]; u32 size = gd_hle_state.params[1]; u32 dest = gd_hle_state.params[2]; + // params[3] 0 DEBUG_LOG(REIOS, "GDROM: GETSCD format %x size %x dest %08x", format, size, dest); if (libGDR_GetDiscType() == Open || libGDR_GetDiscType() == NoDisk) { - gd_hle_state.status = BIOS_ERROR; - gd_hle_state.result[0] = 2; // ? + gd_hle_state.status = GDC_ERR; + gd_hle_state.result[0] = 6; // GDC_ERR_UNITATTENTION gd_hle_state.result[1] = 0; gd_hle_state.result[2] = 0; gd_hle_state.result[3] = 0; @@ -157,7 +158,7 @@ static void GDCC_HLE_GETSCD() { if (sns_asc != 0) { // Helps D2 detect the disk change - gd_hle_state.status = BIOS_ERROR; + gd_hle_state.status = GDC_ERR; gd_hle_state.result[0] = sns_key; gd_hle_state.result[1] = sns_asc; gd_hle_state.result[2] = 0x18; // ? @@ -184,6 +185,7 @@ static void GDCC_HLE_GETSCD() { // record size of pio transfer to gdrom gd_hle_state.result[2] = size; } + template static void multi_xfer() { @@ -243,7 +245,7 @@ static void multi_xfer() if (!dma) { gd_hle_state.result[2] = gd_hle_state.multi_read_total - gd_hle_state.multi_read_count; - gd_hle_state.result[3] = 0; // 1 hangs Bust-a-Move-4 + gd_hle_state.result[3] = GDC_WAIT_INTERNAL; if (gd_hle_state.multi_callback != 0) { Sh4cntx.r[4] = gd_hle_state.multi_callback_arg; @@ -253,17 +255,17 @@ static void multi_xfer() else { gd_hle_state.result[2] = 2048; - gd_hle_state.result[3] = gd_hle_state.multi_read_count > 0 ? 1 : 0; + gd_hle_state.result[3] = gd_hle_state.multi_read_count > 0 ? GDC_WAIT_IRQ : GDC_WAIT_INTERNAL; gd_hle_state.dma_trans_ended = true; if (gd_hle_state.multi_read_count == 0) - gd_hle_state.status = BIOS_COMPLETED; + gd_hle_state.status = GDC_COMPLETE; asic_RaiseInterrupt(holly_GDROM_DMA); } } u32 SecMode[4]; -static void GD_HLE_Command(u32 cc) +static void GD_HLE_Command(gd_command cc) { switch(cc) { @@ -275,7 +277,7 @@ static void GD_HLE_Command(u32 cc) GDROM_HLE_ReadTOC(); break; - case GDCC_GETSES: + case GDCC_REQ_SES: GDROM_HLE_ReadSES(); break; @@ -308,22 +310,23 @@ static void GD_HLE_Command(u32 cc) break; - case GDCC_PLAY_SECTOR: + case GDCC_PLAY2: { - u32 start_fad = gd_hle_state.params[0]; - u32 end_fad = gd_hle_state.params[1]; - DEBUG_LOG(REIOS, "GDROM: CMD PLAYSEC from %d to %d repeats %d", start_fad, end_fad, gd_hle_state.params[2]); - cdda.status = cdda_t::Playing; - cdda.StartAddr.FAD = start_fad; - cdda.EndAddr.FAD = end_fad; + cdda.StartAddr.FAD = gd_hle_state.params[0]; + cdda.EndAddr.FAD = gd_hle_state.params[1]; cdda.repeats = gd_hle_state.params[2]; - cdda.CurrAddr.FAD = start_fad; + // params[3] debug (0) + DEBUG_LOG(REIOS, "GDROM: CMD PLAYSEC from %d to %d repeats %d", cdda.StartAddr.FAD, cdda.EndAddr.FAD, cdda.repeats); + cdda.status = cdda_t::Playing; + cdda.CurrAddr.FAD = cdda.StartAddr.FAD; SecNumber.Status = GD_PLAY; } break; case GDCC_RELEASE: DEBUG_LOG(REIOS, "GDROM: CMD RELEASE"); + cdda.repeats = gd_hle_state.params[0]; + // params[1] debug (0) if (cdda.status == cdda_t::Paused) cdda.status = cdda_t::Playing; SecNumber.Status = GD_PLAY; @@ -337,6 +340,8 @@ static void GD_HLE_Command(u32 cc) case GDCC_SEEK: DEBUG_LOG(REIOS, "GDROM: CMD SEEK"); + cdda.CurrAddr.FAD = cdda.StartAddr.FAD = gd_hle_state.params[0]; + // params[1] debug (0) cdda.status = cdda_t::Paused; SecNumber.Status = GD_PAUSE; break; @@ -345,18 +350,16 @@ static void GD_HLE_Command(u32 cc) { u32 first_track = gd_hle_state.params[0]; u32 last_track = gd_hle_state.params[1]; - u32 repeats = gd_hle_state.params[2]; - u32 start_fad, end_fad, dummy; - libGDR_GetTrack(first_track, start_fad, dummy); - libGDR_GetTrack(last_track, dummy, end_fad); - DEBUG_LOG(REIOS, "GDROM: CMD PLAY first_track %x last_track %x repeats %x start_fad %x end_fad %x param4 %x", first_track, last_track, repeats, - start_fad, end_fad, gd_hle_state.params[3]); + cdda.repeats = gd_hle_state.params[2]; + // params[3] debug (0) + u32 dummy; + libGDR_GetTrack(first_track, cdda.StartAddr.FAD, dummy); + libGDR_GetTrack(last_track, dummy, cdda.EndAddr.FAD); + DEBUG_LOG(REIOS, "GDROM: CMD PLAY first_track %x last_track %x repeats %x start_fad %x end_fad %x", first_track, last_track, cdda.repeats, + cdda.StartAddr.FAD, cdda.EndAddr.FAD); cdda.status = cdda_t::Playing; - cdda.StartAddr.FAD = start_fad; - cdda.EndAddr.FAD = end_fad; - cdda.repeats = repeats; - if (SecNumber.Status != GD_PAUSE || cdda.CurrAddr.FAD < start_fad || cdda.CurrAddr.FAD > end_fad) - cdda.CurrAddr.FAD = start_fad; + if (SecNumber.Status != GD_PAUSE || cdda.CurrAddr.FAD < cdda.StartAddr.FAD || cdda.CurrAddr.FAD > cdda.EndAddr.FAD) + cdda.CurrAddr.FAD = cdda.StartAddr.FAD; SecNumber.Status = GD_PLAY; } break; @@ -368,19 +371,19 @@ static void GD_HLE_Command(u32 cc) SecNumber.Status = GD_PAUSE; break; - case GDCC_READ: + case GDCC_DMA_READ_REQ: { u32 sector = gd_hle_state.params[0]; u32 num = gd_hle_state.params[1]; DEBUG_LOG(REIOS, "GDROM: CMD READ Sector=%d, Num=%d", sector, num); - gd_hle_state.status = BIOS_DATA_AVAIL; + gd_hle_state.status = GDC_CONTINUE; gd_hle_state.multi_read_sector = sector; gd_hle_state.multi_read_count = num * 2048; gd_hle_state.multi_read_total = gd_hle_state.multi_read_count; gd_hle_state.multi_read_offset = 0; gd_hle_state.result[2] = 2048; - gd_hle_state.result[3] = num > 0 ? 1 : 0; + gd_hle_state.result[3] = num > 0 ? GDC_WAIT_IRQ : GDC_WAIT_INTERNAL; } break; @@ -422,11 +425,12 @@ static void GD_HLE_Command(u32 cc) } break; - case GDCC_GET_VER: + case GDCC_GET_VERSION: { u32 dest = gd_hle_state.params[0]; + // params[1] 0 - debugf("GDROM: GDCC_GET_VER dest %x", dest); + debugf("GDROM: GDCC_GET_VERSION dest %x", dest); char ver[] = "GDC Version 1.10 1999-03-31 "; u32 len = (u32)strlen(ver); @@ -444,10 +448,10 @@ static void GD_HLE_Command(u32 cc) case GDCC_REQ_STAT: { // odd, but this function seems to get passed 4 unique pointers - u32 dst0 = gd_hle_state.params[0]; - u32 dst1 = gd_hle_state.params[1]; - u32 dst2 = gd_hle_state.params[2]; - u32 dst3 = gd_hle_state.params[3]; + u32 dst0 = gd_hle_state.params[0]; // repeat + u32 dst1 = gd_hle_state.params[1]; // track + u32 dst2 = gd_hle_state.params[2]; // toc + u32 dst3 = gd_hle_state.params[3]; // index debugf("GDROM: GDCC_REQ_STAT dst0=%08x dst1=%08x dst2=%08x dst3=%08x", dst0, dst1, dst2, dst3); @@ -459,7 +463,6 @@ static void GD_HLE_Command(u32 cc) // 1 | 0 | 0 | 0 | 0 | repeat count // ------------------------------------------------------ // 2-3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 -// WriteMem32(dst0, (cdda.repeats << 8) | SecNumber.Status); WriteMem32(dst0, (cdda.repeats << 8) | (SecNumber.Status == GD_STANDBY ? GD_PAUSE : SecNumber.Status)); // bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 @@ -500,11 +503,12 @@ static void GD_HLE_Command(u32 cc) { u32 sector = gd_hle_state.params[0]; u32 num = gd_hle_state.params[1]; + // params[2] seekAhead (wince) bool dma = cc == GDCC_MULTI_DMAREAD; - DEBUG_LOG(REIOS, "GDROM: MULTI_%sREAD Sector=%d, Num=%d", dma ? "DMA" : "PIO", sector, num); + DEBUG_LOG(REIOS, "GDROM: MULTI_%sREAD Sector=%d, Num=%d SeekAhead=%d", dma ? "DMA" : "PIO", sector, num, gd_hle_state.params[2]); - gd_hle_state.status = BIOS_DATA_AVAIL; + gd_hle_state.status = GDC_CONTINUE; gd_hle_state.multi_read_sector = sector; gd_hle_state.multi_read_count = num * 2048; gd_hle_state.multi_read_total = gd_hle_state.multi_read_count; @@ -535,29 +539,29 @@ static void GD_HLE_Command(u32 cc) WARN_LOG(REIOS, "GDROM: Unknown GDROM CC:%X", cc); break; } - if (gd_hle_state.status == BIOS_ACTIVE) - gd_hle_state.status = BIOS_COMPLETED; - gd_hle_state.command = -1; + if (gd_hle_state.status == GDC_BUSY) + gd_hle_state.status = GDC_COMPLETE; + gd_hle_state.command = GDCC_NONE; } #define r Sh4cntx.r void gdrom_hle_op() { - if( SYSCALL_GDROM == r[6] ) // GDROM SYSCALL + if (SYSCALL_GDROM == r[6]) // GDROM SYSCALL { switch(r[7]) // COMMAND CODE { - case GDROM_SEND_COMMAND: + case GDROM_REQ_CMD: // Enqueue a command for the GDROM subsystem to execute. // // Args: // r4 = command code // r5 = pointer to parameter block for the command, can be NULL if the command does not take parameters // - // Returns: a request id (>=0) if successful, negative error code if failed - debugf("GDROM: HLE SEND COMMAND CC:%X param ptr: %X bios status %d", r[4], r[5], gd_hle_state.status); - if (gd_hle_state.status != BIOS_INACTIVE) + // Returns: a request id (>0) if successful, 0 if failed + debugf("GDROM: HLE REQ_CMD CC:%X param ptr: %X bios status %d", r[4], r[5], gd_hle_state.status); + if (gd_hle_state.status != GDC_OK) { r[0] = 0; } @@ -576,147 +580,158 @@ void gdrom_hle_op() if (gd_hle_state.next_request_id == ~0u || gd_hle_state.next_request_id == 0) gd_hle_state.next_request_id = 1; gd_hle_state.last_request_id = r[0] = gd_hle_state.next_request_id++; - gd_hle_state.status = BIOS_ACTIVE; - gd_hle_state.command = r[4]; + gd_hle_state.status = GDC_BUSY; + gd_hle_state.command = (gd_command)r[4]; gd_hle_state.multi_read_count = 0; } break; - case GDROM_CHECK_COMMAND: + case GDROM_GET_CMD_STAT: // Check if an enqueued command has completed. // // Args: // r4 = request id - // r5 = pointer to four 32 bit integers to receive extended status information. The first is a generic error code. + // r5 = pointer to four 32 bit integers to receive extended status information. The first is a generic error code: + // GDC_ERR_NOERR 0x00 + // GDC_ERR_RECOVERED 0x01 + // GDC_ERR_NOTREADY 0x02 + // GDC_ERR_MEDIUM 0x03 + // GDC_ERR_HARDWARE 0x04 + // GDC_ERR_ILLEGALREQUEST 0x05 + // GDC_ERR_UNITATTENTION 0x06 + // GDC_ERR_DATAPROTECT 0x07 + // GDC_ERR_ABORTED 0x0B + // GDC_ERR_NOREADABLE 0x10 + // GDC_ERR_G1SEMAPHORE 0x20 // // Returns: - // 0 - no such request active - // 1 - request is still being processed - // 2 - request has completed (if queried again, you will get a 0) - // 3 - multi request has data available - // -1 - request has failed (examine extended status information for cause of failure) + // GDC_OK - no such request active (idle) + // GDC_BUSY - request is still being processed + // GDC_COMPLETE - request has completed (if queried again, you will get GDC_OK) + // GDC_CONTINUE - multi request has data available + // GDC_SMPHR_BUSY ? + // GDC_ERR - request has failed (examine extended status information for cause of failure) try { - WriteMem32(r[5], gd_hle_state.result[0]); - WriteMem32(r[5] + 4, gd_hle_state.result[1]); - WriteMem32(r[5] + 8, gd_hle_state.result[2]); - WriteMem32(r[5] + 12, gd_hle_state.result[3]); + WriteMem32(r[5], gd_hle_state.result[0]); // error + WriteMem32(r[5] + 4, gd_hle_state.result[1]); // error1 + WriteMem32(r[5] + 8, gd_hle_state.result[2]); // size + WriteMem32(r[5] + 12, gd_hle_state.result[3]); // wait state (if busy) } catch (SH4ThrownException&) { } - if (gd_hle_state.status == BIOS_INACTIVE || gd_hle_state.status == BIOS_ACTIVE) + if (gd_hle_state.status == GDC_OK || gd_hle_state.status == GDC_BUSY) { - r[0] = gd_hle_state.status; // no such request active or still being processed + r[0] = gd_hle_state.status; } else if (r[4] != gd_hle_state.last_request_id) { - r[0] = 0; // no such request active + r[0] = GDC_OK; // no such request active } else { - if (gd_hle_state.status == BIOS_DATA_AVAIL && gd_hle_state.command == GDCC_REQ_PIO_TRANS) - r[0] = BIOS_ACTIVE; // Bust-a-move 4 likes this + if (gd_hle_state.status == GDC_CONTINUE && gd_hle_state.command == GDCC_REQ_PIO_TRANS) + r[0] = GDC_BUSY; // Bust-a-move 4 likes this else r[0] = gd_hle_state.status; // completed or error // Fixes NBA 2K - if (gd_hle_state.status == BIOS_DATA_AVAIL && gd_hle_state.multi_read_count == 0) + if (gd_hle_state.status == GDC_CONTINUE && gd_hle_state.multi_read_count == 0) { - gd_hle_state.status = BIOS_COMPLETED; + gd_hle_state.status = GDC_COMPLETE; gd_hle_state.result[3] = 0; } - else if (gd_hle_state.status != BIOS_DATA_AVAIL) + else if (gd_hle_state.status != GDC_CONTINUE) { - gd_hle_state.status = BIOS_INACTIVE; + gd_hle_state.status = GDC_OK; gd_hle_state.last_request_id = 0xFFFFFFFF; } } - debugf("GDROM: HLE CHECK COMMAND REQID:%X param ptr: %X -> %X : %x %x %x %x", r[4], r[5], r[0], + debugf("GDROM: HLE GET_CMD_STAT REQID:%X param ptr: %X -> %X : %x %x %x %x", r[4], r[5], r[0], gd_hle_state.result[0], gd_hle_state.result[1], gd_hle_state.result[2], gd_hle_state.result[3]); break; - case GDROM_MAIN: + case GDROM_EXEC_SERVER: // In order for enqueued commands to get processed, this function must be called a few times. - debugf("GDROM: HLE GDROM_MAIN"); - if (gd_hle_state.status == BIOS_ACTIVE || (gd_hle_state.status == BIOS_DATA_AVAIL && gd_hle_state.command == GDCC_REQ_PIO_TRANS)) + debugf("GDROM: HLE EXEC_SERVER"); + if (gd_hle_state.status == GDC_BUSY || (gd_hle_state.status == GDC_CONTINUE && gd_hle_state.command == GDCC_REQ_PIO_TRANS)) { GD_HLE_Command(gd_hle_state.command); } break; - case GDROM_INIT: + case GDROM_INIT_SYSTEM: // Initialize the GDROM subsystem. Should be called before any requests are enqueued. - DEBUG_LOG(REIOS, "GDROM: HLE GDROM_INIT"); + DEBUG_LOG(REIOS, "GDROM: HLE INIT_SYSTEM"); gd_hle_state = {}; break; case GDROM_RESET: // Resets the drive. - DEBUG_LOG(REIOS, "GDROM: HLE GDROM_RESET"); + DEBUG_LOG(REIOS, "GDROM: HLE RESET"); gd_hle_state.last_request_id = 0xFFFFFFFF; - gd_hle_state.status = BIOS_INACTIVE; + gd_hle_state.status = GDC_OK; break; - case GDROM_CHECK_DRIVE: + case GDROM_GET_DRV_STAT: { // Checks the general condition of the drive. // // Args: - // r4 = pointer to two 32 bit integers, to receive the drive status. The first is the current drive status, the second is the type of disc inserted (if any). - // 0 Drive is busy - // 1 Drive is paused - // 2 Drive is in standby - // 3 Drive is playing - // 4 Drive is seeking - // 5 Drive is scanning - // 6 Drive lid is open - // 7 Lid is closed, but there is no disc + // r4 = pointer to two 32 bit integers, to receive the drive status. The first is the current drive status (gd_drv_stat), + // the second is the type of disc inserted (if any). // - // Returns: zero if successful, nonzero if failure + // Returns: 0 OK, -1 ERR, 1 BUSY, 2 COMPLETE, 3 CONTINUE + gd_drv_stat status; u32 discType = libGDR_GetDiscType(); switch (discType) { case Open: - WriteMem32(r[4], 6); - WriteMem32(r[4] + 4, 0); + status = GD_STAT_OPEN; + discType = 0; break; case NoDisk: - WriteMem32(r[4], 7); - WriteMem32(r[4] + 4, 0); + status = GD_STAT_NODISC; + discType = 0; break; default: - WriteMem32(r[4], (gd_hle_state.status == BIOS_DATA_AVAIL || SecNumber.Status == GD_PLAY) ? 3 : 1); - if (memcmp(ip_meta.disk_type, "GD-ROM", sizeof(ip_meta.disk_type)) == 0) - WriteMem32(r[4] + 4, GdRom); + if (gd_hle_state.status == GDC_BUSY) + status = GD_STAT_BUSY; + else if (gd_hle_state.status == GDC_CONTINUE || SecNumber.Status == GD_PLAY) + status = GD_STAT_PLAY; else - WriteMem32(r[4] + 4, discType); + status = GD_STAT_PAUSE; + if (memcmp(ip_meta.disk_type, "GD-ROM", sizeof(ip_meta.disk_type)) == 0) + discType = GdRom; break; } - debugf("GDROM: HLE GDROM_CHECK_DRIVE r4:%X -> %x %x", r[4], ReadMem32(r[4]), ReadMem32(r[4] + 4)); - r[0] = 0; + WriteMem32(r[4], (u32)status); + WriteMem32(r[4] + 4, discType); + debugf("GDROM: HLE GET_DRV_STAT r4:%X -> %x %x", r[4], status, discType); + r[0] = GDC_OK; } break; - case GDROM_ABORT_COMMAND: + case GDROM_READ_ABORT: // Tries to abort a previously enqueued command. // // Args: // r4 = request id // - // Returns: zero if successful, nonzero if failure - WARN_LOG(REIOS, "GDROM: HLE GDROM_ABORT_COMMAND r4:%X",r[4]); + // Returns: GDC_OK, GDC_ERR + WARN_LOG(REIOS, "GDROM: HLE GDROM_ABORT_COMMAND req id%x", r[4]); if (r[4] == gd_hle_state.last_request_id - && (gd_hle_state.status == BIOS_DATA_AVAIL || gd_hle_state.status == BIOS_ACTIVE)) + && (gd_hle_state.status == GDC_CONTINUE || gd_hle_state.status == GDC_BUSY || gd_hle_state.status == GDC_COMPLETE)) { - r[0] = 0; + r[0] = GDC_OK; gd_hle_state.multi_read_count = 0; gd_hle_state.xfer_end_time = 0; } else { - r[0] = -1; + r[0] = GDC_ERR; } break; - case GDROM_SECTOR_MODE: + case GDROM_CHANGE_DATA_TYPE: // Sets/gets the sector format for read commands. // // Args: @@ -727,42 +742,43 @@ void gdrom_hle_op() // 2 1024 = mode 1, 2048 = mode 2, 0 = auto detect // 3 Sector size in bytes (normally 2048) // - // Returns: zero if successful, -1 if failure - DEBUG_LOG(REIOS, "GDROM: HLE GDROM_SECTOR_MODE PTR_r4:%X",r[4]); + // Returns: GDC_OK, GDC_ERR + DEBUG_LOG(REIOS, "GDROM: HLE CHANGE_DATA_TYPE PTR_r4:%X",r[4]); for(int i=0; i<4; i++) { SecMode[i] = ReadMem32(r[4]+(i<<2)); DEBUG_LOG(REIOS, "%08X", SecMode[i]); } - r[0] = 0; + r[0] = GDC_OK; break; case GDROM_G1_DMA_END: DEBUG_LOG(REIOS, "GDROM: G1_DMA_END callback %x arg %x", r[4], r[5]); gd_hle_state.multi_callback = r[4]; gd_hle_state.multi_callback_arg = r[5]; - r[0] = 0; + r[0] = GDC_OK; if (gd_hle_state.multi_callback != 0 && gd_hle_state.dma_trans_ended) // FIXME hack for 2K sports games { r[4] = gd_hle_state.multi_callback_arg; Sh4cntx.pc = gd_hle_state.multi_callback; gd_hle_state.dma_trans_ended = false; } + asic_CancelInterrupt(holly_GDROM_DMA); break; case GDROM_REQ_DMA_TRANS: - gd_hle_state.params[0] = ReadMem32(r[5]); - gd_hle_state.params[1] = ReadMem32(r[5] + 4); + gd_hle_state.params[0] = ReadMem32(r[5]); // buffer + gd_hle_state.params[1] = ReadMem32(r[5] + 4); // size DEBUG_LOG(REIOS, "GDROM: REQ_DMA_TRANS req_id %x dest %x size %x", r[4], gd_hle_state.params[0], gd_hle_state.params[1]); - if (gd_hle_state.status != BIOS_DATA_AVAIL || gd_hle_state.params[1] > gd_hle_state.multi_read_count) + if (gd_hle_state.status != GDC_CONTINUE || gd_hle_state.params[1] > gd_hle_state.multi_read_count || gd_hle_state.params[1] == 0) { - r[0] = -1; + r[0] = GDC_ERR; } else { multi_xfer(); - r[0] = 0; + r[0] = GDC_OK; } break; @@ -771,29 +787,30 @@ void gdrom_hle_op() gd_hle_state.params[1] = ReadMem32(r[5] + 4); DEBUG_LOG(REIOS, "GDROM: REQ_PIO_TRANS req_id %x dest %x size %x", r[4], gd_hle_state.params[0], gd_hle_state.params[1]); - if (gd_hle_state.status != BIOS_DATA_AVAIL || gd_hle_state.params[1] > gd_hle_state.multi_read_count) + if (gd_hle_state.status != GDC_CONTINUE || gd_hle_state.params[1] > gd_hle_state.multi_read_count) { - r[0] = -1; + r[0] = GDC_ERR; } else { gd_hle_state.command = GDCC_REQ_PIO_TRANS; - r[0] = 0; + r[0] = GDC_OK; } break; case GDROM_CHECK_DMA_TRANS: { + // r4 handle u32 len_addr = r[5]; DEBUG_LOG(REIOS, "GDROM: CHECK_DMA_TRANS req_id %x len_addr %x -> %x", r[4], len_addr, gd_hle_state.multi_read_count); - if (gd_hle_state.status == BIOS_DATA_AVAIL) + WriteMem32(len_addr, gd_hle_state.multi_read_count); + if (gd_hle_state.status == GDC_CONTINUE) { - WriteMem32(len_addr, gd_hle_state.multi_read_count); - r[0] = 0; + r[0] = GDC_OK; } else { - r[0] = -1; + r[0] = GDC_BUSY; } } break; @@ -802,21 +819,21 @@ void gdrom_hle_op() DEBUG_LOG(REIOS, "GDROM: SET_PIO_CALLBACK callback %x arg %x", r[4], r[5]); gd_hle_state.multi_callback = r[4]; gd_hle_state.multi_callback_arg = r[5]; - r[0] = 0; + r[0] = GDC_OK; break; case GDROM_CHECK_PIO_TRANS: { u32 len_addr = r[5]; DEBUG_LOG(REIOS, "GDROM: CHECK_PIO_TRANS req_id %x len_addr %x -> %x", r[4], len_addr, gd_hle_state.multi_read_count); - if (gd_hle_state.status == BIOS_DATA_AVAIL) + if (gd_hle_state.status == GDC_CONTINUE) { WriteMem32(len_addr, gd_hle_state.multi_read_count); - r[0] = 0; + r[0] = GDC_OK; } else { - r[0] = -1; + r[0] = GDC_ERR; } } break; @@ -834,7 +851,7 @@ void gdrom_hle_op() // Initializes all the syscall vectors to their default values. // Returns: zero WARN_LOG(REIOS, "GDROM: MISC_INIT not implemented"); - r[0] = 0; + r[0] = GDC_OK; break; case MISC_SETVECTOR: diff --git a/core/reios/gdrom_hle.h b/core/reios/gdrom_hle.h index 01cf0a03e..2f5d98785 100644 --- a/core/reios/gdrom_hle.h +++ b/core/reios/gdrom_hle.h @@ -3,61 +3,95 @@ #define SYSCALL_GDROM 0x00 -#define GDROM_SEND_COMMAND 0x00 -#define GDROM_CHECK_COMMAND 0x01 -#define GDROM_MAIN 0x02 -#define GDROM_INIT 0x03 -#define GDROM_CHECK_DRIVE 0x04 -#define GDROM_G1_DMA_END 0x05 // r4: callback, r5: callback arg -#define GDROM_REQ_DMA_TRANS 0x06 // r4: request id -#define GDROM_CHECK_DMA_TRANS 0x07 // r4: request id, r5: u32 *size -#define GDROM_ABORT_COMMAND 0x08 -#define GDROM_RESET 0x09 -#define GDROM_SECTOR_MODE 0x0A -#define GDROM_SET_PIO_CALLBACK 0x0B // r4: callback, r5: callback arg -#define GDROM_REQ_PIO_TRANS 0x0C // r4: request id -#define GDROM_CHECK_PIO_TRANS 0x0D // r4: request id, r5: u32 *size +enum gd_entry_points { + GDROM_REQ_CMD, + GDROM_GET_CMD_STAT, + GDROM_EXEC_SERVER, + GDROM_INIT_SYSTEM, + GDROM_GET_DRV_STAT, + GDROM_G1_DMA_END, // r4: callback, r5: callback arg + GDROM_REQ_DMA_TRANS, // r4: request id + GDROM_CHECK_DMA_TRANS, // r4: request id, r5: u32 *size + GDROM_READ_ABORT, + GDROM_RESET, + GDROM_CHANGE_DATA_TYPE, + GDROM_SET_PIO_CALLBACK, // r4: callback, r5: callback arg + GDROM_REQ_PIO_TRANS, // r4: request id + GDROM_CHECK_PIO_TRANS // r4: request id, r5: u32 *size +}; -#define GDCC_PIOREAD 0x10 -#define GDCC_DMAREAD 0x11 -#define GDCC_GETTOC 0x12 -#define GDCC_GETTOC2 0x13 -#define GDCC_PLAY 0x14 -#define GDCC_PLAY_SECTOR 0x15 -#define GDCC_PAUSE 0x16 -#define GDCC_RELEASE 0x17 -#define GDCC_INIT 0x18 -#define GDCC_SEEK 0x1b -#define GDCC_READ 0x1c -#define GDCC_REQ_MODE 0x1e -#define GDCC_SET_MODE 0x1f -#define GDCC_STOP 0x21 -#define GDCC_GETSCD 0x22 -#define GDCC_GETSES 0x23 -#define GDCC_REQ_STAT 0x24 -#define GDCC_MULTI_DMAREAD 0x26 -#define GDCC_MULTI_PIOREAD 0x27 -#define GDCC_GET_VER 0x28 -// pseudo-commands for multi dma/pio xfers -#define GDCC_REQ_DMA_TRANS 0x106 -#define GDCC_REQ_PIO_TRANS 0x10C +typedef enum : u32 { + GDCC_NONE = 0, + GDCC_PIOREAD = 0x10, + GDCC_DMAREAD, + GDCC_GETTOC, + GDCC_GETTOC2, + GDCC_PLAY, + GDCC_PLAY2, + GDCC_PAUSE, + GDCC_RELEASE, + GDCC_INIT, + GDCC_READABORT, + GDCC_OPEN, + GDCC_SEEK, + GDCC_DMA_READ_REQ, + GDCC_GETQINFO, + GDCC_REQ_MODE, + GDCC_SET_MODE, + GDCC_SCAN, + GDCC_STOP, + GDCC_GETSCD, + GDCC_REQ_SES, + GDCC_REQ_STAT, + GDCC_PIOREADREQ, + GDCC_MULTI_DMAREAD, + GDCC_MULTI_PIOREAD, + GDCC_GET_VERSION, + GDCC_CMDA, + GDCC_CMDB, + GDCC_CMDC, + GDCC_CMDD, + GDCC_CMDE, + GDCC_CMDF, + GDCC_CMDG, + // pseudo-commands for multi dma/pio xfers + GDCC_REQ_DMA_TRANS = 0x106, + GDCC_REQ_PIO_TRANS = 0x10C +} gd_command; -#define MISC_INIT 0x00 -#define MISC_SETVECTOR 0x01 +enum gdc_wait { + GDC_WAIT_INTERNAL, + GDC_WAIT_IRQ +}; + +enum misc_command { + MISC_INIT, + MISC_SETVECTOR +}; void gdrom_hle_init(); void gdrom_hle_term(); void gdrom_hle_op(); -typedef enum { BIOS_ERROR = -1, BIOS_INACTIVE, BIOS_ACTIVE, BIOS_COMPLETED, BIOS_DATA_AVAIL } gd_bios_status; +typedef enum : int32_t { + GDC_ERR = -1, + GDC_OK, // Idle + GDC_BUSY, // Command being processed + GDC_COMPLETE, // Command has finished + GDC_CONTINUE, // Data has been transferred, more data available + GDC_SMPHR_BUSY, + GDC_RET1, + GDC_RET2 +} gd_return_value; + struct gdrom_hle_state_t { gdrom_hle_state_t() : params{}, result{} {} u32 last_request_id = 0xFFFFFFFF; u32 next_request_id = 2; - gd_bios_status status = BIOS_INACTIVE; - u32 command = 0; + gd_return_value status = GDC_OK; + gd_command command = GDCC_NONE; u32 params[4]; u32 result[4]; u32 cur_sector = 0; @@ -110,3 +144,16 @@ struct gdrom_hle_state_t }; extern gdrom_hle_state_t gd_hle_state; +// status for GDROM_GET_DRV_STAT +enum gd_drv_stat { + GD_STAT_BUSY, + GD_STAT_PAUSE, + GD_STAT_STANDBY, + GD_STAT_PLAY, + GD_STAT_SEEK, + GD_STAT_SCAN, + GD_STAT_OPEN, + GD_STAT_NODISC, + GD_STAT_RETRY, + GD_STAT_ERROR +};