OSDN Git Service

[VM][General][WIP] Apply new (Upstream 2016-02-21) APIs to VMs.
[csp-qt/common_source_project-fm7.git] / source / src / vm / prnfile.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2015.12.18-
6
7         [ dummy printer ]
8 */
9
10 #include "prnfile.h"
11
12 #define EVENT_BUSY      0
13 #define EVENT_ACK       1
14
15 void PRNFILE::initialize()
16 {
17         fio = new FILEIO();
18         
19         value = busy_id = ack_id = wait_frames = -1;
20 #ifdef PRINTER_STROBE_RISING_EDGE
21         strobe = false;
22 #else
23         strobe = true;
24 #endif
25         res = busy = false;
26         set_busy(false);
27         set_ack(true);
28         
29         register_frame_event(this);
30 }
31
32 void PRNFILE::release()
33 {
34         close_file();
35         delete fio;
36 }
37
38 void PRNFILE::reset()
39 {
40         close_file();
41         
42         busy_id = ack_id = wait_frames = -1;
43         set_busy(false);
44         set_ack(true);
45 }
46
47 void PRNFILE::event_frame()
48 {
49         if(wait_frames > 0 && --wait_frames == 0) {
50                 close_file();
51         }
52 }
53
54 void PRNFILE::write_signal(int id, uint32 data, uint32 mask)
55 {
56         if(id == SIG_PRINTER_DATA) {
57                 if(value == -1) {
58                         value = 0;
59                 }
60                 value &= ~mask;
61                 value |= (data & mask);
62         } else if(id == SIG_PRINTER_STROBE) {
63                 bool new_strobe = ((data & mask) != 0);
64 #ifdef PRINTER_STROBE_RISING_EDGE
65                 bool edge = (!strobe && new_strobe);
66 #else
67                 bool edge = (strobe && !new_strobe);
68 #endif
69                 strobe = new_strobe;
70                 
71                 if(edge && value != -1) {
72                         if(!fio->IsOpened()) {
73                                 open_file();
74                         }
75                         fio->Fputc(value);
76                         
77                         // busy 1msec
78                         if(busy_id != -1) {
79                                 cancel_event(this, busy_id);
80                         }
81                         register_event(this, EVENT_BUSY, 10000.0, false, &busy_id);
82                         set_busy(true);
83                         
84                         // wait 1sec and finish printing
85 #ifdef SUPPORT_VARIABLE_TIMING
86                         wait_frames = (int)(vm->get_frame_rate() * 1.0 + 0.5);
87 #else
88                         wait_frames = (int)(FRAMES_PER_SEC * 1.0 + 0.5);
89 #endif
90                 }
91         } else if(id == SIG_PRINTER_RESET) {
92                 bool new_res = ((data & mask) != 0);
93                 if(res && !new_res) {
94                         reset();
95                 }
96                 res = new_res;
97         }
98 }
99
100 uint32 PRNFILE::read_signal(int ch)
101 {
102         if(ch == SIG_PRINTER_BUSY) {
103                 if(busy) {
104                         if(busy_id != -1) {
105                                 cancel_event(this, busy_id);
106                                 busy_id = -1;
107                         }
108                         set_busy(false);
109                         return 0xffffffff;
110                 }
111         } else if(ch == SIG_PRINTER_ACK) {
112                 if(ack) {
113                         return 0xffffffff;
114                 }
115         }
116         return 0;
117 }
118
119 void PRNFILE::event_callback(int event_id, int err)
120 {
121         if(event_id == EVENT_BUSY) {
122                 busy_id = -1;
123                 set_busy(false);
124         } else if(event_id == EVENT_ACK) {
125                 ack_id = -1;
126                 set_ack(true);
127         }
128 }
129
130 void PRNFILE::set_busy(bool value)
131 {
132         if(busy && !value) {
133                 // ack 10usec
134                 if(ack_id != -1) {
135                         cancel_event(this, ack_id);
136                 }
137                 register_event(this, EVENT_ACK, 10.0, false, &ack_id);
138                 set_ack(false);
139         }
140         busy = value;
141         write_signals(&outputs_busy, busy ? 0xffffffff : 0);
142 }
143
144 void PRNFILE::set_ack(bool value)
145 {
146         ack = value;
147         write_signals(&outputs_ack, ack ? 0xffffffff : 0);
148 }
149
150 void PRNFILE::open_file()
151 {
152         create_date_file_path(file_path, _MAX_PATH, _T("txt"));
153         fio->Fopen(file_path, FILEIO_WRITE_BINARY);
154 }
155
156 void PRNFILE::close_file()
157 {
158         if(fio->IsOpened()) {
159                 // remove if the file size is less than 2 bytes
160                 bool remove = (fio->Ftell() < 2);
161                 fio->Fclose();
162                 if(remove) {
163                         FILEIO::RemoveFile(file_path);
164                 }
165         }
166 }
167
168 #define STATE_VERSION   2
169
170 void PRNFILE::save_state(FILEIO* state_fio)
171 {
172         state_fio->FputUint32(STATE_VERSION);
173         state_fio->FputInt32(this_device_id);
174         
175         state_fio->FputInt32(value);
176         state_fio->FputInt32(busy_id);
177         state_fio->FputInt32(ack_id);
178         state_fio->FputBool(strobe);
179         state_fio->FputBool(res);
180         state_fio->FputBool(busy);
181         state_fio->FputBool(ack);
182 }
183
184 bool PRNFILE::load_state(FILEIO* state_fio)
185 {
186         close_file();
187         
188         if(state_fio->FgetUint32() != STATE_VERSION) {
189                 return false;
190         }
191         if(state_fio->FgetInt32() != this_device_id) {
192                 return false;
193         }
194         value = state_fio->FgetInt32();
195         busy_id = state_fio->FgetInt32();
196         ack_id = state_fio->FgetInt32();
197         strobe = state_fio->FgetBool();
198         res = state_fio->FgetBool();
199         busy = state_fio->FgetBool();
200         ack = state_fio->FgetBool();
201         
202         // post process
203         wait_frames = -1;
204         return true;
205 }
206