Starting a rewrite of how the IO works.

Currently 100% broken, also going to change how devices are selected
for each system so no more if/else everywhere and system should be more accurate.
This commit is contained in:
Godzil
2021-12-20 15:43:04 +00:00
parent 8fa2ef06ab
commit 6f56a8efda
33 changed files with 1017 additions and 699 deletions

View File

@@ -0,0 +1,9 @@
/*
* NewOswan
* buttons.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/

View File

@@ -0,0 +1,9 @@
/*
* NewOswan
* color_system.c: IO specific to the WonderSwan Color systems.
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/

View File

@@ -0,0 +1,36 @@
/*
* NewOswan
* debug.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/
#include <stdio.h>
#include <stdint.h>
extern uint8_t *ws_ioRam;
uint8_t debug_io_read(void *pdata, uint8_t port)
{
switch (port)
{
}
}
void debug_io_write(void *pdata, uint8_t port, uint8_t value)
{
switch (port)
{
case 0xF1:
printf("%d\n", (signed short)((value << 8) | ws_ioRam[0xF0]));
break;
case 0xF2:
printf("%c", value);
fflush(stdout);
break;
}
}

9
source/peripherals/dma.c Normal file
View File

@@ -0,0 +1,9 @@
/*
* NewOswan
* dma.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/

336
source/peripherals/eeprom.c Normal file
View File

@@ -0,0 +1,336 @@
/*
* NewOswan
* eeprom.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <memory.h>
#include <nec.h>
#include <log.h>
#include <gpu.h>
extern uint8_t *externalEeprom;
extern uint16_t *internalEeprom;
enum
{
EEPROM_SUBCOMMAND = 0, /* 00 00 */
EEPROM_WRITE, /* 01 xx */
EEPROM_READ, /* 10 xx */
EEPROM_ERASE, /* 11 xx */
EEPROM_WRITEDISABLE, /* 00 00 */
EEPROM_WRITEALL, /* 00 01 */
EEPROM_ERASEALL, /* 00 10 */
EEPROM_WRITEENABLE /* 00 11 */
};
char *eii_CommandName[] = {
"SUB", "WRI", "RED", "ERA", "WRD", "WRA", "ERL", "WRE",
};
uint8_t iee_WriteEnable = false;
uint16_t iee_SelAddress = 0;
uint16_t iee_Databuffer = 0;
uint8_t iee_Mode = EEPROM_READ;
uint8_t cee_WriteEnable = true;
uint16_t cee_SelAddress = 0;
uint16_t cee_Databuffer = 0;
uint8_t cee_Mode = EEPROM_READ;
// TODO: temporary
extern uint8_t *ws_ioRam;
uint8_t rs232_io_read(void *pdata, uint8_t port)
{
uint8_t retVal;
switch (port)
{
case 0xba: // eeprom even byte read
retVal = iee_Databuffer & 0x00FF;
break;
case 0xbb: // eeprom odd byte read
retVal = (iee_Databuffer & 0xFF00) >> 8;
break;
case 0xbe: // internal eeprom status/command register
// ack eeprom write
if (ws_ioRam[0xbe] & 0x20)
{
retVal = ws_ioRam[0xbe] | 2;
break;
}
// ack eeprom read
if (ws_ioRam[0xbe] & 0x10)
{
retVal = ws_ioRam[0xbe] | 1;
break;
}
// else ack both
retVal = ws_ioRam[0xbe] | 3;
break;
case 0xC8:
// ack eeprom write
if (ws_ioRam[0xbe] & 0x20)
{
retVal = ws_ioRam[0xbe] | 2;
break;
}
// ack eeprom read
if (ws_ioRam[0xbe] & 0x10)
{
retVal = ws_ioRam[0xbe] | 1;
break;
}
// else ack both
retVal = ws_ioRam[0xbe] | 3;
break;
case 0xC4: // eeprom even byte read
return cee_Databuffer & 0x00FF;
case 0xC5: // eeprom odd byte read
return (cee_Databuffer & 0xFF00) >> 8;
}
}
void rs232_io_write(void *pdata, uint8_t port, uint8_t value)
{
uint8_t retVal;
switch (port)
{
/* Internal EEPROM */
case 0xba: /* DATA Low */
iee_Databuffer = iee_Databuffer & 0xFF00;
iee_Databuffer = iee_Databuffer | (value);
break;
case 0xbb: /* Data High */
iee_Databuffer = iee_Databuffer & 0x00FF;
iee_Databuffer = iee_Databuffer | (value << 8);
break;
case 0xBC: /* Address Low */
case 0xBD: /* Address High */
break;
case 0xBE: /* Command / Status */
{
uint16_t address, command, subcmd;
iee_SelAddress = (ws_ioRam[0xBD] << 8) | ws_ioRam[0xBC];
if (ws_gpu_operatingInColor)
{
/*
13 00
S CCaa AAAA AAAA
0001 0011 0000 0000
*/
/* S CC aaAAAAAAAA */
command = (iee_SelAddress >> 10) & 0x3;
address = iee_SelAddress & 0x3FF;
subcmd = (iee_SelAddress >> 8) & 0x03;
}
else
{
/* S CC aaAAAA */
command = (iee_SelAddress >> 6) & 0x3;
address = iee_SelAddress & 0x3F;
subcmd = (iee_SelAddress >> 4) & 0x03;
}
if (command == EEPROM_SUBCOMMAND)
{
command = EEPROM_WRITEDISABLE + subcmd;
}
#ifdef EEPROM_DEBUG
printf("IEEP: RA:%04X RD:%04X A:%03X C:%s", iee_SelAddress, iee_Databuffer, address, eii_CommandName[command]);
#endif
if (value & 0x40)
{
/* Sub command */
#ifdef EEPROM_DEBUG
printf(" - Sub");
#endif
if (command == EEPROM_WRITEENABLE)
{
#ifdef EEPROM_DEBUG
printf(" Write Enable\n");
#endif
iee_WriteEnable = true;
}
else if (command == EEPROM_WRITEDISABLE)
{
#ifdef EEPROM_DEBUG
printf(" Write Disable\n");
#endif
iee_WriteEnable = false;
}
else if (command == EEPROM_ERASEALL)
{
#ifdef EEPROM_DEBUG
printf(" Erase All\n");
#endif
if (ws_gpu_operatingInColor)
{
memset(internalEeprom, 0, COLOR_IEEPROM_SIZE);
}
else
{
memset(internalEeprom, 0, BW_IEEPROM_SIZE);
}
}
#ifdef EEPROM_DEBUG
else
{
printf(" Write All?\n");
}
#endif
}
else if (value & 0x20)
{
/* Write */
#ifdef EEPROM_DEBUG
printf(" - Write?");
#endif
if (iee_WriteEnable)
{
#ifdef EEPROM_DEBUG
printf(" Yes : %04X\n", iee_Databuffer);
#endif
internalEeprom[address] = iee_Databuffer;
}
#ifdef EEPROM_DEBUG
else
{
printf(" No\n");
}
#endif
}
else if (value & 0x10)
{
/* Read */
#ifdef EEPROM_DEBUG
printf(" - Read");
#endif
iee_Databuffer = internalEeprom[address];
#ifdef EEPROM_DEBUG
printf(" Data : %04X\n", iee_Databuffer);
#endif
}
#ifdef EEPROM_DEBUG
else
{
printf(" Unknown value: %02X\n", value);
}
#endif
fflush(stdout);
}
break;
/* Cart EEPROM */
case 0xC4: /* Data High */
cee_Databuffer = cee_Databuffer & 0xFF00;
cee_Databuffer = cee_Databuffer | (value);
break;
case 0xC5: /* Data High */
cee_Databuffer = cee_Databuffer & 0x00FF;
cee_Databuffer = cee_Databuffer | (value << 8);
break;
case 0xC6: /* Address Low */
case 0xC7: /* Address High */
break;
case 0xC8: /* Command / Status */
{
uint16_t address, command, subcmd; /*, start;*/
cee_SelAddress = (ws_ioRam[0xBD] << 8) | ws_ioRam[0xBC];
/* S CC aaAAAA */
command = (cee_SelAddress >> 6) & 0x3;
address = cee_SelAddress & 0x3F;
subcmd = (cee_SelAddress >> 4) & 0x03;
if (command == EEPROM_SUBCOMMAND)
{
command = EEPROM_WRITEDISABLE + subcmd;
}
printf("CEEP: RA:%04X RD:%04X A:%03X C:%s", cee_SelAddress, cee_Databuffer, address, eii_CommandName[command]);
if (value & 0x40)
{
/* Sub command */
printf(" - Sub");
if (command == EEPROM_WRITEENABLE)
{
printf(" Write Enable\n");
cee_WriteEnable = true;
}
else if (command == EEPROM_WRITEDISABLE)
{
printf(" Write Disable\n");
cee_WriteEnable = false;
}
else if (command == EEPROM_ERASEALL)
{
printf(" Erase All\n");
/* Nothing here at the moment */
}
else
{
printf(" Write All?\n");
}
}
else if (value & 0x20)
{
/* Write */
printf(" - Write?");
if (cee_WriteEnable)
{
printf(" Yes : %04X\n", cee_Databuffer);
externalEeprom[address] = cee_Databuffer;
}
else
{
printf(" No\n");
}
}
else if (value & 0x10)
{
/* Read */
printf(" - Read");
cee_Databuffer = externalEeprom[address];
printf(" Data : %04X\n", cee_Databuffer);
}
else
{
printf(" Unknown value: %02X@", value);
}
fflush(stdout);
}
break;
case 0xCB:
break;
}
}

