MCUME/MCUME_teensy/teensygen/io.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);
}