OSDN Git Service

[Qt][X1][General] Fix FILEIO::IsFileExists(). Fixed non-start X1 series when not...
[csp-qt/common_source_project-fm7.git] / source / src / vm / x1 / iobus.cpp
1 /*
2         SHARP X1 Emulator 'eX1'
3         SHARP X1twin Emulator 'eX1twin'
4         SHARP X1turbo Emulator 'eX1turbo'
5
6         Author : Takeda.Toshiya
7         Date   : 2009.03.14-
8
9         [ 8bit i/o bus ]
10 */
11
12 #include "iobus.h"
13 #include "io_wait.h"
14 #ifdef _X1TURBO_FEATURE
15 #include "io_wait_hireso.h"
16 #endif
17 #include "display.h"
18
19 void IOBUS::initialize()
20 {
21         prev_clock = vram_wait_index = 0;
22         column40 = true;
23 }
24
25 void IOBUS::reset()
26 {
27         memset(vram, 0, sizeof(vram));
28         vram_b = vram + 0x0000;
29         vram_r = vram + 0x4000;
30         vram_g = vram + 0x8000;
31         vram_mode = signal = false;
32         vdisp = 0;
33 #ifdef _X1TURBO_FEATURE
34         memset(crtc_regs, 0, sizeof(crtc_regs));
35         crtc_ch = 0;
36         hireso = true;
37 #endif
38 }
39
40 void IOBUS::write_signal(int id, uint32 data, uint32 mask)
41 {
42         // H -> L
43         bool next = ((data & 0x20) != 0);
44         if(signal && !next) {
45                 vram_mode = true;
46         }
47         signal = next;
48         column40 = ((data & 0x40) != 0);
49 }
50
51 void IOBUS::write_io8w(uint32 addr, uint32 data, int* wait)
52 {
53         write_port8(addr, data, false, wait);
54 }
55
56 uint32 IOBUS::read_io8w(uint32 addr, int* wait)
57 {
58         return read_port8(addr, false, wait);
59 }
60
61 void IOBUS::write_dma_io8w(uint32 addr, uint32 data, int* wait)
62 {
63         write_port8(addr, data, true, wait);
64 }
65
66 uint32 IOBUS::read_dma_io8w(uint32 addr, int* wait)
67 {
68         return read_port8(addr, true, wait);
69 }
70
71 void IOBUS::write_port8(uint32 addr, uint32 data, bool is_dma, int* wait)
72 {
73         // vram access
74         switch(addr & 0xc000) {
75         case 0x0000:
76                 if(vram_mode) {
77                         vram_b[addr & 0x3fff] = data;
78                         vram_r[addr & 0x3fff] = data;
79                         vram_g[addr & 0x3fff] = data;
80                         *wait = get_vram_wait();
81                         return;
82                 }
83                 break;
84         case 0x4000:
85                 if(vram_mode) {
86                         vram_r[addr & 0x3fff] = data;
87                         vram_g[addr & 0x3fff] = data;
88                 } else {
89                         vram_b[addr & 0x3fff] = data;
90                 }
91                 *wait = get_vram_wait();
92                 return;
93         case 0x8000:
94                 if(vram_mode) {
95                         vram_b[addr & 0x3fff] = data;
96                         vram_g[addr & 0x3fff] = data;
97                 } else {
98                         vram_r[addr & 0x3fff] = data;
99                 }
100                 *wait = get_vram_wait();
101                 return;
102         case 0xc000:
103                 if(vram_mode) {
104                         vram_b[addr & 0x3fff] = data;
105                         vram_r[addr & 0x3fff] = data;
106                 } else {
107                         vram_g[addr & 0x3fff] = data;
108                 }
109                 *wait = get_vram_wait();
110                 return;
111         }
112 #ifdef _X1TURBO_FEATURE
113         if(addr == 0x1fd0) {
114                 int ofs = (data & 0x10) ? 0xc000 : 0;
115                 vram_b = vram + 0x0000 + ofs;
116                 vram_r = vram + 0x4000 + ofs;
117                 vram_g = vram + 0x8000 + ofs;
118         } else if((addr & 0xff0f) == 0x1800) {
119                 crtc_ch = data;
120         } else if((addr & 0xff0f) == 0x1801 && crtc_ch < 18) {
121                 crtc_regs[crtc_ch] = data;
122                 // update vram wait
123                 int ch_height = (crtc_regs[9] & 0x1f) + 1;
124                 int vt_total = ((crtc_regs[4] & 0x7f) + 1) * ch_height + (crtc_regs[5] & 0x1f);
125                 hireso = (vt_total > 400);
126         }
127 #endif
128         //printf("IO WRITE:%04x %02x CPU_PC=%04x\n", addr, data & 0xff, d_cpu->get_pc());
129         if(is_dma) {
130                 d_io->write_dma_io8(addr, data & 0xff);
131         } else {
132                 d_io->write_io8(addr, data & 0xff);
133         }
134         switch(addr & 0xff00) {
135         case 0x1900:    // sub cpu
136         case 0x1b00:    // psg
137         case 0x1c00:    // psg
138                 *wait = 1;
139                 break;
140         default:
141                 *wait = 0;
142                 break;
143         }
144 }
145
146 uint32 IOBUS::read_port8(uint32 addr, bool is_dma, int* wait)
147 {
148         // vram access
149         vram_mode = false;
150         switch(addr & 0xc000) {
151         case 0x4000:
152                 *wait = get_vram_wait();
153                 return vram_b[addr & 0x3fff];
154         case 0x8000:
155                 *wait = get_vram_wait();
156                 return vram_r[addr & 0x3fff];
157         case 0xc000:
158                 *wait = get_vram_wait();
159                 return vram_g[addr & 0x3fff];
160         }
161         uint32 val = is_dma ? d_io->read_dma_io8(addr) : d_io->read_io8(addr);;
162         if((addr & 0xff0f) == 0x1a01) {
163                 // hack: cpu detects vblank
164                 if((vdisp & 0x80) && !(val & 0x80)) {
165                         d_display->write_signal(SIG_DISPLAY_DETECT_VBLANK, 1, 1);
166                 }
167                 vdisp = val;
168         }
169         //printf("IO READ:%04x %02x CPU_PC=%04x\n", addr, val, d_cpu->get_pc());
170         switch(addr & 0xff00) {
171         case 0x1900:    // sub cpu
172         case 0x1b00:    // psg
173         case 0x1c00:    // psg
174                 *wait = 1;
175                 break;
176         default:
177                 *wait = 0;
178                 break;
179         }
180         return val & 0xff;
181 }
182
183 int IOBUS::get_vram_wait()
184 {
185         vram_wait_index += passed_clock(prev_clock);
186         vram_wait_index %= 2112;
187         prev_clock = current_clock();
188 #ifdef _X1TURBO_FEATURE
189         int tmp_index = (vram_wait_index + d_cpu->get_extra_clock()) % 2112; // consider dma access
190         if(hireso) {
191                 return column40 ? vram_wait_40_hireso[tmp_index] : vram_wait_80_hireso[tmp_index];
192         } else
193 #else
194         #define tmp_index vram_wait_index
195 #endif
196         return column40 ? vram_wait_40[tmp_index] : vram_wait_80[tmp_index];
197 }
198
199 #define STATE_VERSION   2
200
201 void IOBUS::save_state(FILEIO* state_fio)
202 {
203         state_fio->FputUint32(STATE_VERSION);
204         state_fio->FputInt32(this_device_id);
205         
206         state_fio->Fwrite(vram, sizeof(vram), 1);
207         state_fio->FputBool(vram_mode);
208         state_fio->FputBool(signal);
209         state_fio->FputInt32((int)(vram_b - vram));
210         state_fio->FputInt32((int)(vram_r - vram));
211         state_fio->FputInt32((int)(vram_g - vram));
212         state_fio->FputUint8(vdisp);
213         state_fio->FputUint32(prev_clock);
214         state_fio->FputUint32(vram_wait_index);
215         state_fio->FputBool(column40);
216 #ifdef _X1TURBO_FEATURE
217         state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
218         state_fio->FputInt32(crtc_ch);
219         state_fio->FputBool(hireso);
220 #endif
221 }
222
223 bool IOBUS::load_state(FILEIO* state_fio)
224 {
225         if(state_fio->FgetUint32() != STATE_VERSION) {
226                 return false;
227         }
228         if(state_fio->FgetInt32() != this_device_id) {
229                 return false;
230         }
231         state_fio->Fread(vram, sizeof(vram), 1);
232         vram_mode = state_fio->FgetBool();
233         signal = state_fio->FgetBool();
234         vram_b = vram + state_fio->FgetInt32();
235         vram_r = vram + state_fio->FgetInt32();
236         vram_g = vram + state_fio->FgetInt32();
237         vdisp = state_fio->FgetUint8();
238         prev_clock = state_fio->FgetUint32();
239         vram_wait_index = state_fio->FgetUint32();
240         column40 = state_fio->FgetBool();
241 #ifdef _X1TURBO_FEATURE
242         state_fio->Fread(crtc_regs, sizeof(crtc_regs), 1);
243         crtc_ch = state_fio->FgetInt32();
244         hireso = state_fio->FgetBool();
245 #endif
246         return true;
247 }
248