OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / tk80bs / cmt.cpp
1 /*
2         NEC TK-80BS (COMPO BS/80) Emulator 'eTK-80BS'
3         NEC TK-80 Emulator 'eTK-80'
4
5         Author : Takeda.Toshiya
6         Date   : 2008.08.26 -
7
8         [ cmt ]
9 */
10
11 #include "cmt.h"
12 #include "../datarec.h"
13 #if defined(_TK80BS)
14 #include "../i8251.h"
15 #endif
16 #include "../i8255.h"
17
18 #define EVENT_PULSE     0
19
20 namespace TK80 {
21         
22 void CMT::initialize()
23 {
24         mic = ear = pulse = false;
25         pulse_count = 0;
26         register_event(this, EVENT_PULSE, 1000000 / 4000, true, NULL);
27         
28 #if defined(_TK80BS)
29         fio = new FILEIO();
30         play = rec = false;
31 #endif
32 }
33
34 #if defined(_TK80BS)
35 void CMT::release()
36 {
37         release_tape();
38         delete fio;
39 }
40
41 void CMT::reset()
42 {
43         close_tape();
44         play = rec = false;
45 }
46 #endif
47
48 void CMT::write_signal(int id, uint32_t data, uint32_t mask)
49 {
50         if(id == SIG_CMT_MIC) {
51                 // recv mic signal from pio
52                 mic = ((data & mask) != 0);
53         } else if(id == SIG_CMT_EAR) {
54                 // recv ear signal from datarec
55                 bool next = ((data & mask) != 0);
56                 if(ear != next) {
57                         pulse_count = 0;
58                         ear = next;
59                 }
60 #if defined(_TK80BS)
61         } else if(id == SIG_CMT_OUT) {
62                 // recv data from sio
63                 if(rec) {
64                         buffer[bufcnt++] = data & mask;
65                         if(bufcnt >= BUFFER_SIZE) {
66                                 fio->Fwrite(buffer, bufcnt, 1);
67                                 bufcnt = 0;
68                         }
69                 }
70 #endif
71         }
72 }
73
74 void CMT::event_callback(int event_id, int err)
75 {
76         // send mic signal to datarec
77         d_drec->write_signal(SIG_DATAREC_MIC, (mic && pulse) ? 1 : 0, 1);
78         pulse = !pulse;
79         
80         // send ear signal to pio
81         if(pulse_count > 4) {
82                 // ear signal is not changed for 1 msec or more
83                 d_pio->write_signal(SIG_I8255_PORT_B, 0, 1);
84         } else {
85                 d_pio->write_signal(SIG_I8255_PORT_B, 1, 1);
86                 pulse_count++;
87         }
88 }
89
90 #if defined(_TK80BS)
91 void CMT::play_tape(const _TCHAR* file_path)
92 {
93         close_tape();
94         
95         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
96                 fio->Fseek(0, FILEIO_SEEK_END);
97                 int size = (fio->Ftell() + 9) & (BUFFER_SIZE - 1);
98                 fio->Fseek(0, FILEIO_SEEK_SET);
99                 memset(buffer, 0, sizeof(buffer));
100                 fio->Fread(buffer, sizeof(buffer), 1);
101                 fio->Fclose();
102                 
103                 // send data to sio
104                 // this implement does not care the sio buffer size... :-(
105                 for(int i = 0; i < size; i++) {
106                         d_sio->write_signal(SIG_I8251_RECV, buffer[i], 0xff);
107                 }
108                 play = true;
109         }
110 }
111
112 void CMT::rec_tape(const _TCHAR* file_path)
113 {
114         close_tape();
115         
116         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
117                 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
118                 bufcnt = 0;
119                 rec = true;
120         }
121 }
122
123 void CMT::close_tape()
124 {
125         // close file
126         release_tape();
127         
128         // clear sio buffer
129         d_sio->write_signal(SIG_I8251_CLEAR, 0, 0);
130 }
131
132 void CMT::release_tape()
133 {
134         // close file
135         if(fio->IsOpened()) {
136                 if(rec && bufcnt) {
137                         fio->Fwrite(buffer, bufcnt, 1);
138                 }
139                 fio->Fclose();
140         }
141         play = rec = false;
142 }
143 #endif
144
145 #define STATE_VERSION   2
146
147 bool CMT::process_state(FILEIO* state_fio, bool loading)
148 {
149         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
150                 return false;
151         }
152         if(!state_fio->StateCheckInt32(this_device_id)) {
153                 return false;
154         }
155         state_fio->StateBool(mic);
156         state_fio->StateBool(ear);
157         state_fio->StateBool(pulse);
158         state_fio->StateInt32(pulse_count);
159 #if defined(_TK80BS)
160         state_fio->StateBool(play);
161         state_fio->StateBool(rec);
162         state_fio->StateBuffer(rec_file_path, sizeof(rec_file_path), 1);
163         if(loading) {
164                 int length_tmp = state_fio->FgetInt32_LE();
165                 if(rec) {
166                         fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
167                         while(length_tmp != 0) {
168                                 uint8_t buffer_tmp[1024];
169                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
170                                 state_fio->Fread(buffer_tmp, length_rw, 1);
171                                 if(fio->IsOpened()) {
172                                         fio->Fwrite(buffer_tmp, length_rw, 1);
173                                 }
174                                 length_tmp -= length_rw;
175                         }
176                 }
177         } else {
178                 if(rec && fio->IsOpened()) {
179                         int length_tmp = (int)fio->Ftell();
180                         fio->Fseek(0, FILEIO_SEEK_SET);
181                         state_fio->FputInt32_LE(length_tmp);
182                         while(length_tmp != 0) {
183                                 uint8_t buffer_tmp[1024];
184                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
185                                 fio->Fread(buffer_tmp, length_rw, 1);
186                                 state_fio->Fwrite(buffer_tmp, length_rw, 1);
187                                 length_tmp -= length_rw;
188                         }
189                 } else {
190                         state_fio->FputInt32_LE(0);
191                 }
192         }
193         state_fio->StateInt32(bufcnt);
194         state_fio->StateBuffer(buffer, sizeof(buffer), 1);
195 #endif
196         return true;
197 }
198
199 }