src/mess/video/vdc.c
| r905 | r906 | |
| 1 | 1 | #include "driver.h" |
| 2 | 2 | #include "video/vdc.h" |
| 3 | 3 | |
| 4 | /* VDC segments */ |
| 5 | #define STATE_VSW 0 |
| 6 | #define STATE_VDS 1 |
| 7 | #define STATE_VDW 2 |
| 8 | #define STATE_VCR 3 |
| 9 | |
| 4 | 10 | /* todo: replace this with the PAIR structure from 'osd_cpu.h' */ |
| 5 | 11 | typedef union |
| 6 | 12 | { |
| r905 | r906 | |
| 23 | 29 | pair vce_data[512]; /* Palette data */ |
| 24 | 30 | UINT16 sprite_ram[64*4]; /* Sprite RAM */ |
| 25 | 31 | int curline; /* the current scanline we're on */ |
| 32 | int current_bitmap_line; /* the current line in the display we are on */ |
| 33 | int current_segment; /* current segment of display */ |
| 34 | int current_segment_line; /* current line inside a segment of display */ |
| 35 | int vblank_triggered; /* to indicate whether vblank has been triggered */ |
| 36 | int raster_count; /* counter to compare RCR against */ |
| 26 | 37 | UINT8 *vram; |
| 27 | 38 | UINT8 inc; |
| 28 | 39 | UINT8 vdc_register; |
| r905 | r906 | |
| 31 | 42 | int status; |
| 32 | 43 | mame_bitmap *bmp; |
| 33 | 44 | int y_scroll; |
| 34 | | int top_blanking; |
| 35 | | int top_overscan; |
| 36 | | int active_lines; |
| 37 | | int bottomfill; |
| 38 | 45 | }VDC; |
| 39 | 46 | |
| 40 | 47 | static VDC vdc; |
| r905 | r906 | |
| 51 | 58 | { |
| 52 | 59 | int ret = 0; |
| 53 | 60 | |
| 54 | | if(vdc.curline==0) |
| 55 | | { |
| 56 | | //state is now in the VDS region, nothing even tries to draw here. |
| 57 | | vdc.top_blanking=(vdc.vdc_data[VPR].b.l&0x1F)+1; |
| 58 | | vdc.top_overscan=(vdc.vdc_data[VPR].b.h)+2; |
| 59 | | vdc.active_lines = vdc.physical_height = 1 + ( vdc.vdc_data[VDW].w & 0x01FF ); |
| 60 | | vdc.bottomfill=vdc.vdc_data[VCR].b.l; |
| 61 | /* Draw the last scanline */ |
| 62 | if ( vdc.current_bitmap_line >= 14 && vdc.current_bitmap_line < 14 + 242 ) { |
| 63 | /* We are in the active display area */ |
| 64 | if ( vdc.current_segment == STATE_VDW ) { |
| 65 | pce_refresh_line( vdc.current_bitmap_line, vdc.current_segment_line ); |
| 66 | } else { |
| 67 | draw_overscan_line( vdc.current_bitmap_line ); |
| 68 | } |
| 69 | } else { |
| 70 | /* We are in one of the blanking areas */ |
| 71 | draw_black_line( vdc.current_bitmap_line ); |
| 61 | 72 | } |
| 62 | 73 | |
| 63 | | if ( vdc.curline < vdc.top_blanking ) { |
| 64 | | /* We are in the top blanking area */ |
| 65 | | draw_black_line( vdc.curline ); |
| 66 | | } else if ( vdc.curline < vdc.top_blanking + vdc.top_overscan ) { |
| 67 | | /* We are in the top overscan area */ |
| 68 | | draw_overscan_line( vdc.curline ); |
| 69 | | } else if ( vdc.curline < vdc.top_blanking + vdc.top_overscan + vdc.active_lines ) { |
| 70 | | /* We are in the active screen area */ |
| 71 | | pce_refresh_line( vdc.curline, vdc.curline - ( vdc.top_blanking + vdc.top_overscan ) ); |
| 72 | | } else { |
| 73 | | /* We are in the bottom blanking area */ |
| 74 | | draw_overscan_line( vdc.curline ); |
| 74 | /* bump current scanline */ |
| 75 | vdc.current_bitmap_line = ( vdc.current_bitmap_line + 1 ) % VDC_LPF; |
| 76 | vdc.curline += 1; |
| 77 | vdc.current_segment_line += 1; |
| 78 | vdc.raster_count += 1; |
| 79 | |
| 80 | if ( vdc.current_bitmap_line == 0 ) { |
| 81 | vdc.current_segment = STATE_VSW; |
| 82 | vdc.current_segment_line = 0; |
| 83 | vdc.vblank_triggered = 0; |
| 84 | vdc.curline = 0; |
| 75 | 85 | } |
| 76 | 86 | |
| 77 | | /* bump current scanline */ |
| 78 | | vdc.curline = (vdc.curline + 1) % VDC_LPF; |
| 87 | if ( STATE_VSW == vdc.current_segment && vdc.current_segment_line >= ( vdc.vdc_data[VPR].b.l & 0x1F ) ) { |
| 88 | vdc.current_segment = STATE_VDS; |
| 89 | vdc.current_segment_line = 0; |
| 90 | } |
| 79 | 91 | |
| 80 | | if ( vdc.curline == vdc.top_blanking + vdc.top_overscan ) { |
| 92 | if ( STATE_VDS == vdc.current_segment && vdc.current_segment_line >= vdc.vdc_data[VPR].b.h ) { |
| 93 | vdc.current_segment = STATE_VDW; |
| 94 | vdc.current_segment_line = 0; |
| 95 | vdc.raster_count = 0x40; |
| 81 | 96 | vdc.y_scroll = vdc.vdc_data[BYR].w; |
| 82 | 97 | } |
| 83 | 98 | |
| 84 | | if ( vdc.curline == vdc.top_blanking + vdc.top_overscan + vdc.active_lines ) { |
| 85 | | if ( vdc.bottomfill != 0 ) { |
| 86 | | vdc.status |= VDC_VD; |
| 87 | | if ( vdc.vdc_data[CR].w & CR_VR ) |
| 88 | | ret = 1; |
| 99 | if ( STATE_VDW == vdc.current_segment && vdc.current_segment_line > ( vdc.vdc_data[VDW].w & 0x01FF ) ) { |
| 100 | vdc.current_segment = STATE_VCR; |
| 101 | vdc.current_segment_line = 0; |
| 89 | 102 | |
| 90 | | /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */ |
| 91 | | if( ( vdc.vdc_data[DCR].w & DCR_DSR ) || vdc.dvssr_write ) { |
| 92 | | int i; |
| 93 | | if ( vdc.dvssr_write ) |
| 94 | | vdc.dvssr_write = 0; |
| 103 | /* Generate VBlank interrupt, sprite DMA */ |
| 104 | vdc.status |= VDC_VD; |
| 105 | vdc.vblank_triggered = 1; |
| 106 | if ( vdc.vdc_data[CR].w & CR_VR ) |
| 107 | ret = 1; |
| 95 | 108 | |
| 96 | | for( i = 0; i < 256; i++ ) { |
| 97 | | vdc.sprite_ram[i] = ( vdc.vram[ ( vdc.vdc_data[DVSSR].w << 1 ) + i * 2 + 1 ] << 8 ) | vdc.vram[ ( vdc.vdc_data[DVSSR].w << 1 ) + i * 2 ]; |
| 98 | | } |
| 109 | /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */ |
| 110 | if( ( vdc.vdc_data[DCR].w & DCR_DSR ) || vdc.dvssr_write ) { |
| 111 | int i; |
| 99 | 112 | |
| 100 | | vdc.status |= VDC_DS; /* set satb done flag */ |
| 113 | vdc.dvssr_write = 0; |
| 101 | 114 | |
| 102 | | /* generate interrupt if needed */ |
| 103 | | if ( vdc.vdc_data[DCR].w & DCR_DSC ) |
| 104 | | ret = 1; |
| 115 | for( i = 0; i < 256; i++ ) { |
| 116 | vdc.sprite_ram[i] = ( vdc.vram[ ( vdc.vdc_data[DVSSR].w << 1 ) + i * 2 + 1 ] << 8 ) | vdc.vram[ ( vdc.vdc_data[DVSSR].w << 1 ) + i * 2 ]; |
| 105 | 117 | } |
| 118 | |
| 119 | vdc.status |= VDC_DS; /* set satb done flag */ |
| 120 | |
| 121 | /* generate interrupt if needed */ |
| 122 | if ( vdc.vdc_data[DCR].w & DCR_DSC ) |
| 123 | ret = 1; |
| 106 | 124 | } |
| 107 | 125 | } |
| 108 | 126 | |
| 127 | if ( STATE_VCR == vdc.current_segment ) { |
| 128 | if ( vdc.current_segment_line >= 3 && vdc.current_segment_line >= vdc.vdc_data[VCR].b.l ) { |
| 129 | vdc.current_segment = STATE_VSW; |
| 130 | vdc.current_segment_line = 0; |
| 131 | } |
| 132 | } |
| 133 | |
| 109 | 134 | /* generate interrupt on line compare if necessary */ |
| 110 | | if(vdc.vdc_data[CR].w & CR_RC) |
| 111 | | if( vdc.curline == ( ( ( vdc.vdc_data[RCR].w-64 ) + vdc.top_blanking + vdc.top_overscan ) % ( VDC_LPF + 1 ) )) |
| 112 | | { |
| 135 | if ( vdc.raster_count == vdc.vdc_data[RCR].w && vdc.vdc_data[CR].w & CR_RC && vdc.vdc_data[RCR].w < 0x0147 ) { |
| 113 | 136 | vdc.status |= VDC_RR; |
| 114 | 137 | ret = 1; |
| 115 | 138 | } |
| 116 | 139 | |
| 117 | 140 | /* handle frame events */ |
| 118 | | if(vdc.curline == VDC_LPF - 1 && ( vdc.bottomfill == 0 || vdc.top_overscan + vdc.top_blanking + vdc.active_lines >= VDC_LPF ) ) |
| 119 | | { |
| 141 | if(vdc.curline == 261 && ! vdc.vblank_triggered ) { |
| 142 | |
| 120 | 143 | vdc.status |= VDC_VD; /* set vblank flag */ |
| 144 | vdc.vblank_triggered = 1; |
| 145 | if(vdc.vdc_data[CR].w & CR_VR) /* generate IRQ1 if enabled */ |
| 146 | ret = 1; |
| 121 | 147 | |
| 122 | 148 | /* do VRAM > SATB DMA if the enable bit is set or the DVSSR reg. was written to */ |
| 123 | | if((vdc.vdc_data[DCR].w & DCR_DSR) || vdc.dvssr_write) |
| 124 | | { |
| 149 | if ( ( vdc.vdc_data[DCR].w & DCR_DSR ) || vdc.dvssr_write ) { |
| 125 | 150 | int i; |
| 126 | | if(vdc.dvssr_write) vdc.dvssr_write = 0; |
| 151 | |
| 152 | vdc.dvssr_write = 0; |
| 127 | 153 | #ifdef MAME_DEBUG |
| 128 | 154 | assert(((vdc.vdc_data[DVSSR].w<<1) + 512) <= 0x10000); |
| 129 | 155 | #endif |
| r905 | r906 | |
| 135 | 161 | |
| 136 | 162 | /* generate interrupt if needed */ |
| 137 | 163 | if(vdc.vdc_data[DCR].w & DCR_DSC) |
| 138 | | { |
| 139 | 164 | ret = 1; |
| 140 | | } |
| 141 | 165 | } |
| 166 | } |
| 142 | 167 | |
| 143 | | if(vdc.vdc_data[CR].w & CR_VR) /* generate IRQ1 if enabled */ |
| 144 | | { |
| 145 | | ret = 1; |
| 146 | | } |
| 147 | | } |
| 148 | 168 | if (ret) |
| 149 | 169 | cpunum_set_input_line(0, 0, HOLD_LINE); |
| 150 | 170 | } |