-/*\r
- NEC PC-6001 Emulator 'yaPC-6001'\r
- NEC PC-6001mkII Emulator 'yaPC-6201'\r
- NEC PC-6001mkIISR Emulator 'yaPC-6401'\r
- NEC PC-6601 Emulator 'yaPC-6601'\r
- NEC PC-6601SR Emulator 'yaPC-6801'\r
-\r
- Author : Takeda.Toshiya\r
- Date : 2014.05.24-\r
-\r
- [ sub cpu ]\r
-*/\r
-\r
-#include "sub.h"\r
-#include "timer.h"\r
-#include "../datarec.h"\r
-#include "../i8255.h"\r
-#include "../mcs48.h"\r
-#include "../../fileio.h"\r
-\r
-#define EVENT_PLAY 0\r
-#define EVENT_STOP 1\r
-\r
-static const uint8 key_matrix[16][8] = {\r
- {0x00, 0x11, 0x10, 0x12, 0x00, 0x00, 0x00, 0x00},\r
- {0x31, 0x51, 0x41, 0x5a, 0x4b, 0x49, 0x38, 0xbc},\r
- {0x32, 0x57, 0x53, 0x58, 0x4c, 0x4f, 0x39, 0xbe},\r
- {0x33, 0x45, 0x44, 0x43, 0xbb, 0x50, 0x70, 0xbf},\r
- {0x34, 0x52, 0x46, 0x56, 0xba, 0xc0, 0x71, 0xe2},\r
- {0x35, 0x54, 0x47, 0x42, 0xdd, 0xdb, 0x72, 0x20},\r
- {0x36, 0x59, 0x48, 0x4e, 0xbd, 0xde, 0x73, 0x30},\r
- {0x37, 0x55, 0x4a, 0x4d, 0x00, 0xdc, 0x74, 0x00},\r
- {0x0d, 0x13, 0x26, 0x28, 0x27, 0x25, 0x09, 0x1b},\r
- {0x15, 0x2d, 0x2e, 0x23, 0x24, 0x00, 0x00, 0x00}, // ROT=END\r
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\r
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\r
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\r
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\r
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\r
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},\r
-};\r
-\r
-void SUB::initialize()\r
-{\r
- fio = new FILEIO();\r
- rec = false;\r
- \r
- key_stat = emu->key_buffer();\r
- p1_out = 0x10;\r
- p2_in = 0xff;\r
- drec_in = rxrdy_in = false;\r
- skip = false;\r
- update_key = true;\r
- register_frame_event(this);\r
-}\r
-\r
-void SUB::release()\r
-{\r
- close_tape();\r
- delete fio;\r
-}\r
-\r
-void SUB::reset()\r
-{\r
- close_tape();\r
- prev_command = 0;\r
-}\r
-\r
-#define SET_WR(v) d_pio->write_signal(SIG_I8255_PORT_C, (v) ? 0xff : 0, 0x10)\r
-#define SET_RD(v) d_pio->write_signal(SIG_I8255_PORT_C, (v) ? 0xff : 0, 0x40)\r
-\r
-void SUB::write_io8(uint32 addr, uint32 data)\r
-{\r
- // FIXME: this function is referred from both 80c48 and z80\r
- if((addr & 0xf0) == 0x90) {\r
- // Z80\r
- if((addr & 0xff) == 0x90) {\r
- if(prev_command == 0x38) {\r
- if(rec && index < sizeof(buffer)) {\r
- buffer[index++] = data;\r
- skip = true;\r
- }\r
- prev_command = 0;\r
- } else {\r
- switch(data) {\r
- case 0x19:\r
-// d_drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);\r
- register_event(this, EVENT_PLAY, 1000000.0, false, NULL);\r
- break;\r
- case 0x1a:\r
-// d_drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);\r
- register_event(this, EVENT_STOP, 1000000.0, false, NULL);\r
- break;\r
- case 0x1e:\r
- case 0x3e:\r
- baud = 1200;\r
- break;\r
- case 0x1d:\r
- case 0x3d:\r
- baud = 600;\r
- break;\r
- }\r
- prev_command = data;\r
- }\r
- }\r
- d_pio->write_io8(addr, data);\r
- } else {\r
- // 8048\r
- switch(addr) {\r
- case MCS48_PORT_P1:\r
- if((p1_out & 0x0f) != (data & 0x0f)) {\r
- update_key = true;\r
- }\r
- p1_out = data;\r
-// d_drec->write_signal(SIG_DATAREC_OUT, data, 0x20);\r
- d_timer->write_signal(SIG_TIMER_IRQ_SUB_CPU, ~data, 0x80);\r
- break;\r
- default:\r
- SET_WR(1);\r
- SET_WR(0);\r
- SET_WR(1);\r
- d_pio->write_signal(SIG_I8255_PORT_A, data, 0xff);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-uint32 SUB::read_io8(uint32 addr)\r
-{\r
- // FIXME: this function is referred from both 80c48 and z80\r
- if((addr & 0xf0) == 0x90) {\r
- // Z80\r
- if((addr & 0xff) == 0x90) {\r
- return d_pio->read_io8(addr);\r
- } else {\r
- return 0xff;\r
- }\r
- } else {\r
- // 8048\r
- switch(addr) {\r
- case MCS48_PORT_P2:\r
- if(update_key) {\r
- int column = p1_out & 0x0f;\r
- int val = 0;\r
- for(int i = 0; i < 8; i++) {\r
- if(key_stat[key_matrix[column][i]]) {\r
- val |= 1 << i;\r
- }\r
- }\r
- p2_in = (~val) & 0xff;\r
- update_key = false;\r
- }\r
- if(p1_out & 0x10) {\r
- return p2_in;\r
- } else {\r
- // bit3: signal from datarec\r
- // bit1: rxrdy from rs-232c\r
- return (rxrdy_in ? 2 : 0) | (drec_in ? 8 : 0) | (p2_in & 0xf0);\r
- }\r
- case MCS48_PORT_T0:\r
- // PC5 -> T0\r
- return (d_pio->read_signal(SIG_I8255_PORT_C) >> 5) & 1;\r
- default:\r
- SET_RD(1);\r
- SET_RD(0);\r
- SET_RD(1);\r
- return d_pio->read_signal(SIG_I8255_PORT_A);\r
- }\r
- }\r
- return 0xff;\r
-}\r
-\r
-uint32 SUB::intr_ack()\r
-{\r
- return d_pio->read_io8(0);\r
-}\r
-\r
-void SUB::event_frame()\r
-{\r
- if(skip) {\r
- request_skip_frames();\r
- skip = false;\r
- }\r
- update_key = true;\r
-}\r
-\r
-void SUB::event_callback(int event_id, int err)\r
-{\r
- if(event_id == EVENT_PLAY) {\r
- d_drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);\r
- } else if(event_id == EVENT_STOP) {\r
- d_drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);\r
- }\r
-}\r
-\r
-void SUB::write_signal(int id, uint32 data, uint32 mask)\r
-{\r
- if(id == SIG_SUB_DATAREC) {\r
- drec_in = ((data & mask) != 0);\r
- } else if(id == SIG_SUB_RXRDY) {\r
- rxrdy_in = ((data & mask) != 0);\r
- }\r
-}\r
-\r
-bool SUB::rec_tape(_TCHAR* file_path)\r
-{\r
- close_tape();\r
- \r
- if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {\r
- index = 0;\r
- rec = true;\r
- is_wav = check_file_extension(file_path, _T(".wav"));\r
- is_p6t = check_file_extension(file_path, _T(".p6t"));\r
- }\r
- return rec;\r
-}\r
-\r
-#pragma pack(1)\r
-typedef struct {\r
- char id[4];\r
- uint32 size;\r
-} wav_chunk_t;\r
-#pragma pack()\r
-\r
-#pragma pack(1)\r
-typedef struct {\r
- wav_chunk_t riff_chunk;\r
- char wave[4];\r
- wav_chunk_t fmt_chunk;\r
- uint16 format_id;\r
- uint16 channels;\r
- uint32 sample_rate;\r
- uint32 data_speed;\r
- uint16 block_size;\r
- uint16 sample_bits;\r
-} wav_header_t;\r
-#pragma pack()\r
-\r
-static const uint8 pulse_1200hz[40] = {\r
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
-};\r
-\r
-static const uint8 pulse_2400hz[20] = {\r
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
-};\r
-\r
-static const uint8 pulse_2400hz_x2[40] = {\r
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\r
- 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,\r
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00\r
-};\r
-\r
-void SUB::close_tape()\r
-{\r
- if(rec) {\r
- if(is_wav) {\r
- wav_header_t wav_header;\r
- wav_chunk_t wav_chunk;\r
- int sample_rate = (baud == 600) ? 24000 : 48000;\r
- \r
- fio->Fwrite(&wav_header, sizeof(wav_header), 1);\r
- fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);\r
- \r
- for(int i = 0; i < 9600; i++) {\r
- fio->Fwrite((void *)pulse_2400hz, sizeof(pulse_2400hz), 1);\r
- }\r
- for(int i = 0; i < 16; i++) {\r
- fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);\r
- for(int j = 0; j < 8; j++) {\r
- if(buffer[i] & (1 << j)) {\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- } else {\r
- fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);\r
- }\r
- }\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- }\r
-// for(int i = 0; i < 1280; i++) {\r
- for(int i = 0; i < 2400; i++) {\r
- fio->Fwrite((void *)pulse_2400hz, sizeof(pulse_2400hz), 1);\r
- }\r
- for(int i = 16; i < index; i++) {\r
- fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);\r
- for(int j = 0; j < 8; j++) {\r
- if(buffer[i] & (1 << j)) {\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- } else {\r
- fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);\r
- }\r
- }\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- }\r
-#if 1\r
- for(int i = 0; i < 16; i++) {\r
- fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);\r
- for(int j = 0; j < 8; j++) {\r
- fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);\r
- }\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);\r
- }\r
-#endif\r
- uint32 length = fio->Ftell();\r
- \r
- memcpy(wav_header.riff_chunk.id, "RIFF", 4);\r
- wav_header.riff_chunk.size = length - 8;\r
- memcpy(wav_header.wave, "WAVE", 4);\r
- memcpy(wav_header.fmt_chunk.id, "fmt ", 4);\r
- wav_header.fmt_chunk.size = 16;\r
- wav_header.format_id = 1;\r
- wav_header.channels = 1;\r
- wav_header.sample_rate = sample_rate;\r
- wav_header.data_speed = sample_rate;\r
- wav_header.block_size = 1;\r
- wav_header.sample_bits = 8;\r
- \r
- memcpy(wav_chunk.id, "data", 4);\r
- wav_chunk.size = length - sizeof(wav_header) - sizeof(wav_chunk);\r
- \r
- fio->Fseek(0, FILEIO_SEEK_SET);\r
- fio->Fwrite(&wav_header, sizeof(wav_header), 1);\r
- fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);\r
- } else {\r
- fio->Fwrite(buffer, index, 1);\r
- if(is_p6t) {\r
- fio->Fputc('P');\r
- fio->Fputc('6');\r
- fio->FputUint8(2);\r
- fio->FputUint8(2);\r
- fio->FputUint8(0);\r
- fio->FputUint8(0);\r
- fio->FputUint8(0);\r
- fio->FputUint16(0);\r
- fio->FputUint16(0);\r
- \r
- fio->Fputc('T');\r
- fio->Fputc('I');\r
- fio->FputUint8(0);\r
- for(int i = 0; i < 6; i++) {\r
- fio->FputUint8(buffer[10 + i]);\r
- }\r
- for(int i = 6; i < 16; i++) {\r
- fio->FputUint8(0);\r
- }\r
- fio->FputUint16(baud);\r
- fio->FputUint16(3000);\r
- fio->FputUint16(4000);\r
- fio->FputUint32(0);\r
- fio->FputUint32(16);\r
- \r
- fio->Fputc('T');\r
- fio->Fputc('I');\r
- fio->FputUint8(0);\r
- for(int i = 0; i < 16; i++) {\r
- fio->FputUint8(0);\r
- }\r
- fio->FputUint16(baud);\r
- fio->FputUint16(0);\r
- fio->FputUint16(1000);\r
- fio->FputUint32(16);\r
- fio->FputUint32(index - 16);\r
- \r
- fio->FputUint32(index);\r
- }\r
- }\r
- fio->Fclose();\r
- }\r
- rec = false;\r
-}\r
+/*
+ NEC PC-6001 Emulator 'yaPC-6001'
+ NEC PC-6001mkII Emulator 'yaPC-6201'
+ NEC PC-6001mkIISR Emulator 'yaPC-6401'
+ NEC PC-6601 Emulator 'yaPC-6601'
+ NEC PC-6601SR Emulator 'yaPC-6801'
+
+ Author : Takeda.Toshiya
+ Date : 2014.05.24-
+
+ [ sub cpu ]
+*/
+
+#include "sub.h"
+#include "timer.h"
+#include "../datarec.h"
+#include "../i8255.h"
+#include "../mcs48.h"
+
+#define EVENT_PLAY 0
+#define EVENT_STOP 1
+
+static const uint8_t key_matrix[16][8] = {
+ {0x00, 0x11, 0x10, 0x12, 0x00, 0x00, 0x00, 0x00},
+ {0x31, 0x51, 0x41, 0x5a, 0x4b, 0x49, 0x38, 0xbc},
+ {0x32, 0x57, 0x53, 0x58, 0x4c, 0x4f, 0x39, 0xbe},
+ {0x33, 0x45, 0x44, 0x43, 0xbb, 0x50, 0x70, 0xbf},
+ {0x34, 0x52, 0x46, 0x56, 0xba, 0xc0, 0x71, 0xe2},
+ {0x35, 0x54, 0x47, 0x42, 0xdd, 0xdb, 0x72, 0x20},
+ {0x36, 0x59, 0x48, 0x4e, 0xbd, 0xde, 0x73, 0x30},
+ {0x37, 0x55, 0x4a, 0x4d, 0x00, 0xdc, 0x74, 0x00},
+ {0x0d, 0x13, 0x26, 0x28, 0x27, 0x25, 0x09, 0x1b},
+ {0x15, 0x2d, 0x2e, 0x23, 0x24, 0x00, 0x00, 0x00}, // ROT=END
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+};
+
+void SUB::initialize()
+{
+ fio = new FILEIO();
+ rec = false;
+
+ key_stat = emu->get_key_buffer();
+ p1_out = 0x10;
+ p2_in = 0xff;
+ drec_in = rxrdy_in = false;
+ skip = false;
+ update_key = true;
+ register_frame_event(this);
+}
+
+void SUB::release()
+{
+ close_tape();
+ delete fio;
+}
+
+void SUB::reset()
+{
+ close_tape();
+ prev_command = 0;
+}
+
+#define SET_WR(v) d_pio->write_signal(SIG_I8255_PORT_C, (v) ? 0xff : 0, 0x10)
+#define SET_RD(v) d_pio->write_signal(SIG_I8255_PORT_C, (v) ? 0xff : 0, 0x40)
+
+void SUB::write_io8(uint32_t addr, uint32_t data)
+{
+ // FIXME: this function is referred from both 80c48 and z80
+ if((addr & 0xf0) == 0x90) {
+ // Z80
+ if((addr & 0xff) == 0x90) {
+ if(prev_command == 0x38) {
+ if(rec && index < sizeof(buffer)) {
+ buffer[index++] = data;
+ skip = true;
+ }
+ prev_command = 0;
+ } else {
+ switch(data) {
+ case 0x19:
+// d_drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
+ register_event(this, EVENT_PLAY, 1000000.0, false, NULL);
+ break;
+ case 0x1a:
+// d_drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);
+ register_event(this, EVENT_STOP, 1000000.0, false, NULL);
+ break;
+ case 0x1e:
+ case 0x3e:
+ baud = 1200;
+ break;
+ case 0x1d:
+ case 0x3d:
+ baud = 600;
+ break;
+ }
+ prev_command = data;
+ }
+ }
+ d_pio->write_io8(addr, data);
+ } else {
+ // 8048
+ switch(addr) {
+ case MCS48_PORT_P1:
+ if((p1_out & 0x0f) != (data & 0x0f)) {
+ update_key = true;
+ }
+ p1_out = data;
+// d_drec->write_signal(SIG_DATAREC_MIC, data, 0x20);
+ d_timer->write_signal(SIG_TIMER_IRQ_SUB_CPU, ~data, 0x80);
+ break;
+ default:
+ SET_WR(1);
+ SET_WR(0);
+ SET_WR(1);
+ d_pio->write_signal(SIG_I8255_PORT_A, data, 0xff);
+ break;
+ }
+ }
+}
+
+uint32_t SUB::read_io8(uint32_t addr)
+{
+ // FIXME: this function is referred from both 80c48 and z80
+ if((addr & 0xf0) == 0x90) {
+ // Z80
+ if((addr & 0xff) == 0x90) {
+ return d_pio->read_io8(addr);
+ } else {
+ return 0xff;
+ }
+ } else {
+ // 8048
+ switch(addr) {
+ case MCS48_PORT_P2:
+ if(update_key) {
+ int column = p1_out & 0x0f;
+ int val = 0;
+ for(int i = 0; i < 8; i++) {
+ if(key_stat[key_matrix[column][i]]) {
+ val |= 1 << i;
+ }
+ }
+ p2_in = (~val) & 0xff;
+ update_key = false;
+ }
+ if(p1_out & 0x10) {
+ return p2_in;
+ } else {
+ // bit3: signal from datarec
+ // bit1: rxrdy from rs-232c
+ return (rxrdy_in ? 2 : 0) | (drec_in ? 8 : 0) | (p2_in & 0xf0);
+ }
+ case MCS48_PORT_T0:
+ // PC5 -> T0
+ return (d_pio->read_signal(SIG_I8255_PORT_C) >> 5) & 1;
+ default:
+ SET_RD(1);
+ SET_RD(0);
+ SET_RD(1);
+ return d_pio->read_signal(SIG_I8255_PORT_A);
+ }
+ }
+ return 0xff;
+}
+
+uint32_t SUB::get_intr_ack()
+{
+ return d_pio->read_io8(0);
+}
+
+void SUB::event_frame()
+{
+ if(skip) {
+ request_skip_frames();
+ skip = false;
+ }
+ update_key = true;
+}
+
+void SUB::event_callback(int event_id, int err)
+{
+ if(event_id == EVENT_PLAY) {
+ d_drec->write_signal(SIG_DATAREC_REMOTE, 1, 1);
+ } else if(event_id == EVENT_STOP) {
+ d_drec->write_signal(SIG_DATAREC_REMOTE, 0, 0);
+ }
+}
+
+void SUB::write_signal(int id, uint32_t data, uint32_t mask)
+{
+ if(id == SIG_SUB_DATAREC) {
+ drec_in = ((data & mask) != 0);
+ } else if(id == SIG_SUB_RXRDY) {
+ rxrdy_in = ((data & mask) != 0);
+ }
+}
+
+bool SUB::rec_tape(const _TCHAR* file_path)
+{
+ close_tape();
+
+ if(fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
+ my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
+ index = 0;
+ rec = true;
+ is_wav = check_file_extension(file_path, _T(".wav"));
+ is_p6t = check_file_extension(file_path, _T(".p6t"));
+ }
+ return rec;
+}
+
+static const uint8_t pulse_1200hz[40] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static const uint8_t pulse_2400hz[20] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static const uint8_t pulse_2400hz_x2[40] = {
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+void SUB::close_tape()
+{
+ if(fio->IsOpened()) {
+ if(rec) {
+ if(is_wav) {
+ wav_header_t wav_header;
+ wav_chunk_t wav_chunk;
+ int sample_rate = (baud == 600) ? 24000 : 48000;
+
+ fio->Fwrite(&wav_header, sizeof(wav_header), 1);
+ fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
+
+ for(int i = 0; i < 9600; i++) {
+ fio->Fwrite((void *)pulse_2400hz, sizeof(pulse_2400hz), 1);
+ }
+ for(int i = 0; i < 16; i++) {
+ fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
+ for(int j = 0; j < 8; j++) {
+ if(buffer[i] & (1 << j)) {
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ } else {
+ fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
+ }
+ }
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ }
+ // for(int i = 0; i < 1280; i++) {
+ for(int i = 0; i < 2400; i++) {
+ fio->Fwrite((void *)pulse_2400hz, sizeof(pulse_2400hz), 1);
+ }
+ for(int i = 16; i < index; i++) {
+ fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
+ for(int j = 0; j < 8; j++) {
+ if(buffer[i] & (1 << j)) {
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ } else {
+ fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
+ }
+ }
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ }
+#if 1
+ for(int i = 0; i < 16; i++) {
+ fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
+ for(int j = 0; j < 8; j++) {
+ fio->Fwrite((void *)pulse_1200hz, sizeof(pulse_1200hz), 1);
+ }
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ fio->Fwrite((void *)pulse_2400hz_x2, sizeof(pulse_2400hz_x2), 1);
+ }
+#endif
+ uint32_t length = fio->Ftell();
+#if 0
+ pair_t __riff_chunk_size;
+ pair_t __fmt_chunk_size;
+ pair_t __wav_chunk_size;
+ pair16_t __fmt_id;
+ pair16_t __channels;
+ pair_t __sample_rate;
+ pair16_t __block_size;
+ pair16_t __sample_bits;
+
+ __riff_chunk_size.d = length - 8;
+ __fmt_chunk_size.d = 16;
+ __fmt_id.w = 1;
+ __channels.w = 1;
+ __sample_rate.d = sample_rate;
+ __block_size.w = 1;
+ __sample_bits.w = 8;
+
+ memcpy(wav_header.riff_chunk.id, "RIFF", 4);
+ wav_header.riff_chunk.size = __riff_chunk_size.get_4bytes_le_to();
+
+ memcpy(wav_header.wave, "WAVE", 4);
+ memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
+ wav_header.fmt_chunk.size = __riff_chunk_size.get_4bytes_le_to();
+ wav_header.format_id = __fmt_id.get_2bytes_le_to();
+ wav_header.channels = __channels.get_2byte_le_to();
+ wav_header.sample_rate = __sample_rate.get_4bytes_le_to();
+ wav_header.data_speed = __sample_rate.get_4bytes_le_to();
+ wav_header.block_size = __block_size.get_2bytes_le_to();
+ wav_header.sample_bits = __sample_bits_get_2bytes_le_to();
+
+ memcpy(wav_chunk.id, "data", 4);
+ __wav_chunk_size.d = length - sizeof(wav_header) - sizeof(wav_chunk);
+ wav_chunk.size = __wav_chunk_size.get_4bytes_le_to();
+
+ fio->Fseek(0, FILEIO_SEEK_SET);
+ fio->Fwrite(&wav_header, sizeof(wav_header), 1);
+ fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
+#else
+ if(set_wav_header(&wav_header, &wav_chunk, 1, sample_rate, 8, length)) {
+ fio->Fseek(0, FILEIO_SEEK_SET);
+ fio->Fwrite(&wav_header, sizeof(wav_header), 1);
+ fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
+ }
+#endif
+ } else {
+ fio->Fwrite(buffer, index, 1);
+ if(is_p6t) {
+ fio->Fputc('P');
+ fio->Fputc('6');
+ fio->FputUint8(2);
+ fio->FputUint8(2);
+ fio->FputUint8(0);
+ fio->FputUint8(0);
+ fio->FputUint8(0);
+ fio->FputUint16(0);
+ fio->FputUint16(0);
+
+ fio->Fputc('T');
+ fio->Fputc('I');
+ fio->FputUint8(0);
+ for(int i = 0; i < 6; i++) {
+ fio->FputUint8(buffer[10 + i]);
+ }
+ for(int i = 6; i < 16; i++) {
+ fio->FputUint8(0);
+ }
+ fio->FputUint16(baud);
+ fio->FputUint16(3000);
+ fio->FputUint16(4000);
+ fio->FputUint32(0);
+ fio->FputUint32(16);
+
+ fio->Fputc('T');
+ fio->Fputc('I');
+ fio->FputUint8(0);
+ for(int i = 0; i < 16; i++) {
+ fio->FputUint8(0);
+ }
+ fio->FputUint16(baud);
+ fio->FputUint16(0);
+ fio->FputUint16(1000);
+ fio->FputUint32(16);
+ fio->FputUint32(index - 16);
+
+ fio->FputUint32(index);
+ }
+ }
+ }
+ fio->Fclose();
+ }
+ rec = false;
+}
+
+#define STATE_VERSION 1
+
+bool SUB::process_state(FILEIO* state_fio, bool loading)
+{
+ if(!state_fio->StateCheckUint32(STATE_VERSION)) {
+ return false;
+ }
+ if(!state_fio->StateCheckInt32(this_device_id)) {
+ return false;
+ }
+ state_fio->StateInt32(p1_out);
+ state_fio->StateInt32(p2_in);
+ state_fio->StateBool(drec_in);
+ state_fio->StateBool(rxrdy_in);
+ state_fio->StateBool(update_key);
+ state_fio->StateBool(rec);
+ state_fio->StateBool(is_wav);
+ state_fio->StateBool(is_p6t);
+ state_fio->StateBuffer(rec_file_path, sizeof(rec_file_path), 1);
+ if(loading) {
+ int length_tmp = state_fio->FgetInt32_LE();
+ if(rec) {
+ fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
+ while(length_tmp != 0) {
+ uint8_t buffer_tmp[1024];
+ int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
+ state_fio->Fread(buffer_tmp, length_rw, 1);
+ if(fio->IsOpened()) {
+ fio->Fwrite(buffer_tmp, length_rw, 1);
+ }
+ length_tmp -= length_rw;
+ }
+ }
+ } else {
+ if(rec && fio->IsOpened()) {
+ int length_tmp = (int)fio->Ftell();
+ fio->Fseek(0, FILEIO_SEEK_SET);
+ state_fio->FputInt32_LE(length_tmp);
+ while(length_tmp != 0) {
+ uint8_t buffer_tmp[1024];
+ int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
+ fio->Fread(buffer_tmp, length_rw, 1);
+ state_fio->Fwrite(buffer_tmp, length_rw, 1);
+ length_tmp -= length_rw;
+ }
+ } else {
+ state_fio->FputInt32_LE(0);
+ }
+ }
+ state_fio->StateInt32(prev_command);
+ state_fio->StateInt32(baud);
+ state_fio->StateInt32(index);
+ state_fio->StateBool(skip);
+ state_fio->StateBuffer(buffer, sizeof(buffer), 1);
+ return true;
+}