OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc6001 / sub.cpp
1 /*
2         NEC PC-6001 Emulator 'yaPC-6001'
3         NEC PC-6001mkII Emulator 'yaPC-6201'
4         NEC PC-6001mkIISR Emulator 'yaPC-6401'
5         NEC PC-6601 Emulator 'yaPC-6601'
6         NEC PC-6601SR Emulator 'yaPC-6801'
7
8         Author : Takeda.Toshiya
9         Date   : 2014.05.24-
10
11         [ sub cpu ]
12 */
13
14 #include "sub.h"
15 #include "timer.h"
16 #include "../datarec.h"
17 #include "../i8255.h"
18 #include "../mcs48.h"
19
20 #define EVENT_PLAY      0
21 #define EVENT_STOP      1
22
23 namespace PC6001 {
24
25 static const uint8_t key_matrix[16][8] = {
26         {0x00,  0x11,   0x10,   0x12,   0x00,   0x00,   0x00,   0x00},
27         {0x31,  0x51,   0x41,   0x5a,   0x4b,   0x49,   0x38,   0xbc},
28         {0x32,  0x57,   0x53,   0x58,   0x4c,   0x4f,   0x39,   0xbe},
29         {0x33,  0x45,   0x44,   0x43,   0xbb,   0x50,   0x70,   0xbf},
30         {0x34,  0x52,   0x46,   0x56,   0xba,   0xc0,   0x71,   0xe2},
31         {0x35,  0x54,   0x47,   0x42,   0xdd,   0xdb,   0x72,   0x20},
32         {0x36,  0x59,   0x48,   0x4e,   0xbd,   0xde,   0x73,   0x30},
33         {0x37,  0x55,   0x4a,   0x4d,   0x00,   0xdc,   0x74,   0x00},
34         {0x0d,  0x13,   0x26,   0x28,   0x27,   0x25,   0x09,   0x1b},
35         {0x15,  0x2d,   0x2e,   0x23,   0x24,   0x00,   0x00,   0x00},  // ROT=END
36         {0x00,  0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00},
37         {0x00,  0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00},
38         {0x00,  0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00},
39         {0x00,  0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00},
40         {0x00,  0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00},
41         {0x00,  0x00,   0x00,   0x00,   0x00,   0x00,   0x00,   0x00},
42 };
43
44 void SUB::initialize()
45 {
46         fio = new FILEIO();
47         rec = false;
48         
49         key_stat = emu->get_key_buffer();
50         p1_out = 0x10;
51         p2_in = 0xff;
52         drec_in = rxrdy_in = false;
53         skip = false;
54         update_key = true;
55         register_frame_event(this);
56 }
57
58 void SUB::release()
59 {
60         close_tape();
61         delete fio;
62 }
63
64 void SUB::reset()
65 {
66         close_tape();
67         prev_command = 0;
68 }
69
70 #define SET_WR(v) d_pio->write_signal(SIG_I8255_PORT_C, (v) ? 0xff : 0, 0x10)
71 #define SET_RD(v) d_pio->write_signal(SIG_I8255_PORT_C, (v) ? 0xff : 0, 0x40)
72
73 void SUB::write_io8(uint32_t addr, uint32_t data)
74 {
75         // FIXME: this function is referred from both 80c48 and z80
76         if((addr & 0xf0) == 0x90) {
77                 // Z80
78                 if((addr & 0xff) == 0x90) {
79                         if(prev_command == 0x38) {
80                                 if(rec && index < sizeof(buffer)) {
81                                         buffer[index++] = data;
82                                         skip = true;
83                                 }
84                                 prev_command = 0;
85                         } else {
86                                 switch(data) {
87                                 case 0x19:
88 //                                      d_drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
89                                         register_event(this, EVENT_PLAY, 1000000.0, false, NULL);
90                                         break;
91                                 case 0x1a:
92 //                                      d_drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);
93                                         register_event(this, EVENT_STOP, 1000000.0, false, NULL);
94                                         break;
95                                 case 0x1e:
96                                 case 0x3e:
97                                         baud = 1200;
98                                         break;
99                                 case 0x1d:
100                                 case 0x3d:
101                                         baud = 600;
102                                         break;
103                                 }
104                                 prev_command = data;
105                         }
106                 }
107                 d_pio->write_io8(addr, data);
108         } else {
109                 // 8048
110                 switch(addr) {
111                 case MCS48_PORT_P1:
112                         if((p1_out & 0x0f) != (data & 0x0f)) {
113                                 update_key = true;
114                         }
115                         p1_out = data;
116 //                      d_drec->write_signal(SIG_DATAREC_MIC, data, 0x20);
117                         d_timer->write_signal(SIG_TIMER_IRQ_SUB_CPU, ~data, 0x80);
118                         break;
119                 default:
120                         SET_WR(1);
121                         SET_WR(0);
122                         SET_WR(1);
123                         d_pio->write_signal(SIG_I8255_PORT_A, data, 0xff);
124                         break;
125                 }
126         }
127 }
128
129 uint32_t SUB::read_io8(uint32_t addr)
130 {
131         // FIXME: this function is referred from both 80c48 and z80
132         if((addr & 0xf0) == 0x90) {
133                 // Z80
134                 if((addr & 0xff) == 0x90) {
135                         return d_pio->read_io8(addr);
136                 } else {
137                         return 0xff;
138                 }
139         } else {
140                 // 8048
141                 switch(addr) {
142                 case MCS48_PORT_P2:
143                         if(update_key) {
144                                 int column = p1_out & 0x0f;
145                                 int val = 0;
146                                 for(int i = 0; i < 8; i++) {
147                                         if(key_stat[key_matrix[column][i]]) {
148                                                 val |= 1 << i;
149                                         }
150                                 }
151                                 p2_in = (~val) & 0xff;
152                                 update_key = false;
153                         }
154                         if(p1_out & 0x10) {
155                                 return p2_in;
156                         } else {
157                                 // bit3: signal from datarec
158                                 // bit1: rxrdy from rs-232c
159                                 return (rxrdy_in ? 2 : 0) | (drec_in ? 8 : 0) | (p2_in & 0xf0);
160                         }
161                 case MCS48_PORT_T0:
162                         // PC5 -> T0
163                         return (d_pio->read_signal(SIG_I8255_PORT_C) >> 5) & 1;
164                 default:
165                         SET_RD(1);
166                         SET_RD(0);
167                         SET_RD(1);
168                         return d_pio->read_signal(SIG_I8255_PORT_A);
169                 }
170         }
171         return 0xff;
172 }
173
174 uint32_t SUB::get_intr_ack()
175 {
176         return d_pio->read_io8(0);
177 }
178
179 void SUB::event_frame()
180 {
181         if(skip) {
182                 request_skip_frames();
183                 skip = false;
184         }
185         update_key = true;
186 }
187
188 void SUB::event_callback(int event_id, int err)
189 {
190         if(event_id == EVENT_PLAY) {
191                 d_drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
192         } else if(event_id == EVENT_STOP) {
193                 d_drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);
194         }
195 }
196
197 void SUB::write_signal(int id, uint32_t data, uint32_t mask)
198 {
199         if(id == SIG_SUB_DATAREC) {
200                 drec_in = ((data & mask) != 0);
201         } else if(id == SIG_SUB_RXRDY) {
202                 rxrdy_in = ((data & mask) != 0);
203         }
204 }
205
206 bool SUB::rec_tape(const _TCHAR* file_path)
207 {
208         close_tape();
209         
210         if(fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
211                 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
212                 index = 0;
213                 rec = true;
214                 is_wav = check_file_extension(file_path, _T(".wav"));
215                 is_p6t = check_file_extension(file_path, _T(".p6t"));
216         }
217         return rec;
218 }
219
220 static const uint8_t pulse_1200hz[40] = {
221         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
222         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
223         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
224         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
225 };
226
227 static const uint8_t pulse_2400hz[20] = {
228         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
229         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
230 };
231
232 static const uint8_t pulse_2400hz_x2[40] = {
233         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
234         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
235         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
236         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
237 };
238
239 void SUB::close_tape()
240 {
241         if(fio->IsOpened()) {
242                 if(rec) {
243                         if(is_wav) {
244                                 wav_header_t wav_header;
245                                 wav_chunk_t wav_chunk;
246                                 int sample_rate = (baud == 600) ? 24000 : 48000;
247                                 
248                                 fio->Fwrite(&wav_header, sizeof(wav_header), 1);
249                                 fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
250                                 
251                                 for(int i = 0; i < 9600; i++) {
252                                         fio->Fwrite((void *)pulse_2400hz, sizeof(pulse_2400hz), 1);
253                                 }
254                                 for(int i = 0; i < 16; i++) {
255                                         fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
256                                         for(int j = 0; j < 8; j++) {
257                                                 if(buffer[i] & (1 << j)) {
258                                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
259                                                 } else {
260                                                         fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
261                                                 }
262                                         }
263                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
264                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
265                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
266                                 }
267         //                      for(int i = 0; i < 1280; i++) {
268                                 for(int i = 0; i < 2400; i++) {
269                                         fio->Fwrite((void *)pulse_2400hz, sizeof(pulse_2400hz), 1);
270                                 }
271                                 for(int i = 16; i < index; i++) {
272                                         fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
273                                         for(int j = 0; j < 8; j++) {
274                                                 if(buffer[i] & (1 << j)) {
275                                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
276                                                 } else {
277                                                         fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
278                                                 }
279                                         }
280                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
281                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
282                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
283                                 }
284 #if 1
285                                 for(int i = 0; i < 16; i++) {
286                                         fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
287                                         for(int j = 0; j < 8; j++) {
288                                                 fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
289                                         }
290                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
291                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
292                                         fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
293                                 }
294 #endif
295                                 uint32_t length = fio->Ftell();
296 #if 0                           
297                                 pair_t __riff_chunk_size;
298                                 pair_t __fmt_chunk_size;
299                                 pair_t __wav_chunk_size;
300                                 pair16_t __fmt_id;
301                                 pair16_t __channels;
302                                 pair_t __sample_rate;
303                                 pair16_t __block_size;
304                                 pair16_t __sample_bits;
305
306                                 __riff_chunk_size.d = length - 8;
307                                 __fmt_chunk_size.d = 16;
308                                 __fmt_id.w = 1;
309                                 __channels.w = 1;
310                                 __sample_rate.d = sample_rate;
311                                 __block_size.w = 1;
312                                 __sample_bits.w = 8;
313         
314                                 memcpy(wav_header.riff_chunk.id, "RIFF", 4);
315                                 wav_header.riff_chunk.size = __riff_chunk_size.get_4bytes_le_to();
316         
317                                 memcpy(wav_header.wave, "WAVE", 4);
318                                 memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
319                                 wav_header.fmt_chunk.size = __riff_chunk_size.get_4bytes_le_to();
320                                 wav_header.format_id = __fmt_id.get_2bytes_le_to();
321                                 wav_header.channels = __channels.get_2byte_le_to();
322                                 wav_header.sample_rate = __sample_rate.get_4bytes_le_to();
323                                 wav_header.data_speed =  __sample_rate.get_4bytes_le_to();
324                                 wav_header.block_size = __block_size.get_2bytes_le_to();
325                                 wav_header.sample_bits = __sample_bits_get_2bytes_le_to();
326         
327                                 memcpy(wav_chunk.id, "data", 4);
328                                 __wav_chunk_size.d = length - sizeof(wav_header) - sizeof(wav_chunk);
329                                 wav_chunk.size = __wav_chunk_size.get_4bytes_le_to();
330                                 
331                                 fio->Fseek(0, FILEIO_SEEK_SET);
332                                 fio->Fwrite(&wav_header, sizeof(wav_header), 1);
333                                 fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
334 #else
335                                 if(set_wav_header(&wav_header, &wav_chunk, 1, sample_rate, 8, length)) {
336                                         fio->Fseek(0, FILEIO_SEEK_SET);
337                                         fio->Fwrite(&wav_header, sizeof(wav_header), 1);
338                                         fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
339                                 }
340 #endif
341                         } else {
342                                 fio->Fwrite(buffer, index, 1);
343                                 if(is_p6t) {
344                                         fio->Fputc('P');
345                                         fio->Fputc('6');
346                                         fio->FputUint8(2);
347                                         fio->FputUint8(2);
348                                         fio->FputUint8(0);
349                                         fio->FputUint8(0);
350                                         fio->FputUint8(0);
351                                         fio->FputUint16(0);
352                                         fio->FputUint16(0);
353                                         
354                                         fio->Fputc('T');
355                                         fio->Fputc('I');
356                                         fio->FputUint8(0);
357                                         for(int i = 0; i < 6; i++) {
358                                                 fio->FputUint8(buffer[10 + i]);
359                                         }
360                                         for(int i = 6; i < 16; i++) {
361                                                 fio->FputUint8(0);
362                                         }
363                                         fio->FputUint16(baud);
364                                         fio->FputUint16(3000);
365                                         fio->FputUint16(4000);
366                                         fio->FputUint32(0);
367                                         fio->FputUint32(16);
368                                         
369                                         fio->Fputc('T');
370                                         fio->Fputc('I');
371                                         fio->FputUint8(0);
372                                         for(int i = 0; i < 16; i++) {
373                                                 fio->FputUint8(0);
374                                         }
375                                         fio->FputUint16(baud);
376                                         fio->FputUint16(0);
377                                         fio->FputUint16(1000);
378                                         fio->FputUint32(16);
379                                         fio->FputUint32(index - 16);
380                                         
381                                         fio->FputUint32(index);
382                                 }
383                         }
384                 }
385                 fio->Fclose();
386         }
387         rec = false;
388 }
389
390 #define STATE_VERSION   1
391
392 bool SUB::process_state(FILEIO* state_fio, bool loading)
393 {
394         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
395                 return false;
396         }
397         if(!state_fio->StateCheckInt32(this_device_id)) {
398                 return false;
399         }
400         state_fio->StateInt32(p1_out);
401         state_fio->StateInt32(p2_in);
402         state_fio->StateBool(drec_in);
403         state_fio->StateBool(rxrdy_in);
404         state_fio->StateBool(update_key);
405         state_fio->StateBool(rec);
406         state_fio->StateBool(is_wav);
407         state_fio->StateBool(is_p6t);
408         state_fio->StateBuffer(rec_file_path, sizeof(rec_file_path), 1);
409         if(loading) {
410                 int length_tmp = state_fio->FgetInt32_LE();
411                 if(rec) {
412                         fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
413                         while(length_tmp != 0) {
414                                 uint8_t buffer_tmp[1024];
415                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
416                                 state_fio->Fread(buffer_tmp, length_rw, 1);
417                                 if(fio->IsOpened()) {
418                                         fio->Fwrite(buffer_tmp, length_rw, 1);
419                                 }
420                                 length_tmp -= length_rw;
421                         }
422                 }
423         } else {
424                 if(rec && fio->IsOpened()) {
425                         int length_tmp = (int)fio->Ftell();
426                         fio->Fseek(0, FILEIO_SEEK_SET);
427                         state_fio->FputInt32_LE(length_tmp);
428                         while(length_tmp != 0) {
429                                 uint8_t buffer_tmp[1024];
430                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
431                                 fio->Fread(buffer_tmp, length_rw, 1);
432                                 state_fio->Fwrite(buffer_tmp, length_rw, 1);
433                                 length_tmp -= length_rw;
434                         }
435                 } else {
436                         state_fio->FputInt32_LE(0);
437                 }
438         }
439         state_fio->StateInt32(prev_command);
440         state_fio->StateInt32(baud);
441         state_fio->StateInt32(index);
442         state_fio->StateBool(skip);
443         state_fio->StateBuffer(buffer, sizeof(buffer), 1);
444         return true;
445 }
446
447 }
448