nkeynes@87: /** nkeynes@87: * $Id: bios.c,v 1.1 2006-01-22 22:40:53 nkeynes Exp $ nkeynes@87: * nkeynes@87: * "Fake" BIOS functions, for operation without the actual BIOS. nkeynes@87: * nkeynes@87: * Copyright (c) 2005 Nathan Keynes. nkeynes@87: * nkeynes@87: * This program is free software; you can redistribute it and/or modify nkeynes@87: * it under the terms of the GNU General Public License as published by nkeynes@87: * the Free Software Foundation; either version 2 of the License, or nkeynes@87: * (at your option) any later version. nkeynes@87: * nkeynes@87: * This program is distributed in the hope that it will be useful, nkeynes@87: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@87: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@87: * GNU General Public License for more details. nkeynes@87: */ nkeynes@87: nkeynes@87: #include "dream.h" nkeynes@87: #include "mem.h" nkeynes@87: #include "bios.h" nkeynes@87: #include "sh4/sh4core.h" nkeynes@87: nkeynes@87: #define COMMAND_QUEUE_LENGTH 16 nkeynes@87: nkeynes@87: /* TODO: Check if these are the real ATAPI command codes or not */ nkeynes@87: #define GD_CMD_PIOREAD 16 nkeynes@87: #define GD_CMD_DMAREAD 17 nkeynes@87: #define GD_CMD_GETTOC 18 nkeynes@87: #define GD_CMD_GETTOC2 19 nkeynes@87: #define GD_CMD_PLAY 20 nkeynes@87: #define GD_CMD_PLAY2 21 nkeynes@87: #define GD_CMD_PAUSE 22 nkeynes@87: #define GD_CMD_RELEASE 23 nkeynes@87: #define GD_CMD_INIT 24 nkeynes@87: #define GD_CMD_SEEK 27 nkeynes@87: #define GD_CMD_READ 28 nkeynes@87: #define GD_CMD_STOP 33 nkeynes@87: #define GD_CMD_GETSCD 34 nkeynes@87: #define GD_CMD_GETSES 35 nkeynes@87: nkeynes@87: #define GD_CMD_STATUS_NONE 0 nkeynes@87: #define GD_CMD_STATUS_ACTIVE 1 nkeynes@87: #define GD_CMD_STATUS_DONE 2 nkeynes@87: #define GD_CMD_STATUS_ABORT 3 nkeynes@87: #define GD_CMD_STATUS_ERROR 4 nkeynes@87: nkeynes@87: #define GD_ERROR_OK 0 nkeynes@87: #define GD_ERROR_NO_DISC 2 nkeynes@87: #define GD_ERROR_DISC_CHANGE 6 nkeynes@87: #define GD_ERROR_SYSTEM 1 nkeynes@87: nkeynes@87: nkeynes@87: typedef struct gdrom_command { nkeynes@87: int status; nkeynes@87: uint32_t cmd_code; nkeynes@87: char *data; nkeynes@87: uint32_t result[4]; nkeynes@87: } *gdrom_command_t; nkeynes@87: nkeynes@87: static struct gdrom_command gdrom_cmd_queue[COMMAND_QUEUE_LENGTH]; nkeynes@87: nkeynes@87: static struct bios_gdrom_status { nkeynes@87: uint32_t status; nkeynes@87: uint32_t disk_type; nkeynes@87: } bios_gdrom_status; nkeynes@87: nkeynes@87: void bios_gdrom_run_command( gdrom_command_t cmd ) nkeynes@87: { nkeynes@87: DEBUG( "BIOS GD command %d", cmd->cmd_code ); nkeynes@87: switch( cmd->cmd_code ) { nkeynes@87: case GD_CMD_INIT: nkeynes@87: /* *shrug* */ nkeynes@87: cmd->status = GD_CMD_STATUS_DONE; nkeynes@87: break; nkeynes@87: default: nkeynes@87: cmd->status = GD_CMD_STATUS_ERROR; nkeynes@87: cmd->result[0] = GD_ERROR_SYSTEM; nkeynes@87: break; nkeynes@87: } nkeynes@87: } nkeynes@87: nkeynes@87: void bios_gdrom_init( void ) nkeynes@87: { nkeynes@87: memset( &gdrom_cmd_queue, 0, sizeof(gdrom_cmd_queue) ); nkeynes@87: } nkeynes@87: nkeynes@87: uint32_t bios_gdrom_enqueue( uint32_t cmd, char *ptr ) nkeynes@87: { nkeynes@87: int i; nkeynes@87: for( i=0; i= COMMAND_QUEUE_LENGTH || nkeynes@87: gdrom_cmd_queue[id].status == GD_CMD_STATUS_NONE ) nkeynes@87: return NULL; nkeynes@87: return &gdrom_cmd_queue[id]; nkeynes@87: } nkeynes@87: nkeynes@87: void bios_install( void ) nkeynes@87: { nkeynes@87: bios_gdrom_init(); nkeynes@87: sh4_write_long( 0x8C0000B0, 0xFFFFFFB0 ); nkeynes@87: sh4_write_long( 0x8C0000B4, 0xFFFFFFB4 ); nkeynes@87: sh4_write_long( 0x8C0000B8, 0xFFFFFFB8 ); nkeynes@87: sh4_write_long( 0x8C0000BC, 0xFFFFFFBC ); nkeynes@87: sh4_write_long( 0x8C0000E0, 0xFFFFFFE0 ); nkeynes@87: } nkeynes@87: nkeynes@87: /** nkeynes@87: * Syscall list courtesy of Marcus Comstedt nkeynes@87: */ nkeynes@87: nkeynes@87: void bios_syscall( uint32_t syscallid ) nkeynes@87: { nkeynes@87: gdrom_command_t cmd; nkeynes@87: nkeynes@87: switch( syscallid ) { nkeynes@87: case 0xB0: /* sysinfo */ nkeynes@87: break; nkeynes@87: case 0xB4: /* Font */ nkeynes@87: break; nkeynes@87: case 0xB8: /* Flash */ nkeynes@87: break; nkeynes@87: case 0xBC: /* Misc/GD-Rom */ nkeynes@87: switch( sh4r.r[6] ) { nkeynes@87: case 0: /* GD-Rom */ nkeynes@87: switch( sh4r.r[7] ) { nkeynes@87: case 0: /* Send command */ nkeynes@87: if( sh4r.r[5] == 0 ) nkeynes@87: sh4r.r[0] = bios_gdrom_enqueue( sh4r.r[4], NULL ); nkeynes@87: else nkeynes@87: sh4r.r[0] = bios_gdrom_enqueue( sh4r.r[4], mem_get_region(sh4r.r[5]) ); nkeynes@87: break; nkeynes@87: case 1: /* Check command */ nkeynes@87: cmd = bios_gdrom_get_command( sh4r.r[4] ); nkeynes@87: if( cmd == NULL ) { nkeynes@87: sh4r.r[0] = GD_CMD_STATUS_NONE; nkeynes@87: } else { nkeynes@87: sh4r.r[0] = cmd->status; nkeynes@87: if( cmd->status == GD_CMD_STATUS_ERROR && nkeynes@87: sh4r.r[5] != 0 ) { nkeynes@87: mem_copy_to_sh4( sh4r.r[5], &cmd->result, sizeof(cmd->result) ); nkeynes@87: } nkeynes@87: } nkeynes@87: break; nkeynes@87: case 2: /* Mainloop */ nkeynes@87: bios_gdrom_run_queue(); nkeynes@87: break; nkeynes@87: case 3: /* Init */ nkeynes@87: bios_gdrom_init(); nkeynes@87: break; nkeynes@87: case 4: /* Drive status */ nkeynes@87: if( sh4r.r[4] != 0 ) { nkeynes@87: mem_copy_to_sh4( sh4r.r[4], &bios_gdrom_status, nkeynes@87: sizeof(bios_gdrom_status) ); nkeynes@87: } nkeynes@87: sh4r.r[0] = 0; nkeynes@87: break; nkeynes@87: case 8: /* Abort command */ nkeynes@87: cmd = bios_gdrom_get_command( sh4r.r[4] ); nkeynes@87: if( cmd == NULL || cmd->status != GD_CMD_STATUS_ACTIVE ) { nkeynes@87: sh4r.r[0] = -1; nkeynes@87: } else { nkeynes@87: cmd->status = GD_CMD_STATUS_ABORT; nkeynes@87: sh4r.r[0] = 0; nkeynes@87: } nkeynes@87: break; nkeynes@87: case 9: /* Reset */ nkeynes@87: break; nkeynes@87: case 10: /* Set mode */ nkeynes@87: sh4r.r[0] = 0; nkeynes@87: break; nkeynes@87: } nkeynes@87: break; nkeynes@87: case -1: /* Misc */ nkeynes@87: break; nkeynes@87: default: /* ??? */ nkeynes@87: break; nkeynes@87: } nkeynes@87: break; nkeynes@87: case 0xE0: /* Menu */ nkeynes@87: switch( sh4r.r[7] ) { nkeynes@87: case 0: nkeynes@87: WARN( "Entering main program" ); nkeynes@87: break; nkeynes@87: case 1: nkeynes@87: WARN( "Program aborted to DC menu"); nkeynes@87: dreamcast_stop(); nkeynes@87: break; nkeynes@87: } nkeynes@87: } nkeynes@87: }