OSDN Git Service

ba1ee08214bba024221a076e4b4c68855a8469ee
[csp-qt/common_source_project-fm7.git] / source / src / vm / fp1100 / main.cpp
1 /*
2         CASIO FP-1100 Emulator 'eFP-1100'
3
4         Author : Takeda.Toshiya
5         Date   : 2010.06.17-
6
7         [ main pcb ]
8 */
9
10 #include "./main.h"
11 #include "./sub.h"
12
13 #define SET_BANK_W(s, e, w) { \
14         int sb = (s) >> 12, eb = (e) >> 12; \
15         for(int i = sb; i <= eb; i++) { \
16                 if((w) == wdmy) { \
17                         wbank[i] = wdmy; \
18                 } else { \
19                         wbank[i] = (w) + 0x1000 * (i - sb); \
20                 } \
21         } \
22 }
23
24 #define SET_BANK_R(s, e, r, w) { \
25         int sb = (s) >> 12, eb = (e) >> 12; \
26         for(int i = sb; i <= eb; i++) { \
27                 if((r) == rdmy) { \
28                         rbank[i] = rdmy; \
29                 } else { \
30                         rbank[i] = (r) + 0x1000 * (i - sb); \
31                 } \
32                 wait[i] = w; \
33         } \
34 }
35
36 void MAIN::initialize()
37 {
38         memset(rom, 0xff, sizeof(rom));
39         memset(rdmy, 0xff, sizeof(rdmy));
40         
41         FILEIO* fio = new FILEIO();
42         if(fio->Fopen(create_local_path(_T("BASIC.ROM")), FILEIO_READ_BINARY)) {
43                 fio->Fread(rom, sizeof(rom), 1);
44                 fio->Fclose();
45         }
46         delete fio;
47         
48         SET_BANK_W(0x0000, 0xffff, ram);
49         SET_BANK_R(0x0000, 0xffff, ram, 0);
50 }
51
52 void MAIN::reset()
53 {
54         rom_sel = true;
55         update_memory_map();
56         slot_sel = slot_exp[0] = slot_exp[1] = 0;
57         intr_mask = intr_request = intr_in_service = 0;
58 }
59
60 void MAIN::write_data8(uint32_t addr, uint32_t data)
61 {
62         addr &= 0xffff;
63         wbank[addr >> 12][addr & 0xfff] = data;
64 }
65
66 uint32_t MAIN::read_data8(uint32_t addr)
67 {
68         addr &= 0xffff;
69         return rbank[addr >> 12][addr & 0xfff];
70 }
71
72 #ifdef Z80_MEMORY_WAIT
73 void MAIN::write_data8w(uint32_t addr, uint32_t data, int *wait)
74 {
75         *wait = 0;
76         write_data8(addr, data);
77 }
78
79 uint32_t MAIN::read_data8w(uint32_t addr, int *wait)
80 {
81         addr &= 0xffff;
82         *wait = wait[addr >> 12];
83         return read_data8(addr);
84 }
85 #endif
86
87 void MAIN::write_io8(uint32_t addr, uint32_t data)
88 {
89 #ifdef _IO_DEBUG_LOG
90         this->out_debug_log(_T("%06x\tOUT8\t%04x,%02x\n"), get_cpu_pc(0), addr, data);
91 #endif
92         switch(addr & 0xffe0) {
93         case 0xff00:
94         case 0xff20:
95         case 0xff40:
96         case 0xff60:
97                 slot_exp[slot_sel] = data & 0x0f;
98                 break;
99         case 0xff80:
100                 if(intr_mask != data) {
101                         if(!(intr_mask & 0x80) && (data & 0x80)) {
102                                 d_sub->write_signal(SIG_SUB_INT2, 1, 1);
103                                 // FIXME: ugly patch for floppy drives
104                                 intr_request &= ~0x10;
105                         } else if((intr_mask & 0x80) && !(data & 0x80)) {
106                                 d_sub->write_signal(SIG_SUB_INT2, 0, 1);
107                         }
108                         intr_mask = data;
109                         update_intr();
110                 }
111                 break;
112         case 0xffa0:
113                 rom_sel = ((data & 2) == 0);
114                 update_memory_map();
115                 slot_sel = data & 1;
116                 break;
117         case 0xffc0:
118                 d_sub->write_signal(SIG_SUB_COMM, data, 0xff);
119                 break;
120         case 0xffe0:
121                 break;
122         default:
123                 if(slot_exp[slot_sel] < 4) {
124                         d_slot[slot_sel][slot_exp[slot_sel]]->write_io8(addr & 0xffff, data);
125                 }
126                 break;
127         }
128 }
129
130 uint32_t MAIN::read_io8(uint32_t addr)
131 {
132         uint32_t val = 0xff;
133         switch(addr & 0xffe0) {
134         case 0xff80:
135         case 0xffa0:
136         case 0xffc0:
137         case 0xffe0:
138                 val = comm_data;
139                 break;
140         default:
141                 if(slot_exp[slot_sel] < 4) {
142                         val = d_slot[slot_sel][slot_exp[slot_sel]]->read_io8(addr & 0xffff);
143                 }
144                 break;
145         }
146 #ifdef _IO_DEBUG_LOG
147         this->out_debug_log(_T("%06x\tIN8\t%04x = %02x\n"), get_cpu_pc(0), addr, val);
148 #endif
149         return val;
150 }
151
152 #ifdef Z80_IO_WAIT
153 void MAIN::write_io8w(uint32_t addr, uint32_t data, int *wait)
154 {
155         *wait = 1;
156         write_io8(addr, data);
157 }
158
159 uint32_t MAIN::read_io8w(uint32_t addr, int *wait)
160 {
161         *wait = 1;
162         return read_io8(addr);
163 }
164 #endif
165
166 static const uint8_t bits[5] = {
167         0x10, 0x01, 0x02, 0x04, 0x08
168 };
169 static const uint32_t vector[5] = {
170         0xf0, 0xf2, 0xf4, 0xf6, 0xf8
171 };
172
173 void MAIN::write_signal(int id, uint32_t data, uint32_t mask)
174 {
175         switch(id) {
176         case SIG_MAIN_INTS:
177         case SIG_MAIN_INTA:
178         case SIG_MAIN_INTB:
179         case SIG_MAIN_INTC:
180         case SIG_MAIN_INTD:
181                 if(data & mask) {
182                         if(!(intr_request & bits[id])) {
183                                 intr_request |= bits[id];
184                                 update_intr();
185                         }
186                 } else {
187                         if(intr_request & bits[id]) {
188                                 intr_request &= ~bits[id];
189                                 update_intr();
190                         }
191                 }
192                 break;
193         case SIG_MAIN_COMM:
194                 comm_data = data & 0xff;
195                 break;
196         }
197 }
198
199 void MAIN::update_memory_map()
200 {
201         if(rom_sel) {
202                 SET_BANK_R(0x0000, 0x8fff, rom, 24);
203         } else {
204                 SET_BANK_R(0x0000, 0x8fff, ram, 0);
205         }
206 }
207
208 void MAIN::update_intr()
209 {
210         for(int i = 0; i < 5; i++) {
211                 if((intr_request & bits[i]) && (intr_mask & bits[i]) && !(intr_in_service & bits[i])) {
212                         d_cpu->set_intr_line(true, true, 0);
213                         return;
214                 }
215         }
216         d_cpu->set_intr_line(false, true, 0);
217 }
218
219 uint32_t MAIN::get_intr_ack()
220 {
221         for(int i = 0; i < 5; i++) {
222                 if((intr_request & bits[i]) && (intr_mask & bits[i]) && !(intr_in_service & bits[i])) {
223                         intr_request &= ~bits[i];
224                         intr_in_service |= bits[i];
225                         return vector[i];
226                 }
227         }
228         // invalid interrupt status
229         return 0xff;
230 }
231
232 void MAIN::notify_intr_reti()
233 {
234         notify_intr_ei();
235 }
236
237 void MAIN::notify_intr_ei()
238 {
239         // FP-1100 uses EI and RET to leave interrupt routine
240         for(int i = 0; i < 5; i++) {
241                 if(intr_in_service & bits[i]) {
242                         intr_in_service &= ~bits[i];
243                         update_intr();
244                         break;
245                 }
246         }
247 }
248
249 #define STATE_VERSION   3
250
251 #include "../../statesub.h"
252
253 void MAIN::decl_state()
254 {
255         enter_decl_state(STATE_VERSION);
256         
257         DECL_STATE_ENTRY_1D_ARRAY(ram, sizeof(ram));
258         DECL_STATE_ENTRY_UINT8(comm_data);
259         DECL_STATE_ENTRY_BOOL(rom_sel);
260         DECL_STATE_ENTRY_UINT8(slot_sel);
261         DECL_STATE_ENTRY_1D_ARRAY(slot_exp, sizeof(slot_exp));
262         DECL_STATE_ENTRY_UINT8(intr_mask);
263         DECL_STATE_ENTRY_UINT8(intr_request);
264         DECL_STATE_ENTRY_UINT8(intr_in_service);
265
266         leave_decl_state();
267 }
268         
269 void MAIN::save_state(FILEIO* state_fio)
270 {
271         if(state_entry != NULL) {
272                 state_entry->save_state(state_fio);
273         }
274
275 //      state_fio->FputUint32(STATE_VERSION);
276 //      state_fio->FputInt32(this_device_id);
277         
278 //      state_fio->Fwrite(ram, sizeof(ram), 1);
279 //      state_fio->FputUint8(comm_data);
280 //      state_fio->FputBool(rom_sel);
281 //      state_fio->FputUint8(slot_sel);
282 //      state_fio->Fwrite(slot_exp, sizeof(slot_exp), 1);
283 //      state_fio->FputUint8(intr_mask);
284 //      state_fio->FputUint8(intr_request);
285 //      state_fio->FputUint8(intr_in_service);
286 }
287
288 bool MAIN::load_state(FILEIO* state_fio)
289 {
290         bool mb = false;
291         if(state_entry != NULL) {
292                 mb = state_entry->load_state(state_fio);
293         }
294         if(!mb) {
295                 return false;
296         }
297
298 //      if(state_fio->FgetUint32() != STATE_VERSION) {
299 //              return false;
300 //      }
301 //      if(state_fio->FgetInt32() != this_device_id) {
302 //              return false;
303 //      }
304 //      state_fio->Fread(ram, sizeof(ram), 1);
305 //      comm_data = state_fio->FgetUint8();
306 //      rom_sel = state_fio->FgetBool();
307 //      slot_sel = state_fio->FgetUint8();
308 //      state_fio->Fread(slot_exp, sizeof(slot_exp), 1);
309 //      intr_mask = state_fio->FgetUint8();
310 //      intr_request = state_fio->FgetUint8();
311 //      intr_in_service = state_fio->FgetUint8();
312         
313         // post process
314         update_memory_map();
315         return true;
316 }
317
318 bool MAIN::process_state(FILEIO* state_fio, bool loading)
319 {
320         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
321                 return false;
322         }
323         if(!state_fio->StateCheckInt32(this_device_id)) {
324                 return false;
325         }
326         state_fio->StateBuffer(ram, sizeof(ram), 1);
327         state_fio->StateUint8(comm_data);
328         state_fio->StateBool(rom_sel);
329         state_fio->StateUint8(slot_sel);
330         state_fio->StateBuffer(slot_exp, sizeof(slot_exp), 1);
331         state_fio->StateUint8(intr_mask);
332         state_fio->StateUint8(intr_request);
333         state_fio->StateUint8(intr_in_service);
334         
335         // post process
336         if(loading) {
337                 update_memory_map();
338         }
339         return true;
340 }