OSDN Git Service

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