View File

@@ -0,0 +1,9 @@
/*
* NewOswan
* mono_system.c: IOs specific to the original WonderSwan
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/

230
source/peripherals/rs232.c Normal file
View File

@@ -0,0 +1,230 @@
/*
* NewOswan
* rs232.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/
#include <stdio.h>
#include <stdint.h>
#include <unistd.h> /* UNIX standard function definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/mman.h>
#include <fcntl.h>
#include <nec.h>
#include <log.h>
/* Temporary */
extern uint8_t *ws_ioRam;
/* Serial port */
#define BDR_9600 (0)
#define BDR_38400 (1)
#define SERIAL_PORT "/dev/tty.USA19H141P1.1"
static int serialfd = -1;
static int serial_have_data = 0;
static unsigned char serial_data = 0;
static int serial_speed = BDR_9600;
static void open_serial()
{
if (serialfd < 0)
{
serialfd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
//set_baudrate(serial_speed);
serial_have_data = 0;
}
}
static void set_baudrate(int speed)
{
struct termios options;
if (serialfd < 0)
{
return;
}
tcgetattr(serialfd, &options);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
if (speed == BDR_9600)
{
cfsetispeed(&options, B9600);
}
else
{
cfsetospeed(&options, B38400);
}
#if 0
options.c_cflag &= ~CNEW_RTSCTS;
#else
options.c_cflag &= ~CRTSCTS;
#endif
options.c_cflag |= (CLOCAL | CREAD);
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
tcsetattr(serialfd, TCSANOW, &options);
/* Make sure read is not blocking */
fcntl(serialfd, F_SETFL, FNDELAY);
}
static void close_serial()
{
close(serialfd);
serialfd = -1;
}
static void check_serial_data()
{
unsigned char buf[10];
int f;
if (serialfd < 0)
{
return;
}
if (serial_have_data == 0)
{
f = read(serialfd, buf, 1);
if (f > 0)
{
Log(TLOG_DEBUG, "serial", "Have data from serial [%d]!", f);
fflush(stdout);
serial_have_data = 0x01;
serial_data = buf[0];
}
}
if (serial_have_data > 0)
{
/* Gen an int if enabled */
if (ws_ioRam[0xB2] & 0x04)
{
ws_ioRam[0xb6] &= ~0x04;
Log(TLOG_DEBUG, "serial", "SERIAL INNNNNTTTT!!!!!!!");
nec_int((ws_ioRam[0xb0] + 3) * 4);
}
}
}
static unsigned char read_serial()
{
unsigned char buf[10];
int f;
if (serialfd < 0)
{
return 0xFF;
}
if (serial_have_data > 0)
{
serial_have_data = 0;
return serial_data;
}
f = read(serialfd, buf, 1);
if (f == 1)
{
return buf[0];
}
return 0x42;
}
static void write_serial(unsigned char value)
{
if (serialfd < 0)
{
return;
}
write(serialfd, &value, 1);
}
uint8_t rs232_io_read(void *pdata, uint8_t port)
{
uint8_t retVal;
switch(port)
{
case 0xB1:
retVal = read_serial();
Log(TLOG_DEBUG, "serial", "Read %02X", retVal);
goto exit;
case 0xB3:
check_serial_data();
if (ws_ioRam[0xB3] & 0x80)
{
retVal = (ws_ioRam[0xB3] & ~1) | serial_have_data | 0x04;
}
else
{
retVal = 0x00;
}
Log(TLOG_DEBUG, "serial", "<<<<RS232STA: %02X [%c%c%cxx%c%c%c]", retVal, (retVal & 0x80) ? 'E' : 'd',
(retVal & 0x40) ? '3' : '9', (retVal & 0x20) ? 'R' : 'n', (retVal & 0x04) ? 'E' : 'f',
(retVal & 0x02) ? 'V' : 'n', (retVal & 0x01) ? 'D' : 'e');
goto exit;
}
exit:
return retVal;
}
void rs232_io_write(void *pdata, uint8_t port, uint8_t value)
{
switch(port)
{
case 0xB1:
write_serial(value);
break;
case 0xB3:
Log(TLOG_DEBUG, "serial", ">>>>RS232STA: %02X [%c%c%cxx%c%c%c]", value, (value & 0x80) ? 'E' : 'd', (value & 0x40) ? '3' : '9',
(value & 0x20) ? 'R' : 'n', (value & 0x04) ? 'E' : 'f', (value & 0x02) ? 'V' : 'n',
(value & 0x01) ? 'D' : 'e');
/* Serial status: 7 = Enable, 6 = baudrate, 5 = Overrun reset
2 = Send Buffer empty
1 = Overrun
0 = Data Received
*/
serial_speed = ((value & 040) == 0x00) ? BDR_9600 : BDR_38400;
if ((value & 0x80) == 0x80)
{
open_serial();
set_baudrate(serial_speed);
check_serial_data();
}
break;
}
}
void rs232_init()
{
}

