ref: 9edd01be58e6cb0fd023e396d560a142dddeb0c4
parent: 447b748dee0431007c9ec8899da38768060232e1
author: allkern <lisandroaalarcon@gmail.com>
date: Mon Sep 25 21:26:12 EDT 2023
Initial MCD implementation
--- a/.gitignore
+++ b/.gitignore
@@ -18,4 +18,5 @@
*.toml
*.zip
*.cue
-*.iso
\ No newline at end of file
+*.iso
+*.mcd
\ No newline at end of file
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -67,7 +67,8 @@
psxi_sda_init(controller, SDA_MODEL_DIGITAL);
psxi_sda_init_input(controller, input);
- psx_pad_init_slot(psx->pad, 0, input);
+ psx_pad_attach_joy(psx->pad, 0, input);
+ psx_pad_attach_mcd(psx->pad, 0, "slot1.mcd");
if (cfg->exe) { while (psx->cpu->pc != 0x80030000) {@@ -95,9 +96,9 @@
log_fatal("gp=%08x sp=%08x fp=%08x ra=%08x", cpu->r[28], cpu->r[29], cpu->r[30], cpu->r[31]); log_fatal("pc=%08x hi=%08x lo=%08x ep=%08x", cpu->pc, cpu->hi, cpu->lo, cpu->cop0_r[COP0_EPC]);- psx_input_destroy(input);
+ psx_pad_detach_joy(psx->pad, 0);
psx_destroy(psx);
- psxi_sda_destroy(controller);
+ //psxi_sda_destroy(controller);
psxe_screen_destroy(screen);
return 0;
--- a/psx/dev/input.c
+++ b/psx/dev/input.c
@@ -35,6 +35,7 @@
}
void psx_input_destroy(psx_input_t* input) {+ free(input->udata);
free(input);
}
--- /dev/null
+++ b/psx/dev/mcd.c
@@ -1,0 +1,130 @@
+#include "mcd.h"
+#include "../log.h"
+
+psx_mcd_t* psx_mcd_create() {+ return (psx_mcd_t*)malloc(sizeof(psx_mcd_t));
+}
+
+void psx_mcd_init(psx_mcd_t* mcd, const char* path) {+ memset(mcd, 0, sizeof(psx_mcd_t));
+
+ mcd->state = MCD_STATE_TX_HIZ;
+ mcd->flag = 0x08;
+ mcd->path = path;
+ mcd->buf = malloc(MCD_MEMORY_SIZE);
+
+ memset(mcd->buf, 0, MCD_MEMORY_SIZE);
+
+ if (!path)
+ return;
+
+ FILE* file = fopen(path, "rb");
+
+ if (!file)
+ return;
+
+ fread(mcd->buf, 1, MCD_MEMORY_SIZE, file);
+
+ fclose(file);
+}
+
+uint8_t psx_mcd_read(psx_mcd_t* mcd) {+ switch (mcd->state) {+ case MCD_STATE_TX_HIZ: mcd->tx_data = 0xff; break;
+ case MCD_STATE_TX_FLG: mcd->tx_data = mcd->flag; break;
+ case MCD_STATE_TX_ID1: mcd->tx_data = 0x5a; break;
+ case MCD_STATE_TX_ID2: {+ mcd->tx_data_ready = 1;
+ mcd->tx_data = 0x5d;
+
+ switch (mcd->mode) {+ case 'R': mcd->state = MCD_R_STATE_RX_MSB; break;
+ case 'W': mcd->state = MCD_W_STATE_RX_MSB; break;
+ case 'S': mcd->state = MCD_S_STATE_TX_ACK1; break;
+ }
+
+ // log_set_quiet(0);
+ // log_fatal("mcd read %02x", mcd->tx_data);+ // log_set_quiet(1);
+
+ return mcd->tx_data;
+ } break;
+
+ // Read states
+ case MCD_R_STATE_RX_MSB: mcd->tx_data = 0x00; break;
+ case MCD_R_STATE_RX_LSB: mcd->tx_data = mcd->msb; break;
+ case MCD_R_STATE_TX_ACK1: mcd->tx_data = 0x5c; break;
+ case MCD_R_STATE_TX_ACK2: mcd->tx_data = 0x5d; break;
+ case MCD_R_STATE_TX_MSB: mcd->tx_data = mcd->msb; mcd->checksum = mcd->msb; break;
+ case MCD_R_STATE_TX_LSB: mcd->tx_data = mcd->lsb; mcd->checksum ^= mcd->lsb;
+ mcd->pending_bytes = 128; break;
+ case MCD_R_STATE_TX_DATA: {+ --mcd->pending_bytes;
+
+ uint8_t data = mcd->buf[mcd->addr++];
+
+ mcd->checksum ^= data;
+
+ if (!mcd->pending_bytes) {+ mcd->tx_data = data;
+
+ break;
+ }
+
+ // log_set_quiet(0);
+ // log_fatal("mcd read %02x", data);+ // log_set_quiet(1);
+
+ return data;
+ } break;
+ case MCD_R_STATE_TX_CHK: mcd->tx_data = mcd->checksum; break;
+ case MCD_R_STATE_TX_MEB: {+ mcd->tx_data_ready = 0;
+ mcd->state = MCD_STATE_TX_HIZ;
+
+ // log_set_quiet(0);
+ // log_fatal("mcd read %02x", 'G');+ // log_set_quiet(1);
+
+ return 'G';
+ } break;
+ }
+
+ mcd->tx_data_ready = 1;
+ mcd->state++;
+
+ // log_set_quiet(0);
+ // log_fatal("mcd read %02x", mcd->tx_data);+ // log_set_quiet(1);
+
+ return mcd->tx_data;
+}
+
+void psx_mcd_write(psx_mcd_t* mcd, uint8_t data) {+ // log_set_quiet(0);
+ // log_fatal("mcd write %02x", data);+ // log_set_quiet(1);
+
+ switch (mcd->state) {+ case MCD_STATE_TX_FLG: mcd->mode = data; break;
+ case MCD_R_STATE_RX_MSB: mcd->msb = data; break;
+ case MCD_R_STATE_RX_LSB: {+ mcd->lsb = data;
+ mcd->addr = ((mcd->msb << 8) | mcd->lsb) << 7;
+ } break;
+ }
+}
+
+int psx_mcd_query(psx_mcd_t* mcd) {+ return mcd->tx_data_ready;
+}
+
+void psx_mcd_destroy(psx_mcd_t* mcd) {+ FILE* file = fopen(mcd->path, "wb");
+
+ fwrite(mcd->buf, 1, MCD_MEMORY_SIZE, file);
+ fclose(file);
+
+ free(mcd->buf);
+ free(mcd);
+}
\ No newline at end of file
--- /dev/null
+++ b/psx/dev/mcd.h
@@ -1,0 +1,62 @@
+#ifndef MCD_H
+#define MCD_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define MCD_MEMORY_SIZE 0x20000 // 128 KB
+
+enum {+ MCD_STATE_TX_HIZ = 0,
+ MCD_STATE_TX_FLG,
+ MCD_STATE_TX_ID1,
+ MCD_STATE_TX_ID2,
+ MCD_R_STATE_RX_MSB,
+ MCD_R_STATE_RX_LSB,
+ MCD_R_STATE_TX_ACK1,
+ MCD_R_STATE_TX_ACK2,
+ MCD_R_STATE_TX_MSB,
+ MCD_R_STATE_TX_LSB,
+ MCD_R_STATE_TX_DATA,
+ MCD_R_STATE_TX_CHK,
+ MCD_R_STATE_TX_MEB,
+ MCD_W_STATE_RX_MSB,
+ MCD_W_STATE_RX_LSB,
+ MCD_W_STATE_RX_DATA,
+ MCD_W_STATE_RX_CHK,
+ MCD_W_STATE_TX_ACK1,
+ MCD_W_STATE_TX_ACK2,
+ MCD_W_STATE_TX_MEB,
+ MCD_S_STATE_TX_ACK1,
+ MCD_S_STATE_TX_ACK2,
+ MCD_S_STATE_TX_DAT0,
+ MCD_S_STATE_TX_DAT1,
+ MCD_S_STATE_TX_DAT2,
+ MCD_S_STATE_TX_DAT3
+};
+
+typedef struct {+ const char* path;
+ uint8_t* buf;
+ uint8_t flag;
+ uint16_t msb;
+ uint16_t lsb;
+ uint16_t addr;
+ int pending_bytes;
+ char mode;
+ int state;
+ uint8_t tx_data;
+ int tx_data_ready;
+ uint8_t checksum;
+} psx_mcd_t;
+
+psx_mcd_t* psx_mcd_create();
+void psx_mcd_init(psx_mcd_t*, const char*);
+uint8_t psx_mcd_read(psx_mcd_t*);
+void psx_mcd_write(psx_mcd_t*, uint8_t);
+int psx_mcd_query(psx_mcd_t*);
+void psx_mcd_destroy(psx_mcd_t*);
+
+#endif
\ No newline at end of file
--- a/psx/dev/pad.c
+++ b/psx/dev/pad.c
@@ -6,28 +6,33 @@
#include "../log.h"
uint32_t pad_read_rx(psx_pad_t* pad) {- psx_input_t* current_slot = pad->slot[(pad->ctrl >> 13) & 1];
+ psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
+ psx_mcd_t* mcd = pad->mcd_slot[(pad->ctrl >> 13) & 1];
- if (!current_slot || !pad->dest)
+ if ((!(joy || mcd)) || !pad->dest)
return 0xffffffff;
- if ((pad->ctrl & CTRL_JOUT) || (pad->ctrl & CTRL_RXEN)) {- switch (pad->dest) {- case DEST_JOY: {- uint8_t data = current_slot->read_func(current_slot->udata);
+ if (!(pad->ctrl & CTRL_JOUT) && !(pad->ctrl & CTRL_RXEN))
+ return 0xffffffff;
- if (!current_slot->query_fifo_func(current_slot->udata))
- pad->dest = 0;
+ switch (pad->dest) {+ case DEST_JOY: {+ uint8_t data = joy->read_func(joy->udata);
- return data;
- } break;
+ if (!joy->query_fifo_func(joy->udata))
+ pad->dest = 0;
- case DEST_MCD: {+ return data;
+ } break;
+
+ case DEST_MCD: {+ uint8_t data = psx_mcd_read(mcd);
+
+ if (!psx_mcd_query(mcd))
pad->dest = 0;
- /* To-do */
- } break;
- }
+ return data;
+ } break;
}
return 0xffffffff;
@@ -34,9 +39,10 @@
}
void pad_write_tx(psx_pad_t* pad, uint16_t data) {- psx_input_t* current_slot = pad->slot[(pad->ctrl >> 13) & 1];
+ psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
+ psx_mcd_t* mcd = pad->mcd_slot[(pad->ctrl >> 13) & 1];
- if (!current_slot || !(pad->ctrl & CTRL_TXEN))
+ if ((!(joy || mcd)) || !(pad->ctrl & CTRL_TXEN))
return;
pad->cycles_until_irq = 512;
@@ -47,29 +53,128 @@
} else { switch (pad->dest) { case DEST_JOY: {- current_slot->write_func(current_slot->udata, data);
+ joy->write_func(joy->udata, data);
- if (!current_slot->query_fifo_func(current_slot->udata))
+ if (!joy->query_fifo_func(joy->udata))
pad->dest = 0;
} break;
case DEST_MCD: {- pad->dest = 0;
+ psx_mcd_write(mcd, data);
- /* To-do */
+ if (!psx_mcd_query(mcd))
+ pad->dest = 0;
} break;
}
}
}
+// uint32_t pad_read_rx(psx_pad_t* pad) {+// // log_set_quiet(0);
+// // log_fatal("pad read dest=%02x, jout=%u, rxen=%u, slot=%u",+// // pad->dest,
+// // !!(pad->ctrl & CTRL_JOUT),
+// // !!(pad->ctrl & CTRL_RXEN),
+// // (pad->ctrl >> 13) & 1
+// // );
+// // log_set_quiet(1);
+
+// if (!pad->dest || !(pad->ctrl & CTRL_JOUT))
+// return 0xffffffff;
+
+// // if ((!(pad->ctrl & CTRL_JOUT)) && (!(pad->ctrl & CTRL_RXEN)))
+// // return 0xffffffff;
+
+// switch (pad->dest) {+// case DEST_JOY: {+// psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
+
+// if (!joy)
+// return 0xffffffff;
+
+// uint8_t data = joy->read_func(joy->udata);
+
+// if (!joy->query_fifo_func(joy->udata))
+// pad->dest = 0;
+
+// return data;
+// } break;
+
+// case DEST_MCD: {+// psx_mcd_t* mcd = pad->mcd_slot[(pad->ctrl >> 13) & 1];
+
+// if (!mcd)
+// return 0xffffffff;
+
+// uint8_t data = psx_mcd_read(mcd);
+
+// if (!psx_mcd_query(mcd))
+// pad->dest = 0;
+
+// return data;
+// } break;
+// }
+
+// return 0xffffffff;
+// }
+
+// void pad_write_tx(psx_pad_t* pad, uint16_t data) {+// if (!(pad->ctrl & CTRL_TXEN))
+// return;
+
+// if (!pad->joy_slot[(pad->ctrl >> 13) & 1])
+// return;
+
+// log_set_quiet(0);
+// log_fatal("pad write %02x", data);+// log_set_quiet(1);
+
+// if (!pad->dest) {+// if ((data == DEST_JOY) || (data == DEST_MCD))
+// pad->dest = data;
+
+// return;
+// }
+
+// switch (pad->dest) {+// case DEST_JOY: {+// psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
+
+// if (!joy)
+// return;
+
+// pad->cycles_until_irq = 512;
+
+// joy->write_func(joy->udata, data);
+
+// if (!joy->query_fifo_func(joy->udata))
+// pad->dest = 0;
+// } break;
+
+// case DEST_MCD: {+// psx_mcd_t* mcd = pad->mcd_slot[(pad->ctrl >> 13) & 1];
+
+// if (!mcd)
+// return;
+
+// pad->cycles_until_irq = 512;
+
+// psx_mcd_write(mcd, data);
+
+// if (!psx_mcd_query(mcd))
+// pad->dest = 0;
+// } break;
+// }
+// }
+
uint32_t pad_handle_stat_read(psx_pad_t* pad) {return 0x07;
- psx_input_t* current_slot = pad->slot[(pad->ctrl >> 13) & 1];
+ psx_input_t* joy = pad->joy_slot[(pad->ctrl >> 13) & 1];
- if (!current_slot)
+ if (!joy)
return 0x5 | pad->stat;
- return 0x5 | (current_slot->query_fifo_func(current_slot->udata) << 1);
+ return 0x5 | (joy->query_fifo_func(joy->udata) << 1);
}
void pad_handle_ctrl_write(psx_pad_t* pad, uint32_t value) {@@ -165,7 +270,7 @@
}
void psx_pad_button_press(psx_pad_t* pad, int slot, uint16_t data) {- psx_input_t* selected_slot = pad->slot[slot];
+ psx_input_t* selected_slot = pad->joy_slot[slot];
if (selected_slot)
selected_slot->on_button_press_func(selected_slot->udata, data);
@@ -172,16 +277,47 @@
}
void psx_pad_button_release(psx_pad_t* pad, int slot, uint16_t data) {- psx_input_t* selected_slot = pad->slot[slot];
+ psx_input_t* selected_slot = pad->joy_slot[slot];
if (selected_slot)
selected_slot->on_button_release_func(selected_slot->udata, data);
}
-void psx_pad_init_slot(psx_pad_t* pad, int slot, psx_input_t* input) {- pad->slot[slot] = input;
+void psx_pad_attach_joy(psx_pad_t* pad, int slot, psx_input_t* input) {+ if (pad->joy_slot[slot])
+ psx_pad_detach_joy(pad, slot);
+
+ pad->joy_slot[slot] = input;
}
+void psx_pad_detach_joy(psx_pad_t* pad, int slot) {+ if (!pad->joy_slot[slot])
+ return;
+
+ psx_input_destroy(pad->joy_slot[slot]);
+
+ pad->joy_slot[slot] = NULL;
+}
+
+void psx_pad_attach_mcd(psx_pad_t* pad, int slot, const char* path) {+ if (pad->mcd_slot[slot])
+ psx_pad_detach_mcd(pad, slot);
+
+ psx_mcd_t* mcd = psx_mcd_create();
+ psx_mcd_init(mcd, path);
+
+ pad->mcd_slot[slot] = mcd;
+}
+
+void psx_pad_detach_mcd(psx_pad_t* pad, int slot) {+ if (!pad->mcd_slot[slot])
+ return;
+
+ psx_mcd_destroy(pad->mcd_slot[slot]);
+
+ pad->mcd_slot[slot] = NULL;
+}
+
void psx_pad_update(psx_pad_t* pad, int cyc) { if (pad->cycles_until_irq) {pad->cycles_until_irq -= cyc;
@@ -195,5 +331,10 @@
}
void psx_pad_destroy(psx_pad_t* pad) {+ psx_pad_detach_joy(pad, 0);
+ psx_pad_detach_joy(pad, 1);
+ psx_pad_detach_mcd(pad, 0);
+ psx_pad_detach_mcd(pad, 1);
+
free(pad);
}
\ No newline at end of file
--- a/psx/dev/pad.h
+++ b/psx/dev/pad.h
@@ -5,6 +5,7 @@
#include "ic.h"
#include "input.h"
+#include "mcd.h"
#define PSX_PAD_BEGIN 0x1f801040
#define PSX_PAD_SIZE 0x10
@@ -115,7 +116,8 @@
uint32_t io_base, io_size;
psx_ic_t* ic;
- psx_input_t* slot[2];
+ psx_input_t* joy_slot[2];
+ psx_mcd_t* mcd_slot[2];
int enable_once;
int cycles_until_irq;
@@ -136,7 +138,10 @@
void psx_pad_destroy(psx_pad_t*);
void psx_pad_button_press(psx_pad_t*, int, uint16_t);
void psx_pad_button_release(psx_pad_t*, int, uint16_t);
-void psx_pad_init_slot(psx_pad_t*, int, psx_input_t*);
+void psx_pad_attach_joy(psx_pad_t*, int, psx_input_t*);
+void psx_pad_detach_joy(psx_pad_t*, int);
+void psx_pad_attach_mcd(psx_pad_t*, int, const char*);
+void psx_pad_detach_mcd(psx_pad_t*, int);
void psx_pad_update(psx_pad_t*, int);
#endif
\ No newline at end of file
--
⑨