Skip to content

Commit

Permalink
set error code when GDC_CHECK_COMMAND is called for something other
Browse files Browse the repository at this point in the history
than the most recent command

clear result after GDC_CHECK_COMMAND is called for a valid command

ignore invalid GDC_GETTOC2 commands
  • Loading branch information
inolen committed Dec 5, 2017
1 parent ba71415 commit e032445
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 76 deletions.
165 changes: 91 additions & 74 deletions src/guest/bios/syscalls.c
Expand Up @@ -93,18 +93,19 @@ enum {
};

enum {
GDC_STATUS_NONE = 0x0,
GDC_STATUS_ERROR = -1,
GDC_STATUS_INACTIVE = 0x0,
GDC_STATUS_ACTIVE = 0x1,
GDC_STATUS_DONE = 0x2,
GDC_STATUS_COMPLETE = 0x2,
GDC_STATUS_ABORT = 0x3,
GDC_STATUS_ERROR = 0x4,
};

enum {
GDC_ERROR_OK = 0x0,
GDC_ERROR_SYSTEM = 0x1,
GDC_ERROR_NO_DISC = 0x2,
GDC_ERROR_INVALID_CMD = 0x5,
GDC_ERROR_DISC_CHANGE = 0x6,
GDC_ERROR_SYSTEM = 0x1,
};

