--- /dev/null
+/*\r
+ FUJITSU FM16beta Emulator 'eFM16beta'\r
+\r
+ Author : Takeda.Toshiya\r
+ Date : 2017.12.28-\r
+\r
+ [ main system ]\r
+*/\r
+\r
+#include "main.h"\r
+#include "sub.h"\r
+#include "keyboard.h"\r
+#include "../disk.h"\r
+#include "../i8237.h"\r
+#include "../i8259.h"\r
+#ifdef HAS_I286\r
+#include "../i286.h"\r
+#endif\r
+#include "../mb8877.h"\r
+#include "../msm58321.h"\r
+#include "../pcm1bit.h"\r
+\r
+void MAIN::initialize()\r
+{\r
+ MEMORY::initialize();\r
+ \r
+ memset(ram, 0x00, sizeof(ram));\r
+ memset(rom, 0xff, sizeof(rom));\r
+ direct = 0;\r
+ \r
+ read_bios(_T("IPL.ROM"), rom, sizeof(rom));\r
+ \r
+ set_memory_rw(0x00000, 0xfbfff, ram);\r
+ set_memory_r(0xfc000, 0xfffff, rom);\r
+ \r
+ // main-sub\r
+// sub_busy = false;\r
+ \r
+ // 1mb fdd\r
+ sidereg_2hd = 0; // side 0\r
+ drvreg_2hd = 0; // drive #0, motor on\r
+ drq_2hd = false;\r
+ d_fdc_2hd->write_signal(SIG_MB8877_MOTOR, 1, 1);\r
+ d_fdc_2hd->write_signal(SIG_MB8877_DRIVEREG, 0, 3);\r
+ \r
+ // 320kb fdd\r
+ sidereg_2d = 0; // side 0\r
+ drvreg_2d = 0x80; // drive #0, motor on\r
+ drq_2d = false;\r
+ d_fdc_2d->write_signal(SIG_MB8877_MOTOR, 1, 1);\r
+ d_fdc_2d->write_signal(SIG_MB8877_DRIVEREG, 0, 3);\r
+ \r
+ // rtc\r
+ rtc_data = 0;\r
+ \r
+ // irq\r
+ irq_enb = ext_irq_enb = 0;\r
+ irq0_tx = irq0_rx = irq0_syn = irq1 = irq2 = irq3 = irq4 = irq5 = irq6 = irq7 = irq8 = irq9 = false;\r
+ firq0 = firq1 = firq2 = firq3 = false;\r
+ int0 = int1 = int2 = int3 = int4 = int5 = int6 = int7 = false;\r
+}\r
+\r
+void MAIN::release()\r
+{\r
+ MEMORY::release();\r
+}\r
+\r
+void MAIN::reset()\r
+{\r
+ MEMORY::reset();\r
+ \r
+#ifdef HAS_I286\r
+ d_dma->set_address_mask(0x000fffff);\r
+ d_cpu->set_address_mask(0x000fffff);\r
+ rst = 0x00;\r
+#endif\r
+ \r
+ \r
+ d_pcm->write_signal(SIG_PCM1BIT_ON, 0, 0);\r
+}\r
+\r
+void MAIN::write_io8(uint32_t addr, uint32_t data)\r
+{\r
+ uint8_t change;\r
+ \r
+ switch(addr) {\r
+ case 0x0020:\r
+ d_dma->write_signal(SIG_I8237_BANK0, data, 0xff);\r
+ break;\r
+ case 0x0021:\r
+ d_dma->write_signal(SIG_I8237_BANK1, data, 0xff);\r
+ break;\r
+ case 0x0022:\r
+ d_dma->write_signal(SIG_I8237_BANK2, data, 0xff);\r
+ break;\r
+ case 0x0023:\r
+ d_dma->write_signal(SIG_I8237_BANK3, data, 0xff);\r
+ break;\r
+\r
+\r
+#ifdef HAS_I286\r
+ case 0x0060:\r
+ if((data & 0xc0) == 0x40) {\r
+ d_cpu->reset();\r
+ rst |= 0x01;\r
+ }\r
+ if(data & 0x01) {\r
+ d_dma->set_address_mask(0x00ffffff);\r
+ d_cpu->set_address_mask(0x00ffffff);\r
+ } else {\r
+ d_dma->set_address_mask(0x000fffff);\r
+ d_cpu->set_address_mask(0x000fffff);\r
+ }\r
+ break;\r
+#endif\r
+ case 0xfd02:\r
+ change = irq_enb ^ data;\r
+ irq_enb = data;\r
+ if(change & 0x01) update_int7(); // Printer\r
+ if(change & 0x0e) update_int4(); // RS-232C\r
+ if(change & 0x10) update_int0(); // PTM\r
+ if(change & 0x20) update_int6(); // 320KB FDD\r
+ if(change & 0x80) update_int1(); // Keyboard\r
+ break;\r
+ case 0xfd03:\r
+ d_pcm->write_signal(SIG_PCM1BIT_ON, data, 0x80);\r
+ break;\r
+\r
+ case 0xfd04:\r
+ d_sub->write_signal(SIG_SUB_MAINACK, 1, 1);\r
+ break;\r
+\r
+ case 0xfd05:\r
+ d_sub->write_signal(SIG_SUB_HALT, data, 0x80);\r
+ d_sub->write_signal(SIG_SUB_CANCEL, data, 0x40);\r
+ break;\r
+\r
+ case 0xfd0f:\r
+ change = direct ^ data;\r
+ direct = data;\r
+ if(change & 0x80) {\r
+ if(direct & 0x80) {\r
+ set_memory_mapped_io_rw(0xc0000, 0xcffff, d_sub);\r
+ } else {\r
+ set_memory_rw(0xc0000, 0xcffff, ram + 0xc0000);\r
+ }\r
+ }\r
+ d_keyboard->write_signal(SIG_KEYBOARD_INSLED, data, 0x02);\r
+ break;\r
+ case 0xfd10:\r
+ d_rtc->write_signal(SIG_MSM58321_DATA, data, 0x0f);\r
+ break;\r
+ case 0xfd11:\r
+ d_rtc->write_signal(SIG_MSM58321_CS, data, 0x80);\r
+ d_rtc->write_signal(SIG_MSM58321_READ, data, 0x04);\r
+ d_rtc->write_signal(SIG_MSM58321_WRITE, data, 0x02);\r
+ d_rtc->write_signal(SIG_MSM58321_ADDR_WRITE, data, 0x01);\r
+ break;\r
+\r
+ case 0xfd1c:\r
+ d_fdc_2d->write_signal(SIG_MB8877_SIDEREG, data, 0x01);\r
+ sidereg_2d = data;\r
+ break;\r
+ case 0xfd1d:\r
+ d_fdc_2d->write_signal(SIG_MB8877_MOTOR, data, 0x80);\r
+ d_fdc_2d->write_signal(SIG_MB8877_DRIVEREG, data, 0x03);\r
+ drvreg_2d = data;\r
+ break;\r
+\r
+\r
+ case 0xfd2c:\r
+ change = ext_irq_enb ^ data;\r
+ ext_irq_enb = data;\r
+ if(change & 0x08) update_int2(); // 1MB FDD\r
+ break;\r
+\r
+ case 0xfd34:\r
+ d_fdc_2hd->write_signal(SIG_MB8877_SIDEREG, data, 0x01);\r
+ sidereg_2hd = data;\r
+ break;\r
+ case 0xfd35:\r
+ d_fdc_2hd->write_signal(SIG_MB8877_MOTOR, ~data, 0x80);\r
+ d_fdc_2hd->write_signal(SIG_MB8877_DRIVEREG, data, 0x03);\r
+ drvreg_2hd = data;\r
+ break;\r
+\r
+ }\r
+}\r
+\r
+uint32_t MAIN::read_io8(uint32_t addr)\r
+{\r
+ switch(addr) {\r
+#ifdef HAS_I286\r
+ case 0x0060:\r
+ {\r
+ uint8_t val = rst | (d_cpu->get_shutdown_flag() << 1);\r
+ rst = 0;\r
+ d_cpu->set_shutdown_flag(0);\r
+ return val;\r
+ }\r
+#endif\r
+ case 0xfd03:\r
+ return (irq8 ? 0x01 : 0) | (irq7 ? 0x02 : 0) | (irq4 ? 0x08 : 0) | (irq3 ? 0x10 : 0) | (irq2 ? 0x20 : 0) | (irq1 ? 0x40 : 0) | (irq0_tx || irq0_rx || irq0_syn ? 0x80 : 0);\r
+\r
+\r
+ case 0xfd04:\r
+ return (firq0 ? 0x01 : 0) | (firq1 ? 0x02 : 0) | (firq2 ? 0x80 : 0);\r
+\r
+ case 0xfd05:\r
+ return (sub_busy ? 0x80 : 0);\r
+\r
+ case 0xfd0f:\r
+ return direct;\r
+\r
+ case 0xfd10:\r
+ return rtc_data;\r
+\r
+ case 0xfd1c:\r
+ return sidereg_2d;\r
+ case 0xfd1d:\r
+ return drvreg_2d;\r
+ case 0xfd1f:\r
+ return (irq4 ? 0x40 : 0) | (drq_2d ? 0x80 : 0);\r
+\r
+ case 0xfd2c:\r
+ return (irq6 ? 0x04 : 0) | (irq5 ? 0x40 : 0);\r
+\r
+ case 0xfd34:\r
+ return sidereg_2hd;\r
+ case 0xfd35:\r
+ return drvreg_2hd;\r
+ case 0xfd36:\r
+ {\r
+ uint8_t val = 0x40; // DSNS=1\r
+ if(d_fdc_2hd->read_signal(SIG_MB8877_MOTOR)) {\r
+ for(int i = 0; i < 4; i++) {\r
+ if(d_fdc_2hd->is_disk_inserted(i)) {\r
+ val |= 1 << i;\r
+ }\r
+ }\r
+ }\r
+ DISK *disk = d_fdc_2hd->get_disk_handler(drvreg_2hd & 3);\r
+ if(disk->get_rpm() == 300) {\r
+ val |= 0x20;\r
+ }\r
+ if(disk->inserted && disk->two_side) {\r
+ val |= 0x80;\r
+ }\r
+ return val;\r
+ }\r
+ case 0xfd37:\r
+ return (irq5 ? 0x40 : 0) | (drq_2hd ? 0x80 : 0);\r
+\r
+// case 0xfda0:\r
+\r
+ }\r
+ return 0xff;\r
+}\r
+\r
+void MAIN::write_signal(int id, uint32_t data, uint32_t mask)\r
+{\r
+ if(id == SIG_MAIN_IRQ0_TX) {\r
+ irq0_tx = ((data & mask) != 0);\r
+ update_int4();\r
+ } else if(id == SIG_MAIN_IRQ0_RX) {\r
+ irq0_rx = ((data & mask) != 0);\r
+ update_int4();\r
+ } else if(id == SIG_MAIN_IRQ0_SYN) {\r
+ irq0_syn = ((data & mask) != 0);\r
+ update_int4();\r
+ } else if(id == SIG_MAIN_IRQ1) {\r
+ if(!(irq_enb & 0x80)) {\r
+ d_sub->write_signal(SIG_SUB_KEY, data, mask);\r
+ }\r
+ irq1 = ((data & mask) != 0);\r
+ update_int1();\r
+ } else if(id == SIG_MAIN_IRQ2) {\r
+ irq2 = ((data & mask) != 0);\r
+ update_int5();\r
+ } else if(id == SIG_MAIN_IRQ3) {\r
+ irq3 = ((data & mask) != 0); // dma\r
+// update_int*();\r
+ } else if(id == SIG_MAIN_IRQ4) {\r
+ irq4 = ((data & mask) != 0);\r
+ update_int6();\r
+ } else if(id == SIG_MAIN_IRQ5) {\r
+ irq5 = ((data & mask) != 0);\r
+ update_int2();\r
+ } else if(id == SIG_MAIN_IRQ6) {\r
+ irq6 = ((data & mask) != 0);\r
+ update_int2();\r
+ } else if(id == SIG_MAIN_IRQ7) {\r
+ irq7 = ((data & mask) != 0);\r
+ update_int6();\r
+ } else if(id == SIG_MAIN_IRQ8) {\r
+ irq8 = ((data & mask) != 0);\r
+ update_int0();\r
+ } else if(id == SIG_MAIN_IRQ9) {\r
+ irq9 = ((data & mask) != 0);\r
+ update_int5();\r
+ } else if(id == SIG_MAIN_FIRQ0) {\r
+ firq0 = ((data & mask) != 0);\r
+ update_int3();\r
+ } else if(id == SIG_MAIN_FIRQ1) {\r
+ firq1 = ((data & mask) != 0);\r
+ update_int1();\r
+ } else if(id == SIG_MAIN_FIRQ2) {\r
+ firq2 = ((data & mask) != 0);\r
+ update_int3();\r
+ } else if(id == SIG_MAIN_FIRQ3) {\r
+ firq3 = ((data & mask) != 0);\r
+ update_int3();\r
+ } else if(id == SIG_MAIN_SUB_BUSY) {\r
+ sub_busy = ((data & mask) != 0);\r
+\r
+this->out_debug_log(_T("SUB -> MAIN: SUB BUSY = %d\n"), sub_busy);\r
+\r
+ } else if(id == SIG_MAIN_DRQ_2HD) {\r
+ drq_2hd = ((data & mask) != 0);\r
+ } else if(id == SIG_MAIN_DRQ_2D) {\r
+ drq_2d = ((data & mask) != 0);\r
+ } else if(id == SIG_MAIN_RTC_DATA) {\r
+ rtc_data = (data & mask) | (rtc_data & ~mask);\r
+ } else if(id == SIG_MAIN_RTC_BUSY) {\r
+ rtc_data = (data & mask) | (rtc_data & ~mask);\r
+ }\r
+}\r
+\r
+/*\r
+IRQ8 -> INT0\r
+ IRQ8: \83^\83C\83}\81[\r
+IRQ1 + FIRQ1 -> INT1\r
+ IRQ1: \83L\81[\83{\81[\83h\r
+ FIRQ1: BREAK\83L\81[\r
+IRQ5 + IRQ6 -> INT2\r
+ IRQ5: IMB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N\r
+ IRQ6: \83n\81[\83h\83f\83B\83X\83N\r
+FIRQ0 + FIRQ2 + FIRQ3 -> INT3\r
+ FIRQ0: SUB\83A\83e\83\93\83V\83\87\83\93\r
+ FIRQ2: \8ag\92£\r
+ FIRQ3: \83\86\81[\83U\97p\r
+IRQ0 -> INT4\r
+ IRQ0: RS-232C\r
+IRQ2 + IRQ9 + INTNDP -> INT5\r
+ IRQ2: \8ag\92£\r
+ IRQ9: \83\86\81[\83U\97p\r
+IRQ4 -> INT6\r
+ IRQ4: 320KB\83t\83\8d\83b\83s\83B\83f\83B\83X\83N\r
+IRQ7 -> INT7\r
+ IRQ7: \83v\83\8a\83\93\83^\r
+*/\r
+\r
+void MAIN::update_int0()\r
+{\r
+// bool prev = int0;\r
+ int0 = (irq8 && (irq_enb & 0x10));\r
+// if(prev != int0) {\r
+ d_pic->write_signal(SIG_I8259_IR0, int0 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+void MAIN::update_int1()\r
+{\r
+// bool prev = int1;\r
+ int1 = (irq1 && (irq_enb & 0x80)) || firq1;\r
+// if(prev != int1) {\r
+ d_pic->write_signal(SIG_I8259_IR1, int1 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+void MAIN::update_int2()\r
+{\r
+// bool prev = int2;\r
+ int2 = (irq5 && (ext_irq_enb & 0x08)) || irq6;\r
+// if(prev != int2) {\r
+ d_pic->write_signal(SIG_I8259_IR2, int2 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+void MAIN::update_int3()\r
+{\r
+// bool prev = int3;\r
+ int3 = firq0 || firq2 || firq3;\r
+// if(prev != int3) {\r
+ d_pic->write_signal(SIG_I8259_IR3, int3 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+void MAIN::update_int4()\r
+{\r
+// bool prev = int4;\r
+ int4 = (irq0_tx && (irq_enb & 0x02)) || (irq0_rx && (irq_enb & 0x04)) || (irq0_syn && (irq_enb & 0x08));\r
+// if(prev != int4) {\r
+ d_pic->write_signal(SIG_I8259_IR4, int4 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+void MAIN::update_int5()\r
+{\r
+// bool prev = int5;\r
+ int5 = irq2 || irq9;\r
+// if(prev != int5) {\r
+ d_pic->write_signal(SIG_I8259_IR5, int5 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+void MAIN::update_int6()\r
+{\r
+// bool prev = int6;\r
+ int6 = (irq6 && (irq_enb & 0x20));\r
+// if(prev != int6) {\r
+ d_pic->write_signal(SIG_I8259_IR6, int6 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+void MAIN::update_int7()\r
+{\r
+// bool prev = int7;\r
+ int7 = irq7 && (irq_enb & 0x01);\r
+// if(prev != int7) {\r
+ d_pic->write_signal(SIG_I8259_IR7, int7 ? 1 : 0, 1);\r
+// }\r
+}\r
+\r
+#define STATE_VERSION 1\r
+\r
+bool MAIN::process_state(FILEIO* state_fio, bool loading)\r
+{\r
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {\r
+ return false;\r
+ }\r
+ if(!state_fio->StateCheckInt32(this_device_id)) {\r
+ return false;\r
+ }\r
+ return true;\r
+}\r
+\r
--- /dev/null
+/*\r
+ FUJITSU FM16beta Emulator 'eFM16beta'\r
+\r
+ Author : Takeda.Toshiya\r
+ Date : 2017.12.28-\r
+\r
+ [ main system ]\r
+*/\r
+\r
+#ifndef _MAIN_H_\r
+#define _MAIN_H_\r
+\r
+#include "../memory.h"\r
+\r
+#define SIG_MAIN_IRQ0_TX 0 // RS-232C\r
+#define SIG_MAIN_IRQ0_RX 1 // RS-232C\r
+#define SIG_MAIN_IRQ0_SYN 2 // RS-232C\r
+#define SIG_MAIN_IRQ1 3 // Keyboard\r
+#define SIG_MAIN_IRQ2 4 // Expantion\r
+#define SIG_MAIN_IRQ3 5 // DMA Controller\r
+#define SIG_MAIN_IRQ4 6 // 320KB Floppy Disk\r
+#define SIG_MAIN_IRQ5 7 // 1MB Floppy Disk\r
+#define SIG_MAIN_IRQ6 8 // Hard Disk\r
+#define SIG_MAIN_IRQ7 9 // Printer\r
+#define SIG_MAIN_IRQ8 10 // PTM\r
+#define SIG_MAIN_IRQ9 11 // User\r
+#define SIG_MAIN_FIRQ0 12 // Sub system attention\r
+#define SIG_MAIN_FIRQ1 13 // Break\r
+#define SIG_MAIN_FIRQ2 14 // Expantion\r
+#define SIG_MAIN_FIRQ3 15 // User\r
+\r
+#define SIG_MAIN_SUB_BUSY 16\r
+\r
+#define SIG_MAIN_DRQ_2HD 17\r
+#define SIG_MAIN_DRQ_2D 18\r
+\r
+#define SIG_MAIN_RTC_DATA 19\r
+#define SIG_MAIN_RTC_BUSY 20\r
+\r
+#ifdef HAS_I286\r
+class I286;\r
+#endif\r
+class I8237;\r
+class MB8877;\r
+\r
+class MAIN : public MEMORY\r
+{\r
+private:\r
+#ifdef HAS_I286\r
+ I286 *d_cpu;\r
+ uint8_t rst;\r
+#endif\r
+ I8237 *d_dma;\r
+ DEVICE *d_pic;\r
+ DEVICE *d_pcm;\r
+ DEVICE *d_keyboard;\r
+\r
+ // memory\r
+ uint8_t ram[0xfc000];\r
+ uint8_t rom[0x04000];\r
+ uint8_t direct;\r
+ \r
+ // main-sub\r
+ DEVICE *d_sub;\r
+ bool sub_busy;\r
+ \r
+ // 1mb fdd\r
+ MB8877 *d_fdc_2hd;\r
+ uint8_t sidereg_2hd, drvreg_2hd;\r
+ bool drq_2hd;\r
+ \r
+ // 320kb fdd\r
+ MB8877 *d_fdc_2d;\r
+ uint8_t sidereg_2d, drvreg_2d;\r
+ bool drq_2d;\r
+ \r
+ // rtc\r
+ DEVICE *d_rtc;\r
+ uint8_t rtc_data;\r
+ \r
+ // irq\r
+ uint8_t irq_enb, ext_irq_enb;\r
+ bool irq0_tx, irq0_rx, irq0_syn, irq1, irq2, irq3, irq4, irq5, irq6, irq7, irq8, irq9;\r
+ bool firq0, firq1, firq2, firq3;\r
+ bool int0, int1, int2, int3, int4, int5, int6, int7;\r
+ \r
+ void update_int0();\r
+ void update_int1();\r
+ void update_int2();\r
+ void update_int3();\r
+ void update_int4();\r
+ void update_int5();\r
+ void update_int6();\r
+ void update_int7();\r
+ \r
+public:\r
+ MAIN(VM_TEMPLATE* parent_vm, EMU* parent_emu) : MEMORY(parent_vm, parent_emu)\r
+ {\r
+ set_device_name(_T("Main System"));\r
+ }\r
+ ~MAIN() {}\r
+ \r
+ // common functions\r
+ void initialize();\r
+ void release();\r
+ void reset();\r
+ void write_io8(uint32_t addr, uint32_t data);\r
+ uint32_t read_io8(uint32_t addr);\r
+ void write_signal(int id, uint32_t data, uint32_t mask);\r
+ bool process_state(FILEIO* state_fio, bool loading);\r
+ \r
+ // unique functions\r
+#ifdef HAS_I286\r
+ void set_context_cpu(I286* device)\r
+ {\r
+ d_cpu = device;\r
+ }\r
+#endif\r
+ void set_context_dma(I8237* device)\r
+ {\r
+ d_dma = device;\r
+ }\r
+ void set_context_fdc_2hd(MB8877* device)\r
+ {\r
+ d_fdc_2hd = device;\r
+ }\r
+ void set_context_fdc_2d(MB8877* device)\r
+ {\r
+ d_fdc_2d = device;\r
+ }\r
+ void set_context_pic(DEVICE* device)\r
+ {\r
+ d_pic = device;\r
+ }\r
+ void set_context_pcm(DEVICE* device)\r
+ {\r
+ d_pcm = device;\r
+ }\r
+ void set_context_rtc(DEVICE* device)\r
+ {\r
+ d_rtc = device;\r
+ }\r
+ void set_context_sub(DEVICE* device)\r
+ {\r
+ d_sub = device;\r
+ }\r
+ void set_context_keyboard(DEVICE* device)\r
+ {\r
+ d_keyboard = device;\r
+ }\r
+};\r
+\r
+#endif\r