OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc8201 / cmt.cpp
index 9e80c69..58c8f4d 100644 (file)
-/*\r
-       NEC PC-8201 Emulator 'ePC-8201'\r
-\r
-       Author : Takeda.Toshiya\r
-       Date   : 2013.04.22-\r
-\r
-       [ cmt (record only) ]\r
-*/\r
-\r
-#include "cmt.h"\r
-#include "../../fileio.h"\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
-#define SAMPLE_RATE 48000\r
-\r
-void CMT::initialize()\r
-{\r
-       fio = new FILEIO();\r
-       rec = remote = false;\r
-}\r
-\r
-void CMT::release()\r
-{\r
-       close_tape();\r
-       delete fio;\r
-}\r
-\r
-void CMT::reset()\r
-{\r
-       close_tape();\r
-       rec = remote = false;\r
-}\r
-\r
-void CMT::write_buffer(uint8 value, int samples)\r
-{\r
-       if(is_wav) {\r
-               for(int i = 0; i < samples; i++) {\r
-                       buffer[bufcnt++] = value;\r
-                       if(bufcnt == sizeof(buffer)) {\r
-                               fio->Fwrite(buffer, sizeof(buffer), 1);\r
-                               bufcnt = 0;\r
-                       }\r
-               }\r
-       } else {\r
-               value = (value > 128) ? 0x80 : 0;\r
-               while(samples > 0) {\r
-                       int s = min(samples, 0x7f);\r
-                       samples -= s;\r
-                       buffer[bufcnt++] = value | s;\r
-                       if(bufcnt == sizeof(buffer)) {\r
-                               fio->Fwrite(buffer, sizeof(buffer), 1);\r
-                               bufcnt = 0;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void CMT::put_signal()\r
-{\r
-       if(rec && remote) {\r
-               uint32 clock = passed_clock(prev_clock);\r
-               if(prev_signal == 1) {\r
-                       // 2400Hz\r
-                       int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5) * 2;\r
-                       for(int i = 0; i < count; i++) {\r
-                               write_buffer(0xff, SAMPLE_RATE / 2400 / 2);\r
-                               write_buffer(0x00, SAMPLE_RATE / 2400 / 2);\r
-                       }\r
-               } else if(prev_signal == -1) {\r
-                       // 1200Hz\r
-                       int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5);\r
-                       for(int i = 0; i < count; i++) {\r
-                               write_buffer(0xff, SAMPLE_RATE / 1200 / 2);\r
-                               write_buffer(0x00, SAMPLE_RATE / 1200 / 2);\r
-                       }\r
-               } else {\r
-                       write_buffer(0x80, SAMPLE_RATE * clock / CPU_CLOCKS);\r
-               }\r
-       }\r
-}\r
-\r
-void CMT::write_signal(int id, uint32 data, uint32 mask)\r
-{\r
-       bool next = ((data & mask) != 0);\r
-       \r
-       if(id == SIG_CMT_REMOTE) {\r
-               if(!remote && next) {\r
-                       // start\r
-                       prev_signal = 0;\r
-                       prev_clock = current_clock();\r
-               } else if(remote && !next) {\r
-                       // stop\r
-                       put_signal();\r
-                       set_skip_frames(false);\r
-               }\r
-               remote = next;\r
-       } else if(id == SIG_CMT_SOD) {\r
-               if(remote) {\r
-                       set_skip_frames(true);\r
-                       put_signal();\r
-               }\r
-               prev_signal = next ? 1 : -1;\r
-               prev_clock = current_clock();\r
-       }\r
-}\r
-\r
-void CMT::rec_tape(_TCHAR* file_path)\r
-{\r
-       close_tape();\r
-       \r
-       if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {\r
-               if(check_file_extension(file_path, _T(".wav"))) {\r
-                       uint8 dummy[sizeof(wav_header_t) + sizeof(wav_chunk_t)];\r
-                       memset(dummy, 0, sizeof(dummy));\r
-                       fio->Fwrite(dummy, sizeof(dummy), 1);\r
-                       is_wav = true;\r
-               }\r
-               bufcnt = 0;\r
-               rec = true;\r
-       }\r
-}\r
-\r
-void CMT::close_tape()\r
-{\r
-       // close file\r
-       if(rec) {\r
-               if(bufcnt) {\r
-                       fio->Fwrite(buffer, bufcnt, 1);\r
-               }\r
-               if(is_wav) {\r
-                       uint32 length = fio->Ftell();\r
-                       \r
-                       wav_header_t wav_header;\r
-                       wav_chunk_t wav_chunk;\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
-               }\r
-               fio->Fclose();\r
-       }\r
-       is_wav = rec = false;\r
-}\r
-\r
+/*
+       NEC PC-8201 Emulator 'ePC-8201'
+
+       Author : Takeda.Toshiya
+       Date   : 2013.04.22-
+
+       [ cmt (record only) ]
+*/
+
+#include "cmt.h"
+
+#define SAMPLE_RATE 48000
+
+namespace PC8201 {
+
+void CMT::initialize()
+{
+       fio = new FILEIO();
+       rec = remote = false;
+}
+
+void CMT::release()
+{
+       close_tape();
+       delete fio;
+}
+
+void CMT::reset()
+{
+       close_tape();
+       rec = remote = false;
+}
+
+void CMT::write_buffer(uint8_t value, int samples)
+{
+       if(is_wav) {
+               for(int i = 0; i < samples; i++) {
+                       buffer[bufcnt++] = value;
+                       if(bufcnt == sizeof(buffer)) {
+                               fio->Fwrite(buffer, sizeof(buffer), 1);
+                               bufcnt = 0;
+                       }
+               }
+       } else {
+               value = (value > 128) ? 0x80 : 0;
+               while(samples > 0) {
+                       int s = min(samples, 0x7f);
+                       samples -= s;
+                       buffer[bufcnt++] = value | s;
+                       if(bufcnt == sizeof(buffer)) {
+                               fio->Fwrite(buffer, sizeof(buffer), 1);
+                               bufcnt = 0;
+                       }
+               }
+       }
+}
+
+void CMT::put_signal()
+{
+       if(rec && remote) {
+               uint32_t clock = get_passed_clock(prev_clock);
+               if(prev_signal == 1) {
+                       // 2400Hz
+                       int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5) * 2;
+                       for(int i = 0; i < count; i++) {
+                               write_buffer(0xff, SAMPLE_RATE / 2400 / 2);
+                               write_buffer(0x00, SAMPLE_RATE / 2400 / 2);
+                       }
+               } else if(prev_signal == -1) {
+                       // 1200Hz
+                       int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5);
+                       for(int i = 0; i < count; i++) {
+                               write_buffer(0xff, SAMPLE_RATE / 1200 / 2);
+                               write_buffer(0x00, SAMPLE_RATE / 1200 / 2);
+                       }
+               } else {
+                       write_buffer(0x80, SAMPLE_RATE * clock / CPU_CLOCKS);
+               }
+       }
+}
+
+void CMT::write_signal(int id, uint32_t data, uint32_t mask)
+{
+       bool next = ((data & mask) != 0);
+       
+       if(id == SIG_CMT_REMOTE) {
+               if(!remote && next) {
+                       // start
+                       prev_signal = 0;
+                       prev_clock = get_current_clock();
+               } else if(remote && !next) {
+                       // stop
+                       put_signal();
+               }
+               remote = next;
+       } else if(id == SIG_CMT_SOD) {
+               if(remote) {
+                       request_skip_frames();
+                       put_signal();
+               }
+               prev_signal = next ? 1 : -1;
+               prev_clock = get_current_clock();
+       }
+}
+
+void CMT::rec_tape(const _TCHAR* file_path)
+{
+       close_tape();
+       
+       if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
+               my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
+               if(check_file_extension(file_path, _T(".wav"))) {
+                       write_dummy_wav_header((void *)fio);
+                       is_wav = true;
+               }
+               bufcnt = 0;
+               rec = true;
+       }
+}
+
+void CMT::close_tape()
+{
+       // close file
+       if(rec) {
+               if(bufcnt) {
+                       fio->Fwrite(buffer, bufcnt, 1);
+               }
+               if(is_wav) {
+                       uint32_t length = fio->Ftell();
+                       wav_header_t wav_header;
+                       wav_chunk_t wav_chunk;
+#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
+               }
+               fio->Fclose();
+       }
+       is_wav = rec = false;
+}
+
+#define STATE_VERSION  1
+
+bool CMT::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->StateBool(is_wav);
+       state_fio->StateBool(rec);
+       state_fio->StateBool(remote);
+       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(bufcnt);
+       state_fio->StateBuffer(buffer, sizeof(buffer), 1);
+       state_fio->StateInt32(prev_signal);
+       state_fio->StateUint32(prev_clock);
+       return true;
+}
+
+}