94
source/peripherals/rtc.c Normal file
View File

@@ -0,0 +1,94 @@
/*
* NewOswan
* rtc.c:
*
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/
#include <stdint.h>
static int rtcDataRegisterReadCount = 0;
uint8_t rtc_io_read(void *pdata, uint8_t port)
{
case (port)
{
case 0xca : // RTC Command and status register
// set ack to always 1
retVal = (ws_ioRam[0xca] | 0x80);
goto exit;
case 0xcb : // RTC data register
if (ws_ioRam[0xca] == 0x15) // get time command
{
struct tm *newtime;
time_t long_time;
time(&long_time);
newtime = localtime(&long_time);
#define BCD(value) ((value/10)<<4)|(value%10)
switch (rtcDataRegisterReadCount)
{
case 0:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_year - 100);
goto exit;
case 1:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_mon);
goto exit;
case 2:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_mday);
goto exit;
case 3:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_wday);
goto exit;
case 4:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_hour);
goto exit;
case 5:
rtcDataRegisterReadCount++;
retVal = BCD(newtime->tm_min);
goto exit;
case 6:
rtcDataRegisterReadCount = 0;
retVal = BCD(newtime->tm_sec);
goto exit;
}
return 0;
}
else
{
// set ack
retVal = (ws_ioRam[0xcb] | 0x80);
goto exit;
}
}
}
void rtc_io_write(void *pdata, uint8_t port, uint8_t value)
{
switch(port)
{
case 0xca:
if (value == 0x15)
{
rtcDataRegisterReadCount = 0;
}
break;
}
}

View File

@@ -0,0 +1,9 @@
/*
* NewOswan
* universal_luxor.c: Implement a "universal" version of both known version of Luxor (Bandai 2001 and Bandai 2003)
* as there is no way from the ROM to really know which version is on the original cart.
* Created by Manoël Trapier on 19/12/2021.
* Copyright (c) 2014-2021 986-Studio. All rights reserved.
*
*/