OSDN Git Service

[VM][FMTOWNS] More simple implement of 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 "./serialrom.h"
12
13 namespace FMTOWNS {
14
15 // POS=rom bit position, c=data
16 void SERIAL_ROM::store_reversed_byte(uint8_t pos, uint8_t c)
17 {
18         int npos = (256 - (uint16_t)pos) >> 3;
19         int bitpos = (256 - (uint16_t)pos) & 7;
20         uint8_t dst = 0x00;
21         for(int i = 0; i < 8; i++) {
22                 dst <<= 1;
23                 dst = dst | ((c >> i)& 0x01);
24         }
25         if(bitpos == 0) {
26                 rom[npos] = dst;
27         } else {
28                 pair16_t tmp;
29                 pair16_t mask;
30                 tmp.b.l = rom[npos];
31                 if(npos < 31) {
32                         tmp.b.h = rom[npos + 1];
33                 } else {
34                         tmp.b.h = 0x00;
35                 }
36                 mask.b.h = 0x00;
37                 mask.b.l = 0xff;
38                 mask.w <<= bitpos;
39                 tmp.w = tmp.w & (~mask.w);
40                 uint16_t data;
41                 data = dst;
42                 data <<= bitpos;
43                 tmp.w = tmp.w | data;
44                 if(npos < 31) {
45                         rom[npos + 1] = tmp.b.h;
46                 }
47                 rom[npos] = tmp.b.l;
48         }
49 }
50
51 uint8_t SERIAL_ROM::read_rom_bits(uint8_t pos)
52 {
53         return ((rom[pos >> 3] >> (pos & 7)) & 0x01);
54 }
55
56 void SERIAL_ROM::initialize()
57 {
58         cs = true;
59         clk = false;
60         reset_reg = false;
61         reset_state = 0;
62         rom_addr = 0;
63         
64         memset(rom, 0xff, sizeof(rom));
65         uint8_t tmprom[256];
66         memset(tmprom, 0xff, sizeof(tmprom));
67         bool loaded = false;
68         FILEIO *fio = new FILEIO();
69         if(fio->Fopen(create_local_path(_T("MYTOWNS.ROM")), FILEIO_READ_BINARY)) { // FONT
70                 fio->Fread(tmprom, sizeof(tmprom), 1);
71                 fio->Fclose();
72                 loaded = true;
73         } else if(fio->Fopen(create_local_path(_T("SERIAL.ROM")), FILEIO_READ_BINARY)) { // FONT
74                 fio->Fread(tmprom, sizeof(tmprom), 1);
75                 fio->Fclose();
76                 loaded = true;
77         }
78         if(loaded) {
79                 // Q: IS MYTOWNS.ROM reverse bit-order? 20191117 K.O
80                 //memcpy(rom, tmprom, sizeof(rom));
81                 for(uint8_t i = 0; i < 32; i++) {
82                         store_reversed_byte(i << 3, tmprom[i]);
83                 }
84         } else {
85                 rom[255 >> 3] = rom[255 >> 3] & 0x0f; // Clear head of 4 bits.
86                 static const _TCHAR signaure[] = _T("FUJITSU");
87                 for(int i = 0; i < strlen(signature); i++) {
88                         store_reversed_byte((uint8_t)(244 - (i * 8)), signature[i]);
89                 }
90                 // ToDo: Reserved BITs (bit 195 - bit 72)
91                 // Machine ID
92                 store_reversed_byte(64, 0x01);
93                 store_reversed_byte(56, 0x01);
94                 // SERIAL (DUMMY)
95                 static const uint8_t serial_num[5] = {0xbc, 0xde, 0xf0, 0x12, 0x34};
96                 uint8_t tmp1 = rom[48 >> 3];
97                 uint8_t tmp2 = serial_num[0] & 0x0f;
98                 uint8_t dst = 0;
99                 for(int i = 0; i < 4; i++) {
100                         dst <<= 1;
101                         dst = dst | (tmp2 & 0x01);
102                         tmps >>= 1;
103                 }
104                 tmp1 = tmp1 & 0xf0;
105                 rom[48 >> 3] = tmp1 | (dst & 0x0f);
106                 for(int i = 1; i < 5; i++) {
107                         store_reversed_byte(20 + ((4 - i) << 3), serial_num[i]);
108                 }
109                 // Clear bit 19 - bit0
110                 rom[16 >> 3] = rom[16 >> 3] & 0xf0;
111                 rom[8 >> 3] = 0x00;
112                 rom[0 >> 3] = 0x00;
113         }
114 }
115         
116 void SERIAL_ROM::reset()
117 {
118 //      cs = true;
119 //      clk = 0;
120 //      reset_state = 0;
121 //      rom_addr = 0;
122 }
123
124 void SERIAL_ROM::write_signal(int ch, uint32_t data, uint32_t mask)
125 {
126         switch(ch) {
127         case SIG_SERIALROM_CLK:
128                 {
129                         bool oldclk = clk;
130                         bool newclk = clk;
131                         if(cs) {
132                                 newclk = ((data & mask) != 0);
133                         }
134                         if((oldclk != newclk) && !(reset_reg)) {
135                                 clk = newclk;
136                                 if(!(oldclk)) {
137                                         // Rise up
138                                         rom_addr = (rom_addr + 1) & 0xff;
139                                 }
140                         }
141                 }
142                 break;
143         case SIG_SERIALROM_CS:
144                 cs = ((data & mask) == 0);
145                 break;
146         case SIG_SERIALROM_RESET:
147                 reset_reg = ((data & mask) != 0);
148                 if((cs) && (clk)) {
149                         switch(reset_state) {
150                         case 0:
151                                 if(reset_reg) reset_state++;
152                                 break;
153                         case 1:
154                                 if(!(reset_reg)) {
155                                         // Do Reset
156                                         rom_addr = 0;
157                                         reset_state = 0;
158                                 }
159                                 break;
160                         default:
161                                 break;
162                         }
163                                         
164                 }
165                 break;
166         }
167 }
168                                 
169 uint32_t SERIAL_ROM::read_signal(int ch)
170 {
171         switch(ch) {
172         case SIG_SERIALROM_CLK:
173                 return ((clk) ? 0xffffffff : 0x00000000);
174                 break;
175         case SIG_SERIALROM_CS:
176                 return ((cs) ? 0xffffffff : 0x00000000);;
177                 break;
178         case SIG_SERIALROM_RESET:
179                 return ((reset_reg) ? 0xffffffff : 0x00000000);
180                 break;
181         case SIG_SERIALROM_RESET_STATE:
182                 return reset_state;
183                 break;
184         case SIG_SERIALROM_DATA:
185                 if(cs) {
186                         return (read_rom_bits(rom_addr) == 0x00) ? 0x00000000 : 0xffffffff;
187                 } else {
188                         return 0x00000000;
189                 }
190                 break;
191         }
192         return 0;
193 }
194
195 bool SERIAL_ROM::write_debug_reg(const _TCHAR *reg, uint32_t data)
196 {
197         _TCHAR numseg[8] = {'\0'};
198         int noff = 0;
199         if((reg[0] == 'R') || (reg[0] == 'r')){
200                 if(strlen(reg) < 2) return false;
201                 if((reg[1] == 'R') || (reg[1] == 'r')) { // Reversed bit
202                         noff = 1;
203                 }
204                 for(int i = 0; i < 2; i++) {
205                         if(reg[i + noff + 1] == '\0') break;
206                         if((reg[i + noff + 1] < '0') || (reg[i + noff + 1] >'9')) break;
207                         numseg[i] = reg[i + noff + 1];
208                 }
209                 if(strlen(numseg) < 1) return false;
210                 int pos = atoi(numseg);
211                 if((pos < 0) || (pos > 31)) return false;
212                 if((reg[1] == 'R') || (reg[1] == 'r')) { // Reversed bit
213                         uint8_t dst = 0;
214                         for(int i = 0; i <8; i++) {
215                                 dst <<= 1;
216                                 dst = dst | (data & 0x01);
217                                 data >>= 1;
218                         }
219                         rom[pos] = dst;
220                 } else {
221                         rom[pos] = data;
222                 }
223                 return true;
224         } else if((reg[0] == 'B') || (reg[0] == 'b')){
225                 if(strlen(reg) < 2) return false;
226                 if((reg[1] == 'R') || (reg[i] == 'r')) { // Reversed bit
227                         noff = 1;
228                 }               
229                 for(int i = 0; i < 3; i++) {
230                         if(reg[i + noff + 1] == '\0') break;
231                         if((reg[i + noff + 1] < '0') || (reg[i + noff + 1] >'9')) break;
232                         numseg[i] = reg[i + noff + 1];
233                 }
234                 if(strlen(numseg) < 1) return false;
235                 int bitpos = atoi(numseg);
236                 if((pos < 0) || (pos > 255)) return false;
237                 int bytepos = bitpos >> 3;
238                 int offs = bitpos & 7;
239                 uint8_t dst = rom[bytepos];
240                 if((reg[1] == 'R') || (reg[i] == 'r')) { // Reversed bit
241                         offs = 7 - offs;
242                 }
243                 dst = dst & (~(0x01 << offs));
244                 dst = dst | ((data & 0x01) << offs);
245                 rom[bytepos] = dst;
246                 return true;
247         }
248         return false;
249 }
250
251 bool SERIAL_ROM::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
252 {
253         uint8_t reverse_mem[32];
254
255         memset(reverse_mem, 0x00, sizeof(reverse_mem));
256         for(int i = 0; i < 32; i++) {
257                 uint8_t dst = 0x00;
258                 uint8_t src = rom[i];
259                 for(int j = 0; j < 8; j++) {
260                         dst <<= 1;
261                         dst |= (src & 0x01);
262                         src >>= 1;
263                 }
264                 reverse_mem[i] = dst;
265         }
266         // Dump raw value
267         my_tcscat_s(buffer, buffer_len, _T("** INFO:\n"));
268         my_tcscat_s(buffer, buffer_len, _T("ROM value is enable to modify, \n"));
269         my_tcscat_s(buffer, buffer_len, _T("  R00-R32 : Overwrite rom raw value by byte\n"));
270         my_tcscat_s(buffer, buffer_len, _T("  RR00-RR32 : Overwrite rom reversed value by byte\n"));
271         my_tcscat_s(buffer, buffer_len, _T("  B000-B256 : Overwrite bit foo to (value != 0) ? 1 : 0\n"));
272         my_tcscat_s(buffer, buffer_len, _T("  BR000-BR256 : Overwrite bit foo to (value != 0) ? 1 : 0 by reversed order.\n\n"));
273         
274         my_tcscat_s(buffer, buffer_len, _T("** STATS:\n"));
275         my_tcscat_s(buffer, buffer_len,
276                                 create_string(_T("    CS=%s CLK=%d RESET REG=%d RESET STATE=%d\n   ROM BIT POSITION=%03d(0x%02X)\n\n"),
277                                                           (cs) ? _T("ON ") : _T("OFF"),
278                                                           (clk) ? 1 : 0,
279                                                           (reset_reg) ? 1 : 0,
280                                                           reset_state,
281                                                           rom_addr, rom_addr)
282                 );
283         
284         my_tcscat_s(buffer, buffer_len, _T("** RAW MEMORY VALUE:\n"));
285         my_tcscat_s(buffer, buffer_len, _T("    +0  +1  +2  +3  +4  +5  +6  +7\n"));
286         my_tcscat_s(buffer, buffer_len, _T("    ------------------------------\n"));
287         for(int n = 0; n < 4; n++) {
288                 my_tcscat_s(buffer, buffer_len,
289                                         create_string(_T("+%02X %02X  %02X  %02X  %02X  %02X  %02X  %02X  %02X\n"),
290                                                                   n * 4,
291                                                                   rom[n * 4 + 0], rom[n * 4 + 1], rom[n * 4 + 2], rom[n * 4 + 3],
292                                                                   rom[n * 4 + 4], rom[n * 4 + 5], rom[n * 4 + 6], rom[n * 4 + 7])
293                         );
294         }
295         my_tcscat_s(buffer, buffer_len, _T("\n"));
296         my_tcscat_s(buffer, buffer_len, _T("** BIT REVERSED VALUE:\n"));
297         my_tcscat_s(buffer, buffer_len, _T("    +0  +1  +2  +3  +4  +5  +6  +7\n"));
298         my_tcscat_s(buffer, buffer_len, _T("    ------------------------------\n"));
299         for(int n = 0; n < 4; n++) {
300                 my_tcscat_s(buffer, buffer_len,
301                                         create_string(_T("+%02X %02X  %02X  %02X  %02X  %02X  %02X  %02X  %02X\n"),
302                                                                   n * 4,
303                                                                   reverse_mem[n * 4 + 0], reverse_mem[n * 4 + 1], reverse_mem[n * 4 + 2], reverse_mem[n * 4 + 3],
304                                                                   reverse_mem[n * 4 + 4], reverse_mem[n * 4 + 5], reverse_mem[n * 4 + 6], reverse_mem[n * 4 + 7])
305                         );
306         }
307         return true;
308 }
309         
310 #define STATE_VERSION   1
311
312 bool SERIAL_ROM::process_state(FILEIO* state_fio, bool loading)
313 {
314         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
315                 return false;
316         }
317         if(!state_fio->StateCheckInt32(this_device_id)) {
318                 return false;
319         }
320         state_fio->StateValue(cs);
321         state_fio->StateValue(clk);
322         state_fio->StateValue(reset_reg);
323         state_fio->StateValue(reset_state);
324         state_fio->StateValue(rom_addr);
325         state_fio->StateArray(rom, sizeof(rom), 1);
326
327         return true;
328 }
329
330 }