static int bios_gdrom_override_format(struct bios *bios, int format) {
Expand Down Expand Up @@ -140,7 +141,7 @@ static uint32_t bios_gdrom_send_cmd(struct bios *bios, uint32_t cmd_code,
uint32_t params) {
struct dreamcast *dc = bios->dc;

if (bios->status != GDC_STATUS_NONE) {
if (bios->status != GDC_STATUS_INACTIVE) {
return 0;
}

Expand Down Expand Up @@ -173,6 +174,9 @@ static void bios_gdrom_mainloop(struct bios *bios) {
return;
}

/* by default, all commands report that they've completed successfully */
bios->status = GDC_STATUS_COMPLETE;

switch (bios->cmd_code) {
case GDC_PIOREAD:
case GDC_DMAREAD: {
Expand Down Expand Up @@ -213,69 +217,78 @@ static void bios_gdrom_mainloop(struct bios *bios) {
uint32_t area = bios->params[0];
uint32_t dst = bios->params[1];

LOG_SYSCALL("GDC_GETTOC2 0=0x%x 1=0x%x", area, dst);
LOG_SYSCALL("GDC_GETTOC2 area=0x%x dst=0x%x", area, dst);

struct gd_toc_info toc;
gdrom_get_toc(gd, area, &toc);
struct gd_status_info stat;
gdrom_get_status(gd, &stat);

/* bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
byte | | | | | | | |
------------------------------------------------------
n*4+0 | track n fad (lsb)
------------------------------------------------------
n*4+1 | track n fad
------------------------------------------------------
n*4*2 | track n fad (msb)
------------------------------------------------------
n*4+3 | track n control | track n adr
------------------------------------------------------
396 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
397 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
398 | start track number
------------------------------------------------------
399 | start track control | start track adr
------------------------------------------------------
400 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
401 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
402 | end track number
------------------------------------------------------
403 | end track control | end track adr
------------------------------------------------------
404 | lead-out track fad (lsb)
------------------------------------------------------
405 | lead-out track fad
------------------------------------------------------
406 | lead-out track fad (msb)
------------------------------------------------------
407 | lead-out track ctrl | lead-out track adr */
uint8_t out[408];
for (int i = 0; i < ARRAY_SIZE(toc.entries); i++) {
struct gd_toc_entry *entry = &toc.entries[i];
out[i * 4 + 0] = (entry->fad & 0x000000ff);
out[i * 4 + 1] = (entry->fad & 0x0000ff00) >> 8;
out[i * 4 + 2] = (entry->fad & 0x00ff0000) >> 16;
out[i * 4 + 3] = ((entry->ctrl & 0xf) << 4) | (entry->adr & 0xf);
if (area == GD_AREA_HIGH && stat.format != GD_DISC_GDROM) {
/* only GD-ROMs have a high-density area. in this situation, the bios
doesn't set a result or error */
bios->status = GDC_STATUS_INACTIVE;
} else {
struct gd_toc_info toc;
gdrom_get_toc(gd, area, &toc);

/* bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
byte | | | | | | | |
------------------------------------------------------
n*4+0 | track n fad (lsb)
------------------------------------------------------
n*4+1 | track n fad
------------------------------------------------------
n*4*2 | track n fad (msb)
------------------------------------------------------
n*4+3 | track n control | track n adr
------------------------------------------------------
396 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
397 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
398 | start track number
------------------------------------------------------
399 | start track control | start track adr
------------------------------------------------------
400 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
401 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
------------------------------------------------------
402 | end track number
------------------------------------------------------
403 | end track control | end track adr
------------------------------------------------------
404 | lead-out track fad (lsb)
------------------------------------------------------
405 | lead-out track fad
------------------------------------------------------
406 | lead-out track fad (msb)
------------------------------------------------------
407 | lead-out track ctrl | lead-out track adr */
uint8_t out[408];
for (int i = 0; i < ARRAY_SIZE(toc.entries); i++) {
struct gd_toc_entry *entry = &toc.entries[i];
out[i * 4 + 0] = (entry->fad & 0x000000ff);
out[i * 4 + 1] = (entry->fad & 0x0000ff00) >> 8;
out[i * 4 + 2] = (entry->fad & 0x00ff0000) >> 16;
out[i * 4 + 3] = ((entry->ctrl & 0xf) << 4) | (entry->adr & 0xf);
}
out[396] = 0;
out[397] = 0;
out[398] = toc.first.fad & 0xff;
out[399] = ((toc.first.ctrl & 0xf) << 4) | (toc.first.adr & 0xf);
out[400] = 0;
out[401] = 0;
out[402] = toc.last.fad & 0xff;
out[403] = ((toc.last.ctrl & 0xf) << 4) | (toc.last.adr & 0xf);
out[404] = (toc.leadout.fad & 0x000000ff);
out[405] = (toc.leadout.fad & 0x0000ff00) >> 8;
out[406] = (toc.leadout.fad & 0x00ff0000) >> 16;
out[407] = ((toc.leadout.ctrl & 0xf) << 4) | (toc.leadout.adr & 0xf);
sh4_memcpy_to_guest(dc->mem, dst, &out, sizeof(out));

/* the bios doesn't perform a pio transfer to get the toc for this req,
it is cached, so there is no transfer size to record */
}
out[396] = 0;
out[397] = 0;
out[398] = toc.first.fad & 0xff;
out[399] = ((toc.first.ctrl & 0xf) << 4) | (toc.first.adr & 0xf);
out[400] = 0;
out[401] = 0;
out[402] = toc.last.fad & 0xff;
out[403] = ((toc.last.ctrl & 0xf) << 4) | (toc.last.adr & 0xf);
out[404] = (toc.leadout.fad & 0x000000ff);
out[405] = (toc.leadout.fad & 0x0000ff00) >> 8;
out[406] = (toc.leadout.fad & 0x00ff0000) >> 16;
out[407] = ((toc.leadout.ctrl & 0xf) << 4) | (toc.leadout.adr & 0xf);
sh4_memcpy_to_guest(dc->mem, dst, &out, sizeof(out));

/* the bios doesn't perform a pio transfer to get the toc for this req,
it is cached, so there is no transfer size to record */
} break;

case GDC_PLAY: {
Expand Down Expand Up @@ -469,8 +482,6 @@ static void bios_gdrom_mainloop(struct bios *bios) {
LOG_FATAL("bios_gdrom_mainloop unexpected cmd=0x%x", bios->cmd_code);
} break;
}

bios->status = GDC_STATUS_DONE;
}

void bios_gdrom_vector(struct bios *bios) {
Expand Down Expand Up @@ -558,14 +569,20 @@ void bios_gdrom_vector(struct bios *bios) {

LOG_SYSCALL("GDROM_CHECK_COMMAND 0x%x 0x%x", cmd_id, status);

ctx->r[0] = bios->status;

if (cmd_id == bios->cmd_id && bios->status != GDC_STATUS_NONE) {
sh4_memcpy_to_guest(dc->mem, status, &bios->result,
if (cmd_id != bios->cmd_id) {
/* error if something other than the most recent command is checked */
const uint32_t result[] = {GDC_ERROR_INVALID_CMD, 0, 0, 0};
sh4_memcpy_to_guest(dc->mem, status, result, sizeof(result));
ctx->r[0] = GDC_STATUS_ERROR;
} else {
sh4_memcpy_to_guest(dc->mem, status, bios->result,
sizeof(bios->result));
}
ctx->r[0] = bios->status;

bios->status = GDC_STATUS_NONE;
/* clear result so nothing is returned if queried a second time */
bios->status = GDC_STATUS_INACTIVE;
memset(bios->result, 0, sizeof(bios->result));
}
} break;

case GDROM_MAINLOOP: {
Expand All @@ -591,7 +608,7 @@ void bios_gdrom_vector(struct bios *bios) {
*/
LOG_SYSCALL("GDROM_INIT");

bios->status = GDC_STATUS_NONE;
bios->status = GDC_STATUS_INACTIVE;
} break;

case GDROM_CHECK_DRIVE: {
Expand Down
4 changes: 2 additions & 2 deletions src/guest/gdrom/cdi.c
Expand Up @@ -50,8 +50,8 @@ static void cdi_get_toc(struct disc *disc, int area, struct track **first_track,
int *leadout_fad) {
struct cdi *cdi = (struct cdi *)disc;

/* cdi's have no high-density area */
CHECK_EQ(area, GD_AREA_SINGLE);
/* cdi's don't have a high-density area */
CHECK_NE(area, GD_AREA_HIGH);

/* the toc on cdi's represents all tracks / sessions */
struct session *first_session = &cdi->sessions[0];
Expand Down

0 comments on commit e032445

Please sign in to comment.