diff options
Diffstat (limited to 'src/emu/machine/cr589.c')
-rw-r--r-- | src/emu/machine/cr589.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/emu/machine/cr589.c b/src/emu/machine/cr589.c new file mode 100644 index 00000000000..4ec39d35845 --- /dev/null +++ b/src/emu/machine/cr589.c @@ -0,0 +1,152 @@ +/* + * Matsushita CR-589 + * + */ + +#include "driver.h" +#include "cr589.h" + +typedef struct +{ + int download; + UINT8 buffer[ 65536 ]; + int bufferOffset; +} SCSICr589; + +static const int identity_offset = 0x3ab; +static const char *download_identity = "MATSHITA CD98Q4 DOWNLOADGS0N"; + +static int cr589_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode ) +{ + UINT8 *command; + int commandLength; + SCSICr589 *our_this = SCSIThis( &SCSIClassCr589, scsiInstance ); + SCSIGetCommand( scsiInstance, &command, &commandLength ); + + switch( command[ 0 ] ) + { + case 0x3b: // WRITE BUFFER + our_this->bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ]; + SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT ); + return ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ]; + + case 0x3c: // READ BUFFER + our_this->bufferOffset = ( command[ 3 ] << 16 ) | ( command[ 4 ] << 8 ) | command[ 5 ]; + SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN ); + return ( command[ 6 ] << 16 ) | ( command[ 7 ] << 8 ) | command[ 8 ]; + + case 0xcc: // FIRMWARE DOWNLOAD ENABLE + SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT ); + return SCSILengthFromUINT16( &command[7] ); + + default: + return SCSIBase( &SCSIClassCr589, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL ); + } +} + +static void cr589_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength ) +{ + UINT8 *command; + int commandLength; + SCSICr589 *our_this = SCSIThis( &SCSIClassCr589, scsiInstance ); + SCSIGetCommand( scsiInstance, &command, &commandLength ); + + switch( command[ 0 ] ) + { + case 0x12: // INQUIRY + SCSIBase( &SCSIClassCr589, SCSIOP_READ_DATA, scsiInstance, dataLength, data ); + + if( our_this->download ) + { + memcpy( &data[ 8 ], download_identity, 28 ); + } + else + { + memcpy( &data[ 8 ], &our_this->buffer[ identity_offset ], 28 ); + } + break; + + case 0x3c: // READ BUFFER + memcpy( data, &our_this->buffer[ our_this->bufferOffset ], dataLength ); + our_this->bufferOffset += dataLength; + break; + + default: + SCSIBase( &SCSIClassCr589, SCSIOP_READ_DATA, scsiInstance, dataLength, data ); + break; + } +} + +static void cr589_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength ) +{ + UINT8 *command; + int commandLength; + SCSICr589 *our_this = SCSIThis( &SCSIClassCr589, scsiInstance ); + SCSIGetCommand( scsiInstance, &command, &commandLength ); + + switch( command[ 0 ] ) + { + case 0x3b: // WRITE BUFFER + memcpy( &our_this->buffer[ our_this->bufferOffset ], data + 32, dataLength - 32 ); + our_this->bufferOffset += dataLength; + break; + + case 0xcc: // FIRMWARE DOWNLOAD ENABLE + if( memcmp( data, &our_this->buffer[ identity_offset ], 28 ) == 0 ) + { + our_this->download = 1; + } + else if( memcmp( data, download_identity, 28 ) == 0 ) + { + our_this->download = 0; + } + break; + + default: + SCSIBase( &SCSIClassCr589, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data ); + break; + } +} + +static void cr589_alloc_instance( SCSIInstance *scsiInstance, int diskId ) +{ + SCSICr589 *our_this = SCSIThis( &SCSIClassCr589, scsiInstance ); + + our_this->download = 0; + memcpy( &our_this->buffer[ identity_offset ], "MATSHITACD-ROM CR-589 GS0N", 28 ); + + state_save_register_item( "cr589", diskId, our_this->download ); + state_save_register_item_array( "cr589", diskId, our_this->buffer ); + state_save_register_item( "cr589", diskId, our_this->bufferOffset ); +} + +static int cr589_dispatch( int operation, void *file, INT64 intparm, void *ptrparm ) +{ + switch( operation ) + { + case SCSIOP_EXEC_COMMAND: + return cr589_exec_command( file, ptrparm ); + + case SCSIOP_READ_DATA: + cr589_read_data( file, ptrparm, intparm ); + return 0; + + case SCSIOP_WRITE_DATA: + cr589_write_data( file, ptrparm, intparm ); + return 0; + + case SCSIOP_ALLOC_INSTANCE: + SCSIBase( &SCSIClassCr589, operation, file, intparm, ptrparm ); + cr589_alloc_instance( *((SCSIInstance **) ptrparm), intparm ); + return 0; + } + + return SCSIBase( &SCSIClassCr589, operation, file, intparm, ptrparm ); +} + +SCSIClass SCSIClassCr589 = +{ + &SCSIClassCDROM, + cr589_dispatch, + sizeof( SCSICr589 ) +}; |