OSDN Git Service

[VM][FM16BETA][OOPS] Add main feature.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 12 Dec 2022 03:07:37 +0000 (12:07 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Mon, 12 Dec 2022 03:07:37 +0000 (12:07 +0900)
source/src/vm/fm16beta/main.cpp [new file with mode: 0644]
source/src/vm/fm16beta/main.h [new file with mode: 0644]

diff --git a/source/src/vm/fm16beta/main.cpp b/source/src/vm/fm16beta/main.cpp
new file mode 100644 (file)
index 0000000..b928a8a
--- /dev/null
@@ -0,0 +1,437 @@
+/*\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
diff --git a/source/src/vm/fm16beta/main.h b/source/src/vm/fm16beta/main.h
new file mode 100644 (file)
index 0000000..6de8df0
--- /dev/null
@@ -0,0 +1,153 @@
+/*\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