OSDN Git Service

[VM][COMMON_VM] Include IO:: class to common_vm.
[csp-qt/common_source_project-fm7.git] / source / src / vm / upd7220.h
1 /*
2         Skelton for retropc emulator
3
4         Origin : Neko Project 2
5         Author : Takeda.Toshiya
6         Date   : 2006.12.06 -
7
8         [ uPD7220 ]
9 */
10
11 #ifndef _UPD7220_H_
12 #define _UPD7220_H_
13
14 //#include "vm.h"
15 //#include "../emu.h"
16 #include "device.h"
17
18 #define MODE_MIX        ((sync[0] & 0x22) == 0x00)
19 #define MODE_GFX        ((sync[0] & 0x22) == 0x02)
20 #define MODE_CHR        ((sync[0] & 0x22) == 0x20)
21
22 #define RT_MULBIT       15
23 #define RT_TABLEBIT     12
24 #define RT_TABLEMAX     (1 << RT_TABLEBIT)
25
26 #define SIG_UPD7220_CLOCK_FREQ  1
27 #define SIG_UPD7220_EXT_VSYNC   2
28 #define SIG_UPD7220_WIDTH_BYTES 3
29 #define SIG_UPD7220_HEIGHT              4
30 #define SIG_UPD7220_PITCH               5
31 #define SIG_UPD7220_DISP_HEIGHT 6
32 #define SIG_UPD7220_DISP_WIDTH  7
33
34 class RINGBUFFER;
35 class FIFO;
36 class UPD7220 : public DEVICE
37 {
38 protected:
39         // output signals
40         outputs_t outputs_drq;
41         outputs_t outputs_vsync;
42         outputs_t outputs_vblank;
43         
44         // vram
45         DEVICE* d_vram_bus;
46         uint8_t* vram;
47         uint32_t vram_size;
48         uint16_t vram_data_mask;
49
50         // feature flags
51         bool __QC10;
52         bool _UPD7220_MSB_FIRST;
53         bool _UPD7220_UGLY_PC98_HACK;
54         int  _UPD7220_FIXED_PITCH;
55         int  _UPD7220_HORIZ_FREQ;
56         int  _UPD7220_A_VERSION;
57         int  _LINES_PER_FRAME;
58         
59         // regs
60         int cmdreg;
61         uint8_t statreg;
62         
63         // params
64         uint8_t sync[16];
65         int vtotal, vfp, vs, vbp, v1, v2, v3, v4;
66         int hfp, hs, hbp, h1, h2, h3, h4;
67         bool sync_changed;
68         bool master;
69         uint8_t zoom, zr, zw;
70         uint8_t ra[16];
71         uint8_t cs[3];
72         uint8_t cs_ptr;
73         uint8_t csrw_ptr;
74         uint8_t sync_ptr;
75         uint8_t pitch;
76         uint32_t lad;
77         uint8_t vect[11];
78         uint8_t vectw_ptr;
79         int ead, dad;
80         bool wg;
81         
82         uint8_t maskl, maskh;
83         uint8_t mod;
84         bool hsync, hblank;
85         bool vsync, vblank;
86         bool start;
87         int blink_cursor;
88         int blink_attr;
89         int blink_rate;
90         bool low_high;
91         bool cmd_write_done;
92         int width;
93         int height;
94         
95         int cpu_clocks;
96         double frames_per_sec;
97         int lines_per_frame;
98         
99         // ring buffers
100         RINGBUFFER *fo;
101         RINGBUFFER *cmd_fifo;
102
103         // waiting
104         int event_cmdready;
105         uint32_t wrote_bytes;
106         bool cmd_drawing;
107         uint32_t clock_freq;
108         // draw
109         int rt[RT_TABLEMAX + 1];
110         int dx, dy;     // from ead, dad
111         int dir, dif, sl, dc, d, d2, d1, dm;
112         bool dgd;
113         uint16_t pattern;
114         const int vectdir[16][4] = {
115                 { 0, 1, 1, 0}, { 1, 1, 1,-1}, { 1, 0, 0,-1}, { 1,-1,-1,-1},
116                 { 0,-1,-1, 0}, {-1,-1,-1, 1}, {-1, 0, 0, 1}, {-1, 1, 1, 1},
117                 { 0, 1, 1, 1}, { 1, 1, 1, 0}, { 1, 0, 1,-1}, { 1,-1, 0,-1},
118                 { 0,-1,-1,-1}, {-1,-1,-1, 0}, {-1, 0,-1, 1}, {-1, 1, 0, 1}
119         };
120         int horiz_freq, next_horiz_freq;        
121         // command
122         //void check_cmd();
123         //void process_cmd();
124         uint32_t before_addr;
125         uint8_t cache_val;
126         bool first_load;
127         bool sync_mask;
128         
129         void cmd_reset();
130         void cmd_reset2();
131         void cmd_reset3();
132         void cmd_sync();
133         void cmd_master();
134         void cmd_slave();
135         void cmd_start();
136         void cmd_stop();
137         void cmd_zoom();
138         void cmd_scroll();
139         void cmd_csrform();
140         //void cmd_pitch();
141         void cmd_lpen();
142         void cmd_vectw();
143         //void cmd_vecte();
144         //void cmd_texte();
145         void cmd_csrw();
146         void cmd_csrr();
147         void cmd_mask();
148         void cmd_write();
149         void cmd_read();
150         void cmd_dmaw();
151         void cmd_dmar();
152         void cmd_unk_5a();
153         
154         void __FASTCALL cmd_write_sub(uint32_t addr, uint8_t data);
155         void __FASTCALL write_vram(uint32_t addr, uint8_t data);
156         uint8_t __FASTCALL read_vram(uint32_t addr);
157         void update_vect();
158         void reset_vect();
159         
160         void __FASTCALL register_event_wait_cmd(uint32_t bytes);
161
162         void check_cmd();
163         void process_cmd();
164         
165         void draw_vectl();
166         void draw_vectt();
167         void draw_vectc();
168         void draw_vectr();
169         
170         void cmd_vecte();
171         void cmd_texte();
172         void cmd_pitch();
173         
174         void draw_text();
175         inline void __FASTCALL draw_pset(int x, int y);
176         inline void __FASTCALL start_pset();
177         inline void __FASTCALL finish_pset();
178         inline bool __FASTCALL draw_pset_diff(int x, int y);
179         inline void __FASTCALL shift_pattern(int shift);
180         
181 public:
182         UPD7220(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
183         {
184                 initialize_output_signals(&outputs_drq);
185                 initialize_output_signals(&outputs_vsync);
186                 initialize_output_signals(&outputs_vblank);
187                 d_vram_bus = NULL;
188                 vram = NULL;
189                 vram_data_mask = 0xffff;
190                 width = 80;
191                 height = 25; // ToDo
192                 clock_freq = 2500 * 1000; // Hz
193                 set_device_name(_T("uPD7220 GDC"));
194         }
195         ~UPD7220() {}
196         
197         // common functions
198         void initialize();
199         void release();
200         void reset();
201         void __FASTCALL write_dma_io8(uint32_t addr, uint32_t data);
202         uint32_t __FASTCALL read_dma_io8(uint32_t addr);
203         void __FASTCALL write_io8(uint32_t addr, uint32_t data);
204         uint32_t __FASTCALL read_io8(uint32_t addr);
205         void event_pre_frame();
206         void event_frame();
207         void event_vline(int v, int clock);
208         void event_callback(int event_id, int err);
209         void update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame);
210         
211         uint32_t __FASTCALL read_signal(int ch);
212         void __FASTCALL write_signal(int ch, uint32_t data, uint32_t mask);
213
214         bool process_state(FILEIO* state_fio, bool loading);
215
216         
217         // unique functions
218         void set_context_drq(DEVICE* device, int id, uint32_t mask)
219         {
220                 register_output_signal(&outputs_drq, device, id, mask);
221         }
222         void set_context_vsync(DEVICE* device, int id, uint32_t mask)
223         {
224                 register_output_signal(&outputs_vsync, device, id, mask);
225         }
226         void set_context_vblank(DEVICE* device, int id, uint32_t mask)
227         {
228                 register_output_signal(&outputs_vblank, device, id, mask);
229         }
230     void set_vram_ptr(uint8_t* ptr, uint32_t size)
231         {
232                 vram = ptr;
233                 vram_size = size;
234         }
235         void set_vram_ptr(uint8_t* ptr, uint32_t size, uint16_t mask)
236         {
237                 set_vram_ptr(ptr, size);
238                 vram_data_mask = mask;
239         }
240         void set_vram_bus_ptr(DEVICE* device, uint32_t size)
241         {
242                 d_vram_bus = device;
243                 vram_size = size;
244         }
245         void set_vram_bus_ptr(DEVICE* device, uint32_t size, uint16_t mask)
246         {
247                 set_vram_bus_ptr(device, size);
248                 vram_data_mask = mask;
249         }
250         void set_screen_width(int value)
251         {
252                 width = value;
253         }
254         void set_screen_height(int value)
255         {
256                 height = value;
257         }
258         void set_clock_freq(uint32_t hz)
259         {
260                 clock_freq = hz;
261         }
262         uint8_t* get_sync()
263         {
264                 return sync;
265         }
266         uint8_t* get_zoom()
267         {
268                 return &zoom;
269         }
270         uint8_t* get_ra()
271         {
272                 return ra;
273         }
274         uint8_t* get_cs()
275         {
276                 return cs;
277         }
278         int* get_ead()
279         {
280                 return &ead;
281         }
282         bool get_start()
283         {
284                 return start;
285         }
286         uint32_t __FASTCALL cursor_addr(uint32_t mask);
287         int __FASTCALL cursor_top();
288         int __FASTCALL cursor_bottom();
289         bool __FASTCALL attr_blink()
290         {
291                 return (blink_attr < (blink_rate * 3 / 4));
292         }
293         void __FASTCALL set_horiz_freq(int freq)
294         {
295                 next_horiz_freq = freq;
296         }
297 };
298
299
300 inline void  UPD7220::draw_pset(int x, int y)
301 {
302         uint32_t addr = y * width + (x >> 3);
303         if(_UPD7220_UGLY_PC98_HACK) {
304 //              if(addr >= 0x8000) return;
305 //              if((y == 409) && (x >= 384)) return;
306 //              if(y > 409) return;
307 //              if((x < 0) || (y < 0) || (x >= (width << 3))) return;
308 //              addr = addr & 0x7fff;
309         } else {
310                 if((x < 0) || (y < 0) || (x >= (width << 3)) || (y >= height)) return;
311         }
312         uint16_t dot = pattern & 1;
313         pattern = (pattern >> 1) | (dot << 15);
314         uint8_t bit;
315         if(_UPD7220_MSB_FIRST) {
316                 bit = 0x80 >> (x & 7);
317         } else {
318                 bit = 1 << (x & 7);
319         }
320         uint8_t cur = read_vram(addr);
321 //      ead = addr;
322 //      dad = x & 0x0f;
323         
324         switch(mod) {
325         case 0: // replace
326                 write_vram(addr, (cur & ~bit) | (dot ? bit : 0));
327                 break;
328         case 1: // complement
329                 write_vram(addr, (cur & ~bit) | ((cur ^ (dot ? 0xff : 0)) & bit));
330                 break;
331         case 2: // reset
332                 write_vram(addr, cur & (dot ? ~bit : 0xff));
333                 break;
334         case 3: // set
335                 write_vram(addr, cur | (dot ? bit : 0));
336                 break;
337         }
338 }
339
340 inline void UPD7220::start_pset()
341 {
342         before_addr = 0xffffffff;
343         first_load = true;
344         cache_val = 0;
345 }
346
347 inline void UPD7220::finish_pset()
348 {
349         if(!first_load) {
350                 write_vram(before_addr, cache_val);
351                 //wrote_bytes++;
352         }
353         first_load = true;
354         before_addr = 0xffffffff;
355         cache_val = 0;
356 }
357
358 inline void UPD7220::shift_pattern(int shift)
359 {
360         int bits;
361         uint16_t dot;
362         if(shift == 0) {
363                 return;
364         } else if(shift < 0) {
365                 // Left shift
366                 bits = (-shift) % 16;
367                 if(bits == 0) return;
368                 dot = pattern;
369                 dot <<= bits;
370                 pattern >>= (16 - bits);
371                 pattern = (pattern | dot) & 0xffff;
372         } else if(shift > 0) {
373                 // Right shift
374                 bits = shift % 16;
375                 if(bits == 0) return;
376                 dot = pattern;
377                 dot >>= bits;
378                 pattern <<= (16 - bits);
379                 pattern = (pattern | dot) & 0xffff;
380         }
381 }
382         
383
384 inline bool UPD7220::draw_pset_diff(int x, int y)
385 {
386         uint16_t dot = pattern & 1;
387         pattern = (pattern >> 1) | (dot << 15);
388         uint32_t addr = y * width + (x >> 3);
389         uint8_t bit;
390
391 //      if(_UPD7220_UGLY_PC98_HACK) {
392 //              if(addr >= 0x8000) {
393 //              if((y > 409) || ((y == 409) && x >= 384)){
394 //                      finish_pset();
395 //                      return false;
396 //              }
397 //              else if((x < 0) || (y < 0) || (x >= (width << 3))) {
398 //                      finish_pset();
399 //                      return false;
400 //              }
401 //      } else if((x < 0) || (y < 0) || (x >= (width << 3)) || (y >= height)) {
402 //              finish_pset();
403 //              return false;
404 //      }
405         if((first_load) || (addr != before_addr)) {
406                 if(!(first_load)) {
407                         write_vram(before_addr, cache_val);
408                         //wrote_bytes++;
409                 }
410                 cache_val = read_vram(addr);
411         }
412         
413         first_load = false;
414         before_addr = addr;
415 //      ead = addr;
416 //      dad = x & 0x0f;
417         
418         if(_UPD7220_MSB_FIRST) {
419                 bit = 0x80 >> (x & 7);
420         } else {
421                 bit = 1 << (x & 7);
422         }
423         uint8_t cur = cache_val;
424         wrote_bytes++; // OK?
425
426         switch(mod) {
427         case 0: // replace
428                 cache_val = (cur & ~bit) | (dot ? bit : 0);
429                 break;
430         case 1: // complement
431                 cache_val = (cur & ~bit) | ((cur ^ (dot ? 0xff : 0)) & bit);
432                 break;
433         case 2: // reset
434                 cache_val = cur & (dot ? ~bit : 0xff);
435                 break;
436         case 3: // set
437                 cache_val = cur | (dot ? bit : 0);
438                 break;
439         }
440         return true;
441 }
442
443 #endif
444