2 Skelton for retropc emulator
4 Origin : Neko Project 2
5 Author : Takeda.Toshiya
14 // -> See also: upd7220_base.cpp .
16 #define EVENT_HSYNC_HFP 0
17 #define EVENT_HSYNC_HS 1
18 #define EVENT_HSYNC_HBP 2
32 void UPD7220_BASE::initialize()
35 for(int i = 0; i <= RT_TABLEMAX; i++) {
36 rt[i] = (int)((double)(1 << RT_MULBIT) * (1 - sqrt(1 - pow((0.70710678118654 * i) / RT_TABLEMAX, 2))));
38 fo = new FIFO(0x10000);
40 vsync = vblank = false;
41 hsync = hblank = false;
48 void UPD7220_BASE::release()
54 void UPD7220_BASE::reset()
59 void UPD7220_BASE::write_dma_io8(uint32_t addr, uint32_t data)
62 switch(cmdreg & 0x18) {
63 case 0x00: // low and high
65 cmd_write_sub(ead * 2 + 1, data & maskh);
68 cmd_write_sub(ead * 2 + 0, data & maskl);
72 case 0x10: // low byte
73 cmd_write_sub(ead * 2 + 0, data & maskl);
76 case 0x18: // high byte
77 cmd_write_sub(ead * 2 + 1, data & maskh);
83 uint32_t UPD7220_BASE::read_dma_io8(uint32_t addr)
88 switch(cmdreg & 0x18) {
89 case 0x00: // low and high
91 val = read_vram(ead * 2 + 1);
94 val = read_vram(ead * 2 + 0);
98 case 0x10: // low byte
99 val = read_vram(ead * 2 + 0);
102 case 0x18: // high byte
103 val = read_vram(ead * 2 + 1);
110 void UPD7220_BASE::write_io8(uint32_t addr, uint32_t data)
115 uint32_t UPD7220_BASE::read_io8(uint32_t addr)
123 val |= vblank ? STAT_BLANK : 0;
125 val |= hblank ? STAT_BLANK : 0;
127 val |= vsync ? STAT_VSYNC : 0;
128 // val |= (params_count == 0) ? STAT_EMPTY : 0;
130 val |= (params_count == 16) ? STAT_FULL : 0;
131 val |= fo->count() ? STAT_DRDY : 0;
133 statreg &= ~(STAT_DMA | STAT_DRAW);
144 void UPD7220_BASE::event_pre_frame()
149 void UPD7220_BASE::update_timing(int new_clocks, double new_frames_per_sec, int new_lines_per_frame)
151 cpu_clocks = new_clocks;
152 frames_per_sec = new_frames_per_sec; // note: refer these params given from the event manager
153 lines_per_frame = new_lines_per_frame; // because this device may be slave gdc
155 // update event clocks
159 void UPD7220_BASE::event_frame()
162 vfp = (int)((double)lines_per_frame * (double)(v1 ) / (double)(v1 + v2 + v3 + v4) + 0.5);
163 vs = (int)((double)lines_per_frame * (double)(v1 + v2 ) / (double)(v1 + v2 + v3 + v4) + 0.5);
164 vbp = (int)((double)lines_per_frame * (double)(v1 + v2 + v3) / (double)(v1 + v2 + v3 + v4) + 0.5);
165 hfp = (int)((double)cpu_clocks * (double)(h1 ) / frames_per_sec / (double)lines_per_frame / (double)(h1 + h2 + h3 + h4) + 0.5);
166 hs = (int)((double)cpu_clocks * (double)(h1 + h2 ) / frames_per_sec / (double)lines_per_frame / (double)(h1 + h2 + h3 + h4) + 0.5);
167 hbp = (int)((double)cpu_clocks * (double)(h1 + h2 + h3) / frames_per_sec / (double)lines_per_frame / (double)(h1 + h2 + h3 + h4) + 0.5);
169 if(++blink_cursor >= blink_rate * 4) {
172 if(++blink_attr >= blink_rate * 2) {
177 void UPD7220_BASE::event_vline(int v, int clock)
181 } else if(v == vfp) {
182 write_signals(&outputs_vsync, 0xffffffff);
185 write_signals(&outputs_vsync, 0);
187 } else if(v == vbp) {
191 register_event_by_clock(this, EVENT_HSYNC_HFP, hfp, false, NULL);
192 register_event_by_clock(this, EVENT_HSYNC_HS, hs, false, NULL);
193 register_event_by_clock(this, EVENT_HSYNC_HBP, hbp, false, NULL);
196 void UPD7220_BASE::event_callback(int event_id, int err)
198 if(event_id == EVENT_HSYNC_HFP) {
200 } else if(event_id == EVENT_HSYNC_HS) {
202 } else if(event_id == EVENT_HSYNC_HBP) {
207 uint32_t UPD7220_BASE::cursor_addr(uint32_t mask)
209 if((cs[0] & 0x80) && ((cs[1] & 0x20) || (blink_cursor < blink_rate * 2))) {
210 return (ead << 1) & mask;
215 int UPD7220_BASE::cursor_top()
220 int UPD7220_BASE::cursor_bottom()
227 void UPD7220_BASE::cmd_reset()
233 ra[0] = ra[1] = ra[2] = 0;
234 ra[3] = 0x1e; /*0x19;*/
235 cs[0] = cs[1] = cs[2] = 0;
237 maskl = maskh = 0xff;
247 // stop display and drawing
251 cmd_write_done = false;
254 void UPD7220_BASE::cmd_sync()
256 start = ((cmdreg & 1) != 0);
257 for(int i = 0; i < 8 && i < params_count; i++) {
258 if(sync[i] != params[i]) {
266 void UPD7220_BASE::cmd_master()
272 void UPD7220_BASE::cmd_slave()
278 void UPD7220_BASE::cmd_start()
284 void UPD7220_BASE::cmd_stop()
290 void UPD7220_BASE::cmd_zoom()
292 if(params_count > 0) {
293 uint8_t tmp = params[0];
300 void UPD7220_BASE::cmd_scroll()
302 if(params_count > 0) {
303 ra[cmdreg & 0x0f] = params[0];
313 void UPD7220_BASE::cmd_csrform()
315 for(int i = 0; i < params_count; i++) {
318 if(params_count > 2) {
321 blink_rate = (cs[1] >> 6) | ((cs[2] & 7) << 2);
324 void UPD7220_BASE::cmd_lpen()
326 fo->write(lad & 0xff);
327 fo->write((lad >> 8) & 0xff);
328 fo->write((lad >> 16) & 0xff);
332 void UPD7220_BASE::cmd_vectw()
334 for(int i = 0; i < 11 && i < params_count; i++) {
336 // this->out_debug_log(_T("\tVECT[%d] = %2x\n"), i, vect[i]);
343 void UPD7220_BASE::cmd_csrw()
345 if(params_count > 0) {
347 if(params_count > 1) {
348 ead |= params[1] << 8;
349 if(params_count > 2) {
350 ead |= params[2] << 16;
354 dad = (ead >> 20) & 0x0f;
359 void UPD7220_BASE::cmd_csrr()
361 fo->write(ead & 0xff);
362 fo->write((ead >> 8) & 0xff);
363 fo->write((ead >> 16) & 0x03);
364 fo->write(dad & 0xff);
365 fo->write((dad >> 8) & 0xff);
369 void UPD7220_BASE::cmd_mask()
371 if(params_count > 1) {
378 void UPD7220_BASE::cmd_write()
381 switch(cmdreg & 0x18) {
382 case 0x00: // low and high
383 if(params_count > 1) {
384 uint8_t l = params[0] & maskl;
385 uint8_t h = params[1] & maskh;
386 for(int i = 0; i < dc + 1; i++) {
387 cmd_write_sub(ead * 2 + 0, l);
388 cmd_write_sub(ead * 2 + 1, h);
391 cmd_write_done = true;
395 case 0x10: // low byte
396 if(params_count > 0) {
397 uint8_t l = params[0] & maskl;
398 for(int i = 0; i < dc + 1; i++) {
399 cmd_write_sub(ead * 2 + 0, l);
402 cmd_write_done = true;
406 case 0x18: // high byte
407 if(params_count > 0) {
408 uint8_t h = params[0] & maskh;
409 for(int i = 0; i < dc + 1; i++) {
410 cmd_write_sub(ead * 2 + 1, h);
413 cmd_write_done = true;
423 void UPD7220_BASE::cmd_read()
426 switch(cmdreg & 0x18) {
427 case 0x00: // low and high
428 for(int i = 0; i < dc; i++) {
429 fo->write(read_vram(ead * 2 + 0));
430 fo->write(read_vram(ead * 2 + 1));
434 case 0x10: // low byte
435 for(int i = 0; i < dc; i++) {
436 fo->write(read_vram(ead * 2 + 0));
440 case 0x18: // high byte
441 for(int i = 0; i < dc; i++) {
442 fo->write(read_vram(ead * 2 + 1));
453 void UPD7220_BASE::cmd_dmaw()
457 write_signals(&outputs_drq, 0xffffffff);
459 // statreg |= STAT_DMA;
463 void UPD7220_BASE::cmd_dmar()
467 write_signals(&outputs_drq, 0xffffffff);
469 // statreg |= STAT_DMA;
473 void UPD7220_BASE::cmd_unk_5a()
475 if(params_count > 2) {
482 void UPD7220_BASE::cmd_write_sub(uint32_t addr, uint8_t data)
486 write_vram(addr, data);
488 case 1: // complement
489 write_vram(addr, read_vram(addr) ^ data);
492 write_vram(addr, read_vram(addr) & ~data);
495 write_vram(addr, read_vram(addr) | data);
500 void UPD7220_BASE::write_vram(uint32_t addr, uint8_t data)
502 if(addr < vram_size) {
505 } else if(d_vram_bus != NULL) {
506 d_vram_bus->write_dma_io8(addr, data);
511 uint8_t UPD7220_BASE::read_vram(uint32_t addr)
513 if(addr < vram_size) {
514 uint8_t mask = (addr & 1) ? (vram_data_mask >> 8) : (vram_data_mask & 0xff);
516 return (vram[addr] & mask) | ~mask;
517 } else if(d_vram_bus != NULL) {
518 return (d_vram_bus->read_dma_io8(addr) & mask) | ~mask;
524 void UPD7220_BASE::update_vect()
527 dif = vectdir[dir][0] + vectdir[dir][1] * pitch;
529 dc = (vect[1] | (vect[ 2] << 8)) & 0x3fff;
530 d = (vect[3] | (vect[ 4] << 8)) & 0x3fff;
531 d2 = (vect[5] | (vect[ 6] << 8)) & 0x3fff;
532 d1 = (vect[7] | (vect[ 8] << 8)) & 0x3fff;
533 dm = (vect[9] | (vect[10] << 8)) & 0x3fff;
536 void UPD7220_BASE::reset_vect()