OSDN Git Service

[VM][FMTOWNS] Add FONT ROMS, MSDOS ROM, SYSTEM ROM and SERIAL ROM.
[csp-qt/common_source_project-fm7.git] / source / src / vm / fmtowns / serialrom.cpp
1 /*
2         FUJITSU FM Towns Emulator 'eFMTowns'
3
4         Author : Kyuma.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2019.01.09 -
6
7         [serial rom]
8 */
9
10 #include "../../fileio.h"
11 #include "./towns_memory.h"
12 #include "./serialrom.h"
13 #include "../i386.h"
14
15 namespace FMTOWNS {
16         
17 void SERIAL_ROM::initialize()
18 {
19         cs = true;
20         clk = false;
21         reset_reg = false;
22         reset_state = 0;
23         rom_addr = 0;
24         
25         memset(rom, 0xff, sizeof(rom));
26         FILEIO *fio = new FULEIO();
27         if(fio->Fopen(create_local_path(_T("MYTOWNS.ROM")), FILEIO_READ_BINARY)) { // FONT
28                 fio->Fread(rom, sizeof(rom), 1);
29                 fio->Fcolose();
30         } else if(fio->Fopen(create_local_path(_T("SERIAL.ROM")), FILEIO_READ_BINARY)) { // FONT
31                 fio->Fread(rom, sizeof(rom), 1);
32                 fio->Fcolose();
33         } else {
34                 // Header
35                 const _TCHAR *id = _T("FUJITSU");
36                 int _len = strlen(id);
37                 if(_len < 0) _len = 0; // Bit 251 - 72
38                 if(_len >= 22) _len = 21; // Bit 251 - 72
39                 for(int i = 0; i < (_len + 1); i++) {
40                         rom[32 - i] = 0x00;
41                 }
42                 for(int i = 0; i < _len; i++) {
43                         uint8_t _c = (uint8_t)id[i];
44                         uint8_t _revc = 0x00;
45                         uint8_t val = 0x80;
46                         for(int j = 0; j < 8; j++) {
47                                 if((_c & 0x01) != 0) _revc = _revc | val;
48                                 val >>= 1;
49                                 _c  >>= 1;
50                         }
51                         rom[31 - i] = rom[31 - i] | ((_revc & 0xf0) >> 4); // High
52                         rom[31 - (i + 1)] = rom[31 - (i + 1)] | ((_revc & 0x0f) << 4); // Low
53                 }
54                 rom[31 - _len] = rom[31 - _len] | 0x0f; // Last bit
55                 // Machine ID (bit 71 - bit 56) must be dummy.
56
57                 // Serial (bit 55 - bit20)
58                 auto serial = static_cast<uint64_t>(0x00000123);
59                 auto nmask  = static_cast<uint64_t>(0x0f);
60                 nmask = nmask << 32;
61                 int nibblepos = 8;
62                 // Initialize footer and serial ID.
63                 for(int i = 0; i < 7; i++) {
64                         rom[7 - i] = 0x00;
65                 }
66                 
67                 for(int i = 0; i < 9; i++) {
68                         uint64_t nval = (nmask & serial) >> 32;
69                         uint8_t _c = ((uint8_t)nval) & 0x0f;
70                         uint8_t _revc = 0x00;
71                         uint8_t val = 0x08;
72                         for(int j = 0; j < 4; j++) {
73                                 if((_c & 0x01) != 0) _revc = _revc | val;
74                                 val >>= 1;
75                                 _c  >>= 1;
76                         }
77                         serial <<= 4;
78                         // High
79                         if((i & 1) == 0) { // Lower
80                                 rom[6 - (i / 2)] = rom[6 - (i / 2)] | (_revc << 4);  
81                         } else { // Lower
82                                 rom[6 - (i / 2)] = rom[6 - (i / 2)] | _revc;  
83                         }
84                 }
85         }
86 }
87
88 void SERIAL_ROM::reset()
89 {
90 //      cs = true;
91 //      clk = 0;
92 //      reset_state = 0;
93 //      rom_addr = 0;
94 }
95
96 void SERIAL_ROM::write_signal(int ch, uint32_t data, uint32_t mask)
97 {
98         switch(ch) {
99         case SIG_SERIAL_ROM_CLK:
100                 {
101                         bool oldclk = clk;
102                         bool newclk = clk;
103                         if(cs) {
104                                 newclk = ((data & mask) != 0);
105                         }
106                         if((oldclk != newclk) && !(reset_reg)) {
107                                 clk = newclk;
108                                 if(!(oldclk)) {
109                                         // Rise up
110                                         rom_addr = (rom_addr + 1) & 0xff;
111                                 }
112                         }
113                 }
114                 break;
115         case SIG_SERIAL_ROM_CS:
116                 cs = ((data & mask) == 0);
117                 break;
118         case SIG_SERIAL_ROM_RESET:
119                 reset_reg = ((data & mask) != 0);
120                 if((cs) && (clk)) {
121                         switch(reset_state) {
122                         case 0:
123                                 if(reset_reg) reset_state++;
124                                 break;
125                         case 1:
126                                 if(!(reset_reg)) {
127                                         // Do Reset
128                                         rom_addr = 0;
129                                         reset_state = 0;
130                                 }
131                                 break;
132                         default:
133                                 break;
134                         }
135                                         
136                 }
137                 break;
138         }
139 }
140                                 
141 uint32_t SERIAL_ROM::read_signal(int ch)
142 {
143         switch(ch) {
144         case SIG_SERIALROM_CLK:
145                 return ((clk) ? 0xffffffff : 0x00000000);
146                 break;
147         case SIG_SERIALROM_CS:
148                 return 0;
149                 break;
150         case SIG_SERIALROM_RESET:
151                 return ((reset_reg) ? 0xffffffff : 0x00000000);
152                 break;
153         case SIG_SERIALROM_DATA:
154                 {
155                         if((rom_addr >= 56) && (rom_addr < 72)) {
156                                 // Serial id
157                                 uint32_t machine_id = d_mem->read_signal(SIG_FMTOWNS_MACHINE_ID);
158                                 uint32_t bitaddr = 15 - (rom_addr - 56);
159                                 uint32_t bitmask = 0x8000 >> bitaddr;
160                                 return (((bitmask & machine_id) != 0) ? 0xffffffff : 0x00000000);
161                         } else {
162                                 uint32_t localaddr = (rom_addr & 0xff) >> 3;
163                                 uint32_t localbit  = (rom_addr & 0xff) & 0x07;
164                                 uint8_t _c = rom[localaddr];
165                                 uint8_t _bmask = 0x01 << localbit;
166                                 return (((_c & _bmask) != 0) ? 0xffffffff : 0x00000000);
167                         }
168                 }
169                 break;
170         }
171         return 0;
172 }
173
174 #define STATE_VERSION   1
175
176 bool SERIAL_ROM::process_state(FILEIO* state_fio, bool loading)
177 {
178         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
179                 return false;
180         }
181         if(!state_fio->StateCheckInt32(this_device_id)) {
182                 return false;
183         }
184         state_fio->StateValue(cs);
185         state_fio->StateValue(clk);
186         state_fio->StateValue(reset_reg);
187         state_fio->StateValue(reset_state);
188         state_fio->StateValue(rom_addr);
189         state_fio->StateArray(rom, sizeof(rom), 1);
190
191         return true;
192 }
193
194 }