kopia lustrzana https://github.com/Jean-MarcHarvengt/MCUME
187 wiersze
5.2 KiB
C
187 wiersze
5.2 KiB
C
/*
|
|
io.c
|
|
I/O controller chip emulation
|
|
*/
|
|
|
|
#include "shared.h"
|
|
|
|
port_t port[3];
|
|
uint8 io_reg[0x10];
|
|
|
|
|
|
void io_reset(void)
|
|
{
|
|
/* I/O register default settings */
|
|
uint8 io_def[0x10] =
|
|
{
|
|
0xA0,
|
|
0x7F, 0x7F, 0x7F,
|
|
0x00, 0x00, 0x00,
|
|
0xFF, 0x00, 0x00,
|
|
0xFF, 0x00, 0x00,
|
|
0xFB, 0x00, 0x00,
|
|
};
|
|
|
|
/* Initialize I/O registers */
|
|
memcpy(io_reg, io_def, 0x10);
|
|
|
|
/*
|
|
Port A : 3B pad
|
|
Port B : Unused
|
|
Port C : Unused
|
|
*/
|
|
port[0].data_w = device_3b_w;
|
|
port[0].data_r = device_3b_r;
|
|
port[1].data_w = NULL;
|
|
port[1].data_r = NULL;
|
|
port[2].data_w = NULL;
|
|
port[2].data_r = NULL;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* I/O chip functions */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
void gen_io_w(int offset, int value)
|
|
{
|
|
switch(offset)
|
|
{
|
|
case 0x01: /* Port A Data */
|
|
value = ((value & 0x80) | (value & io_reg[offset+3]));
|
|
io_reg[offset] = value;
|
|
if(port[0].data_w) port[0].data_w(value);
|
|
return;
|
|
|
|
case 0x02: /* Port B Data */
|
|
value = ((value & 0x80) | (value & io_reg[offset+3]));
|
|
io_reg[offset] = value;
|
|
if(port[1].data_w) port[1].data_w(value);
|
|
return;
|
|
|
|
case 0x03: /* Port C Data */
|
|
value = ((value & 0x80) | (value & io_reg[offset+3]));
|
|
io_reg[offset] = value;
|
|
if(port[2].data_w) port[2].data_w(value);
|
|
return;
|
|
|
|
case 0x04: /* Port A Ctrl */
|
|
case 0x05: /* Port B Ctrl */
|
|
case 0x06: /* Port C Ctrl */
|
|
io_reg[offset] = value & 0xFF;
|
|
break;
|
|
|
|
case 0x07: /* Port A TxData */
|
|
case 0x0A: /* Port B TxData */
|
|
case 0x0D: /* Port C TxData */
|
|
io_reg[offset] = value;
|
|
break;
|
|
|
|
case 0x09: /* Port A S-Ctrl */
|
|
case 0x0C: /* Port B S-Ctrl */
|
|
case 0x0F: /* Port C S-Ctrl */
|
|
io_reg[offset] = (value & 0xF8);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int gen_io_r(int offset)
|
|
{
|
|
uint8 temp;
|
|
uint8 has_scd = 0x20; /* No Sega CD unit attached */
|
|
uint8 gen_ver = 0x00; /* Version 0 hardware */
|
|
|
|
switch(offset)
|
|
{
|
|
case 0x00: /* Version */
|
|
switch(rom_version())
|
|
{
|
|
case 'J':
|
|
temp = 0x00;
|
|
break;
|
|
case 'U':
|
|
temp = 0x80;
|
|
break;
|
|
case 'E':
|
|
temp = 0xC0;
|
|
break;
|
|
case 'A':
|
|
temp = 0xC0;
|
|
break;
|
|
case 'B':
|
|
temp = 0xC0;
|
|
break;
|
|
case '4':
|
|
temp = 0x80;
|
|
break;
|
|
default:
|
|
temp = 0x80;
|
|
break;
|
|
}
|
|
return (temp | has_scd | gen_ver);
|
|
break;
|
|
|
|
case 0x01: /* Port A Data */
|
|
if(port[0].data_r) return ((io_reg[offset] & 0x80) | port[0].data_r());
|
|
return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
|
|
|
|
case 0x02: /* Port B Data */
|
|
if(port[1].data_r) return ((io_reg[offset] & 0x80) | port[1].data_r());
|
|
return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
|
|
|
|
case 0x03: /* Port C Data */
|
|
if(port[2].data_r) return ((io_reg[offset] & 0x80) | port[2].data_r());
|
|
return (io_reg[offset] | ((~io_reg[offset+3]) & 0x7F));
|
|
}
|
|
|
|
return (io_reg[offset]);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
/* Input callbacks */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
uint8 pad_2b_r(void)
|
|
{
|
|
uint8 temp = 0x3F;
|
|
if(input.pad[0] & INPUT_UP) temp &= ~0x01;
|
|
if(input.pad[0] & INPUT_DOWN) temp &= ~0x02;
|
|
if(input.pad[0] & INPUT_LEFT) temp &= ~0x04;
|
|
if(input.pad[0] & INPUT_RIGHT) temp &= ~0x08;
|
|
if(input.pad[0] & INPUT_B) temp &= ~0x10;
|
|
if(input.pad[0] & INPUT_C) temp &= ~0x20;
|
|
return (temp);
|
|
}
|
|
|
|
static int th = 0;
|
|
|
|
uint8 device_3b_r(void)
|
|
{
|
|
uint8 temp = 0x3F;
|
|
|
|
if(th)
|
|
{
|
|
temp = 0x3f;
|
|
if(input.pad[0] & INPUT_UP) temp &= ~0x01;
|
|
if(input.pad[0] & INPUT_DOWN) temp &= ~0x02;
|
|
if(input.pad[0] & INPUT_LEFT) temp &= ~0x04;
|
|
if(input.pad[0] & INPUT_RIGHT) temp &= ~0x08;
|
|
if(input.pad[0] & INPUT_B) temp &= ~0x10;
|
|
if(input.pad[0] & INPUT_C) temp &= ~0x20;
|
|
return (temp | 0x40);
|
|
}
|
|
else
|
|
{
|
|
temp = 0x33;
|
|
if(input.pad[0] & INPUT_UP) temp &= ~0x01;
|
|
if(input.pad[0] & INPUT_DOWN) temp &= ~0x02;
|
|
if(input.pad[0] & INPUT_A) temp &= ~0x10;
|
|
if(input.pad[0] & INPUT_START) temp &= ~0x20;
|
|
return (temp);
|
|
}
|
|
}
|
|
|
|
void device_3b_w(uint8 data)
|
|
{
|
|
th = (data & 0x40);
|
|
}
|