src/mess/video/crt9007.c
| r7485 | r7486 | |
| 1 | 1 | /**********************************************************************
|
| 2 | 2 | |
| 3 | | SMC CRT9007 CRT Video Processor and Controller VPAC emulation
|
| 3 | SMC CRT9007 CRT Video Processor and Controller (VPAC) emulation
|
| 4 | 4 | |
| 5 | 5 | Copyright MESS Team.
|
| 6 | 6 | Visit http://mamedev.org for licensing and usage restrictions.
|
| 7 | 7 | |
| 8 | 8 | **********************************************************************/
|
| 9 | 9 | |
| 10 | /*
|
| 11 | |
| 12 | TODO:
|
| 13 | |
| 14 | - interrupts
|
| 15 | - status register
|
| 16 | - reset
|
| 17 | - DMA mode (currently forcing to non-DMA mode)
|
| 18 | - cursor/blank skew
|
| 19 | - sequential breaks
|
| 20 | - interlaced mode
|
| 21 | - smooth scroll
|
| 22 | - page blank
|
| 23 | - double height cursor
|
| 24 | - row attributes
|
| 25 | - pin configuration
|
| 26 | - operation modes 0,4,7
|
| 27 | - address modes 1,2,3
|
| 28 | - light pen
|
| 29 | - variable clock frequency
|
| 30 | - variable hpixels_per_column
|
| 31 | - state saving
|
| 32 | |
| 33 | */
|
| 34 | |
| 10 | 35 | #include "emu.h"
|
| 11 | 36 | #include "crt9007.h"
|
| 12 | 37 | |
| r7485 | r7486 | |
| 16 | 41 | |
| 17 | 42 | #define LOG 1
|
| 18 | 43 | |
| 44 | #define HAS_VALID_PARAMETERS \
|
| 45 | (crt9007->reg[0x00] && crt9007->reg[0x01] && crt9007->reg[0x07] && crt9007->reg[0x08] && crt9007->reg[0x09])
|
| 46 | |
| 47 | #define CHARACTERS_PER_HORIZONTAL_PERIOD \
|
| 48 | crt9007->reg[0x00]
|
| 49 | |
| 50 | #define CHARACTERS_PER_DATA_ROW \
|
| 51 | (crt9007->reg[0x01] + 1)
|
| 52 | |
| 53 | #define HORIZONTAL_DELAY \
|
| 54 | crt9007->reg[0x02]
|
| 55 | |
| 56 | #define HORIZONTAL_SYNC_WIDTH \
|
| 57 | crt9007->reg[0x03]
|
| 58 | |
| 59 | #define VERTICAL_SYNC_WIDTH \
|
| 60 | crt9007->reg[0x04]
|
| 61 | |
| 62 | #define VERTICAL_DELAY \
|
| 63 | (crt9007->reg[0x05] - 1)
|
| 64 | |
| 65 | #define PIN_CONFIGURATION \
|
| 66 | (crt9007->reg[0x06] >> 6)
|
| 67 | |
| 68 | #define CURSOR_SKEW \
|
| 69 | ((crt9007->reg[0x06] >> 3) & 0x07)
|
| 70 | |
| 71 | #define BLANK_SKEW \
|
| 72 | (crt9007->reg[0x06] & 0x07)
|
| 73 | |
| 74 | #define VISIBLE_DATA_ROWS_PER_FRAME \
|
| 75 | (crt9007->reg[0x07] + 1)
|
| 76 | |
| 77 | #define SCAN_LINES_PER_DATA_ROW \
|
| 78 | ((crt9007->reg[0x08] & 0x1f) + 1)
|
| 79 | |
| 80 | #define SCAN_LINES_PER_FRAME \
|
| 81 | (((crt9007->reg[0x08] << 3) & 0xff00) | crt9007->reg[0x09])
|
| 82 | |
| 83 | #define DMA_BURST_COUNT \
|
| 84 | (crt9007->reg[0x0a] & 0x0f)
|
| 85 | |
| 86 | #define DMA_BURST_DELAY \
|
| 87 | ((crt9007->reg[0x0a] >> 4) & 0x07)
|
| 88 | |
| 89 | #define DMA_DISABLE \
|
| 90 | BIT(crt9007->reg[0x0a], 7)
|
| 91 | |
| 92 | #define OPERATION_MODE \
|
| 93 | ((crt9007->reg[0x0b] >> 1) & 0x07)
|
| 94 | |
| 95 | #define INTERLACE_MODE \
|
| 96 | ((crt9007->reg[0x0b] >> 4) & 0x03)
|
| 97 | |
| 98 | #define TABLE_START \
|
| 99 | (((crt9007->reg[0x0d] << 8) & 0x3f00) | crt9007->reg[0x0c])
|
| 100 | |
| 101 | #define ADDRESS_MODE \
|
| 102 | ((crt9007->reg[0x0d] >> 6) & 0x03)
|
| 103 | |
| 104 | #define AUXILIARY_ADDRESS_1 \
|
| 105 | (((crt9007->reg[0x0f] << 8) & 0x3f00) | crt9007->reg[0x0e])
|
| 106 | |
| 107 | #define SEQUENTIAL_BREAK_1 \
|
| 108 | crt9007->reg[0x10]
|
| 109 | |
| 110 | #define SEQUENTIAL_BREAK_2 \
|
| 111 | crt9007->reg[0x12]
|
| 112 | |
| 113 | #define DATA_ROW_START \
|
| 114 | crt9007->reg[0x11]
|
| 115 | |
| 116 | #define DATA_ROW_END \
|
| 117 | crt9007->reg[0x12]
|
| 118 | |
| 119 | #define AUXILIARY_ADDRESS_2 \
|
| 120 | (((crt9007->reg[0x14] << 8) & 0x3f00) | crt9007->reg[0x13])
|
| 121 | |
| 122 | #define SMOOTH_SCROLL_OFFSET \
|
| 123 | ((crt9007->reg[0x17] >> 1) & 0x3f)
|
| 124 | |
| 125 | #define SMOOTH_SCROLL_OFFSET_OVERFLOW \
|
| 126 | BIT(crt9007->reg[0x17], 7)
|
| 127 | |
| 128 | #define VERTICAL_CURSOR \
|
| 129 | crt9007->reg[0x18]
|
| 130 | |
| 131 | #define HORIZONTAL_CURSOR \
|
| 132 | crt9007->reg[0x19]
|
| 133 | |
| 134 | #define FRAME_TIMER \
|
| 135 | BIT(crt9007->reg[0x1a], 0)
|
| 136 | |
| 137 | #define LIGHT_PEN_INTERRUPT \
|
| 138 | BIT(crt9007->reg[0x1a], 5)
|
| 139 | |
| 140 | #define VERTICAL_RETRACE_INTERRUPT \
|
| 141 | BIT(crt9007->reg[0x1a], 6)
|
| 142 | |
| 143 | #define VERTICAL_LIGHT_PEN \
|
| 144 | crt9007->reg[0x3b]
|
| 145 | |
| 146 | #define HORIZONTAL_LIGHT_PEN \
|
| 147 | crt9007->reg[0x3c]
|
| 148 | |
| 149 | enum
|
| 150 | {
|
| 151 | NON_INTERLACED = 0,
|
| 152 | ENHANCED_VIDEO_INTERFACE,
|
| 153 | NORMAL_VIDEO_INTERFACE,
|
| 154 | };
|
| 155 | |
| 156 | enum
|
| 157 | {
|
| 158 | OPERATION_MODE_REPETITIVE_MEMORY_ADDRESSING = 0,
|
| 159 | OPERATION_MODE_DOUBLE_ROW_BUFFER,
|
| 160 | OPERATION_MODE_SINGLE_ROW_BUFFER = 4,
|
| 161 | OPERATION_MODE_ATTRIBUTE_ASSEMBLE = 7
|
| 162 | };
|
| 163 | |
| 164 | enum
|
| 165 | {
|
| 166 | ADDRESS_MODE_SEQUENTIAL_ADDRESSING = 0,
|
| 167 | ADDRESS_MODE_SEQUENTIAL_ROLL_ADDRESSING,
|
| 168 | ADDRESS_MODE_CONTIGUOUS_ROW_TABLE,
|
| 169 | ADDRESS_MODE_LINKED_LIST_ROW_TABLE
|
| 170 | };
|
| 171 | |
| 172 | #define STATUS_INTERRUPT_PENDING 0x80
|
| 173 | #define STATUS_VERTICAL_RETRACE 0x40
|
| 174 | #define STATUS_LIGHT_PEN_UPDATE 0x20
|
| 175 | #define STATUS_ODD_EVEN 0x04
|
| 176 | #define STATUS_FRAME_TIMER_OCCURRED 0x01
|
| 177 | |
| 19 | 178 | /***************************************************************************
|
| 20 | 179 | TYPE DEFINITIONS
|
| 21 | 180 | ***************************************************************************/
|
| r7485 | r7486 | |
| 29 | 188 | devcb_resolved_write_line out_vs_func;
|
| 30 | 189 | devcb_resolved_read8 in_vd_func;
|
| 31 | 190 | |
| 32 | | UINT8 reg[64];
|
| 191 | crt9007_draw_scanline_func draw_scanline_func;
|
| 192 | |
| 193 | running_device *screen; /* screen */
|
| 194 | |
| 195 | /* registers */
|
| 196 | UINT8 reg[0x3d];
|
| 197 | UINT8 status;
|
| 198 | |
| 199 | int disp;
|
| 200 | int hpixels_per_column;
|
| 201 | |
| 202 | /* runtime variables, do not state save */
|
| 203 | int vsync_start;
|
| 204 | int vsync_end;
|
| 205 | int hsync_start;
|
| 206 | int hsync_end;
|
| 207 | |
| 208 | /* timers */
|
| 209 | emu_timer *vsync_timer; /* vertical sync timer */
|
| 210 | emu_timer *hsync_timer; /* horizontal sync timer */
|
| 33 | 211 | };
|
| 34 | 212 | |
| 35 | 213 | /***************************************************************************
|
| r7485 | r7486 | |
| 53 | 231 | /***************************************************************************
|
| 54 | 232 | IMPLEMENTATION
|
| 55 | 233 | ***************************************************************************/
|
| 234 | |
| 56 | 235 | /*-------------------------------------------------
|
| 236 | update_vsync_timer -
|
| 237 | -------------------------------------------------*/
|
| 238 | |
| 239 | static void update_vsync_timer(crt9007_t *crt9007, int state)
|
| 240 | {
|
| 241 | int next_y = state ? crt9007->vsync_start : crt9007->vsync_end;
|
| 242 | |
| 243 | attotime duration = video_screen_get_time_until_pos(crt9007->screen, next_y, 0);
|
| 244 | |
| 245 | timer_adjust_oneshot(crt9007->vsync_timer, duration, !state);
|
| 246 | }
|
| 247 | |
| 248 | /*-------------------------------------------------
|
| 249 | TIMER_CALLBACK( vsync_tick )
|
| 250 | -------------------------------------------------*/
|
| 251 | |
| 252 | static TIMER_CALLBACK( vsync_tick )
|
| 253 | {
|
| 254 | running_device *device = (running_device *)ptr;
|
| 255 | crt9007_t *crt9007 = get_safe_token(device);
|
| 256 | |
| 257 | devcb_call_write_line(&crt9007->out_vs_func, param);
|
| 258 | |
| 259 | update_vsync_timer(crt9007, param);
|
| 260 | }
|
| 261 | |
| 262 | /*-------------------------------------------------
|
| 263 | update_hsync_timer -
|
| 264 | -------------------------------------------------*/
|
| 265 | |
| 266 | static void update_hsync_timer(crt9007_t *crt9007, int state)
|
| 267 | {
|
| 268 | int y = video_screen_get_vpos(crt9007->screen);
|
| 269 | |
| 270 | int next_x = state ? crt9007->hsync_start : crt9007->hsync_end;
|
| 271 | int next_y = (y + 1) % SCAN_LINES_PER_FRAME;
|
| 272 | |
| 273 | attotime duration = video_screen_get_time_until_pos(crt9007->screen, next_y, next_x);
|
| 274 | |
| 275 | timer_adjust_oneshot(crt9007->hsync_timer, duration, !state);
|
| 276 | }
|
| 277 | |
| 278 | /*-------------------------------------------------
|
| 279 | TIMER_CALLBACK( hsync_tick )
|
| 280 | -------------------------------------------------*/
|
| 281 | |
| 282 | static TIMER_CALLBACK( hsync_tick )
|
| 283 | {
|
| 284 | running_device *device = (running_device *)ptr;
|
| 285 | crt9007_t *crt9007 = get_safe_token(device);
|
| 286 | |
| 287 | devcb_call_write_line(&crt9007->out_hs_func, param);
|
| 288 | |
| 289 | update_hsync_timer(crt9007, param);
|
| 290 | }
|
| 291 | |
| 292 | /*-------------------------------------------------
|
| 293 | recompute_parameters -
|
| 294 | -------------------------------------------------*/
|
| 295 | |
| 296 | static void recompute_parameters(running_device *device)
|
| 297 | {
|
| 298 | crt9007_t *crt9007 = get_safe_token(device);
|
| 299 |
|
| 300 | /* check that necessary registers have been loaded */
|
| 301 | if (!HAS_VALID_PARAMETERS) return;
|
| 302 | |
| 303 | int horiz_pix_total = CHARACTERS_PER_HORIZONTAL_PERIOD * crt9007->hpixels_per_column;
|
| 304 | int vert_pix_total = SCAN_LINES_PER_FRAME;
|
| 305 | |
| 306 | attoseconds_t refresh = HZ_TO_ATTOSECONDS(device->clock) * horiz_pix_total * vert_pix_total;
|
| 307 | |
| 308 | rectangle visarea;
|
| 309 | |
| 310 | visarea.min_x = 0;
|
| 311 | visarea.min_y = 0;
|
| 312 | visarea.max_x = (CHARACTERS_PER_DATA_ROW * crt9007->hpixels_per_column) - 1;
|
| 313 | visarea.max_y = (VISIBLE_DATA_ROWS_PER_FRAME * SCAN_LINES_PER_DATA_ROW) - 1;
|
| 314 | |
| 315 | if (LOG)
|
| 316 | {
|
| 317 | logerror("CRT9007 '%s' Screen: %u x %u @ %f Hz\n", device->tag.cstr(), horiz_pix_total, vert_pix_total, 1 / ATTOSECONDS_TO_DOUBLE(refresh));
|
| 318 | logerror("CRT9007 '%s' Visible Area: (%u, %u) - (%u, %u)\n", device->tag.cstr(), visarea.min_x, visarea.min_y, visarea.max_x, visarea.max_y);
|
| 319 | }
|
| 320 | |
| 321 | video_screen_configure(crt9007->screen, horiz_pix_total, vert_pix_total, &visarea, refresh);
|
| 322 | |
| 323 | crt9007->vsync_start = VISIBLE_DATA_ROWS_PER_FRAME - VERTICAL_DELAY;
|
| 324 | crt9007->vsync_end = (crt9007->vsync_start + VERTICAL_SYNC_WIDTH) % VISIBLE_DATA_ROWS_PER_FRAME;
|
| 325 | crt9007->hsync_start = (CHARACTERS_PER_HORIZONTAL_PERIOD - HORIZONTAL_DELAY) * crt9007->hpixels_per_column;
|
| 326 | crt9007->hsync_end = ((crt9007->hsync_start + HORIZONTAL_SYNC_WIDTH) % CHARACTERS_PER_HORIZONTAL_PERIOD) * crt9007->hpixels_per_column;
|
| 327 | |
| 328 | update_hsync_timer(crt9007, 1);
|
| 329 | update_vsync_timer(crt9007, 1);
|
| 330 | }
|
| 331 | |
| 332 | /*-------------------------------------------------
|
| 57 | 333 | crt9007_r - register read
|
| 58 | 334 | -------------------------------------------------*/
|
| 59 | 335 | |
| r7485 | r7486 | |
| 66 | 342 | switch (offset)
|
| 67 | 343 | {
|
| 68 | 344 | case 0x15:
|
| 345 | crt9007->disp = 1;
|
| 69 | 346 | if (LOG) logerror("CRT9007 '%s' Start\n", device->tag.cstr());
|
| 70 | 347 | break;
|
| 71 | 348 | |
| 72 | 349 | case 0x16:
|
| 350 | crt9007->disp = 0;
|
| 73 | 351 | if (LOG) logerror("CRT9007 '%s' Reset\n", device->tag.cstr());
|
| 74 | 352 | break;
|
| 75 | 353 | |
| 76 | 354 | case 0x38:
|
| 77 | | data = crt9007->reg[0x18];
|
| 355 | data = VERTICAL_CURSOR;
|
| 78 | 356 | break;
|
| 79 | 357 | |
| 80 | 358 | case 0x39:
|
| 81 | | data = crt9007->reg[0x19];
|
| 359 | data = HORIZONTAL_CURSOR;
|
| 82 | 360 | break;
|
| 83 | 361 | |
| 84 | 362 | case 0x3a:
|
| 363 | data = crt9007->status;
|
| 85 | 364 | break;
|
| 86 | 365 | |
| 87 | 366 | case 0x3b:
|
| 367 | data = VERTICAL_LIGHT_PEN;
|
| 88 | 368 | break;
|
| 89 | 369 | |
| 90 | 370 | case 0x3c:
|
| 371 | data = HORIZONTAL_LIGHT_PEN;
|
| 91 | 372 | break;
|
| 92 | 373 | |
| 93 | 374 | default:
|
| r7485 | r7486 | |
| 110 | 391 | switch (offset)
|
| 111 | 392 | {
|
| 112 | 393 | case 0x00:
|
| 113 | | if (LOG) logerror("CRT9007 '%s' Characters per Horizontal Period: %u\n", device->tag.cstr(), data);
|
| 394 | recompute_parameters(device);
|
| 395 | if (LOG) logerror("CRT9007 '%s' Characters per Horizontal Period: %u\n", device->tag.cstr(), CHARACTERS_PER_HORIZONTAL_PERIOD);
|
| 114 | 396 | break;
|
| 115 | 397 |
|
| 116 | 398 | case 0x01:
|
| 117 | | if (LOG) logerror("CRT9007 '%s' Characters per Data Row: %u\n", device->tag.cstr(), data + 1);
|
| 399 | recompute_parameters(device);
|
| 400 | if (LOG) logerror("CRT9007 '%s' Characters per Data Row: %u\n", device->tag.cstr(), CHARACTERS_PER_DATA_ROW);
|
| 118 | 401 | break;
|
| 119 | 402 | |
| 120 | 403 | case 0x02:
|
| 121 | | if (LOG) logerror("CRT9007 '%s' Horizontal Delay: %u\n", device->tag.cstr(), data);
|
| 404 | recompute_parameters(device);
|
| 405 | if (LOG) logerror("CRT9007 '%s' Horizontal Delay: %u\n", device->tag.cstr(), HORIZONTAL_DELAY);
|
| 122 | 406 | break;
|
| 123 | 407 | |
| 124 | 408 | case 0x03:
|
| 125 | | if (LOG) logerror("CRT9007 '%s' Horizontal Sync Width: %u\n", device->tag.cstr(), data);
|
| 409 | recompute_parameters(device);
|
| 410 | if (LOG) logerror("CRT9007 '%s' Horizontal Sync Width: %u\n", device->tag.cstr(), HORIZONTAL_SYNC_WIDTH);
|
| 126 | 411 | break;
|
| 127 | 412 | |
| 128 | 413 | case 0x04:
|
| 129 | | if (LOG) logerror("CRT9007 '%s' Vertical Sync Width: %u\n", device->tag.cstr(), data);
|
| 414 | recompute_parameters(device);
|
| 415 | if (LOG) logerror("CRT9007 '%s' Vertical Sync Width: %u\n", device->tag.cstr(), VERTICAL_SYNC_WIDTH);
|
| 130 | 416 | break;
|
| 131 | 417 | |
| 132 | 418 | case 0x05:
|
| 133 | | if (LOG) logerror("CRT9007 '%s' Vertical Delay: %u\n", device->tag.cstr(), data - 1);
|
| 419 | recompute_parameters(device);
|
| 420 | if (LOG) logerror("CRT9007 '%s' Vertical Delay: %u\n", device->tag.cstr(), VERTICAL_DELAY);
|
| 134 | 421 | break;
|
| 135 | 422 | |
| 136 | 423 | case 0x06:
|
| 424 | recompute_parameters(device);
|
| 137 | 425 | if (LOG) |
| 138 | 426 | {
|
| 139 | | logerror("CRT9007 '%s' Pin Configuration: %u\n", device->tag.cstr(), data >> 6);
|
| 140 | | logerror("CRT9007 '%s' Cursor Skew: %u\n", device->tag.cstr(), (data >> 3) & 0x07);
|
| 141 | | logerror("CRT9007 '%s' Blank Skew: %u\n", device->tag.cstr(), data & 0x07);
|
| 427 | logerror("CRT9007 '%s' Pin Configuration: %u\n", device->tag.cstr(), PIN_CONFIGURATION);
|
| 428 | logerror("CRT9007 '%s' Cursor Skew: %u\n", device->tag.cstr(), CURSOR_SKEW);
|
| 429 | logerror("CRT9007 '%s' Blank Skew: %u\n", device->tag.cstr(), BLANK_SKEW);
|
| 142 | 430 | }
|
| 143 | 431 | break;
|
| 144 | 432 | |
| 145 | 433 | case 0x07:
|
| 146 | | if (LOG) logerror("CRT9007 '%s' Visible Data Rows per Frame: %u\n", device->tag.cstr(), data + 1);
|
| 434 | recompute_parameters(device);
|
| 435 | if (LOG) logerror("CRT9007 '%s' Visible Data Rows per Frame: %u\n", device->tag.cstr(), VISIBLE_DATA_ROWS_PER_FRAME);
|
| 147 | 436 | break;
|
| 148 | 437 | |
| 149 | 438 | case 0x08:
|
| 150 | | if (LOG) logerror("CRT9007 '%s' Scan Lines per Data Row: %u\n", device->tag.cstr(), (data & 0x1f) + 1);
|
| 439 | recompute_parameters(device);
|
| 440 | if (LOG) logerror("CRT9007 '%s' Scan Lines per Data Row: %u\n", device->tag.cstr(), SCAN_LINES_PER_DATA_ROW);
|
| 151 | 441 | break;
|
| 152 | 442 | |
| 153 | 443 | case 0x09:
|
| 154 | | if (LOG) logerror("CRT9007 '%s' Scan Lines per Frame: %u\n", device->tag.cstr(), ((crt9007->reg[0x08] << 3) & 0xff00) | data);
|
| 444 | recompute_parameters(device);
|
| 445 | if (LOG) logerror("CRT9007 '%s' Scan Lines per Frame: %u\n", device->tag.cstr(), SCAN_LINES_PER_FRAME);
|
| 155 | 446 | break;
|
| 156 | 447 | |
| 157 | 448 | case 0x0a:
|
| 158 | 449 | if (LOG)
|
| 159 | 450 | {
|
| 160 | | logerror("CRT9007 '%s' DMA Burst Count: %u\n", device->tag.cstr(), (data & 0x0f) + 1);
|
| 161 | | logerror("CRT9007 '%s' DMA Burst Delay: %u\n", device->tag.cstr(), (data >> 4) & 0x07);
|
| 162 | | logerror("CRT9007 '%s' DMA Disable: %u\n", device->tag.cstr(), BIT(data, 7));
|
| 451 | logerror("CRT9007 '%s' DMA Burst Count: %u\n", device->tag.cstr(), DMA_BURST_COUNT);
|
| 452 | logerror("CRT9007 '%s' DMA Burst Delay: %u\n", device->tag.cstr(), DMA_BURST_DELAY);
|
| 453 | logerror("CRT9007 '%s' DMA Disable: %u\n", device->tag.cstr(), DMA_DISABLE);
|
| 163 | 454 | }
|
| 164 | 455 | break;
|
| 165 | 456 | |
| r7485 | r7486 | |
| 167 | 458 | if (LOG)
|
| 168 | 459 | {
|
| 169 | 460 | logerror("CRT9007 '%s' %s Height Cursor\n", device->tag.cstr(), BIT(data, 0) ? "Single" : "Double");
|
| 170 | | logerror("CRT9007 '%s' Operation Mode: %u\n", device->tag.cstr(), (data >> 1) & 0x07);
|
| 171 | | logerror("CRT9007 '%s' Interlace Mode: %u\n", device->tag.cstr(), (data >> 4) & 0x03);
|
| 461 | logerror("CRT9007 '%s' Operation Mode: %u\n", device->tag.cstr(), OPERATION_MODE);
|
| 462 | logerror("CRT9007 '%s' Interlace Mode: %u\n", device->tag.cstr(), INTERLACE_MODE);
|
| 172 | 463 | logerror("CRT9007 '%s' %s Mechanism\n", device->tag.cstr(), BIT(data, 6) ? "Page Blank" : "Smooth Scroll");
|
| 173 | 464 | }
|
| 174 | 465 | break;
|
| r7485 | r7486 | |
| 179 | 470 | case 0x0d:
|
| 180 | 471 | if (LOG)
|
| 181 | 472 | {
|
| 182 | | logerror("CRT9007 '%s' Table Start Register: %04x\n", device->tag.cstr(), ((data << 8) & 0x3f00) | crt9007->reg[0x0c]);
|
| 183 | | logerror("CRT9007 '%s' Address Mode: %u\n", device->tag.cstr(), (data >> 6) & 0x03);
|
| 473 | logerror("CRT9007 '%s' Table Start Register: %04x\n", device->tag.cstr(), TABLE_START);
|
| 474 | logerror("CRT9007 '%s' Address Mode: %u\n", device->tag.cstr(), ADDRESS_MODE);
|
| 184 | 475 | }
|
| 185 | 476 | break;
|
| 186 | 477 | |
| r7485 | r7486 | |
| 190 | 481 | case 0x0f:
|
| 191 | 482 | if (LOG)
|
| 192 | 483 | {
|
| 193 | | logerror("CRT9007 '%s' Auxialiary Address Register 1: %04x\n", device->tag.cstr(), ((data << 8) & 0x3f00) | crt9007->reg[0x0e]);
|
| 484 | logerror("CRT9007 '%s' Auxialiary Address Register 1: %04x\n", device->tag.cstr(), AUXILIARY_ADDRESS_1);
|
| 194 | 485 | logerror("CRT9007 '%s' Row Attributes: %u\n", device->tag.cstr(), (data >> 6) & 0x03);
|
| 195 | 486 | }
|
| 196 | 487 | break;
|
| 197 | 488 | |
| 198 | 489 | case 0x10:
|
| 199 | | if (LOG) logerror("CRT9007 '%s' Sequential Break Register 1: %u\n", device->tag.cstr(), data);
|
| 490 | if (LOG) logerror("CRT9007 '%s' Sequential Break Register 1: %u\n", device->tag.cstr(), SEQUENTIAL_BREAK_1);
|
| 200 | 491 | break;
|
| 201 | 492 | |
| 202 | 493 | case 0x11:
|
| 203 | | if (LOG) logerror("CRT9007 '%s' Data Row Start Register: %u\n", device->tag.cstr(), data);
|
| 494 | if (LOG) logerror("CRT9007 '%s' Data Row Start Register: %u\n", device->tag.cstr(), DATA_ROW_START);
|
| 204 | 495 | break;
|
| 205 | 496 | |
| 206 | 497 | case 0x12:
|
| 207 | | if (LOG) logerror("CRT9007 '%s' Data Row End/Sequential Break Register 2: %u\n", device->tag.cstr(), data);
|
| 498 | if (LOG) logerror("CRT9007 '%s' Data Row End/Sequential Break Register 2: %u\n", device->tag.cstr(), SEQUENTIAL_BREAK_2);
|
| 208 | 499 | break;
|
| 209 | 500 | |
| 210 | 501 | case 0x13:
|
| r7485 | r7486 | |
| 213 | 504 | case 0x14:
|
| 214 | 505 | if (LOG)
|
| 215 | 506 | {
|
| 216 | | logerror("CRT9007 '%s' Auxiliary Address Register 2: %04x\n", device->tag.cstr(), ((data << 8) & 0x3f00) | crt9007->reg[0x13]);
|
| 507 | logerror("CRT9007 '%s' Auxiliary Address Register 2: %04x\n", device->tag.cstr(), AUXILIARY_ADDRESS_2);
|
| 217 | 508 | logerror("CRT9007 '%s' Row Attributes: %u\n", device->tag.cstr(), (data >> 6) & 0x03);
|
| 218 | 509 | }
|
| 219 | 510 | break;
|
| 220 | 511 | |
| 221 | 512 | case 0x15:
|
| 513 | crt9007->disp = 1;
|
| 222 | 514 | if (LOG) logerror("CRT9007 '%s' Start\n", device->tag.cstr());
|
| 223 | 515 | break;
|
| 224 | 516 | |
| 225 | 517 | case 0x16:
|
| 518 | crt9007->disp = 0;
|
| 226 | 519 | if (LOG) logerror("CRT9007 '%s' Reset\n", device->tag.cstr());
|
| 227 | 520 | break;
|
| 228 | 521 | |
| 229 | 522 | case 0x17:
|
| 230 | 523 | if (LOG)
|
| 231 | 524 | {
|
| 232 | | logerror("CRT9007 '%s' Smooth Scroll Offset: %u\n", device->tag.cstr(), (data >> 1) & 0x3f);
|
| 233 | | logerror("CRT9007 '%s' Smooth Scroll Offset Overflow: %u\n", device->tag.cstr(), BIT(data, 7));
|
| 525 | logerror("CRT9007 '%s' Smooth Scroll Offset: %u\n", device->tag.cstr(), SMOOTH_SCROLL_OFFSET);
|
| 526 | logerror("CRT9007 '%s' Smooth Scroll Offset Overflow: %u\n", device->tag.cstr(), SMOOTH_SCROLL_OFFSET_OVERFLOW);
|
| 234 | 527 | }
|
| 235 | 528 | break;
|
| 236 | 529 | |
| 237 | 530 | case 0x18:
|
| 238 | | if (LOG) logerror("CRT9007 '%s' Vertical Cursor Register: %u\n", device->tag.cstr(), data);
|
| 531 | if (LOG) logerror("CRT9007 '%s' Vertical Cursor Register: %u\n", device->tag.cstr(), VERTICAL_CURSOR);
|
| 239 | 532 | break;
|
| 240 | 533 | |
| 241 | 534 | case 0x19:
|
| 242 | | if (LOG) logerror("CRT9007 '%s' Horizontal Cursor Register: %u\n", device->tag.cstr(), data);
|
| 535 | if (LOG) logerror("CRT9007 '%s' Horizontal Cursor Register: %u\n", device->tag.cstr(), HORIZONTAL_CURSOR);
|
| 243 | 536 | break;
|
| 244 | 537 | |
| 245 | 538 | case 0x1a:
|
| r7485 | r7486 | |
| 257 | 550 | }
|
| 258 | 551 | |
| 259 | 552 | /*-------------------------------------------------
|
| 553 | crt9007_ack_w - DMA acknowledge
|
| 554 | -------------------------------------------------*/
|
| 555 | |
| 556 | WRITE8_DEVICE_HANDLER( crt9007_ack_w )
|
| 557 | {
|
| 558 | }
|
| 559 | |
| 560 | /*-------------------------------------------------
|
| 561 | crt9007_lpstb_w - light pen strobe
|
| 562 | -------------------------------------------------*/
|
| 563 | |
| 564 | WRITE_LINE_DEVICE_HANDLER( crt9007_lpstb_w )
|
| 565 | {
|
| 566 | }
|
| 567 | |
| 568 | /*-------------------------------------------------
|
| 260 | 569 | crt9007_update - update screen
|
| 261 | 570 | -------------------------------------------------*/
|
| 262 | 571 | |
| 263 | 572 | void crt9007_update(running_device *device, bitmap_t *bitmap, const rectangle *cliprect)
|
| 264 | 573 | {
|
| 574 | crt9007_t *crt9007 = get_safe_token(device);
|
| 575 | |
| 576 | if (crt9007->disp && HAS_VALID_PARAMETERS)
|
| 577 | {
|
| 578 | for (int y = 0; y < (VISIBLE_DATA_ROWS_PER_FRAME * SCAN_LINES_PER_DATA_ROW); y++)
|
| 579 | {
|
| 580 | int sl = y % SCAN_LINES_PER_DATA_ROW;
|
| 581 | int sy = y / SCAN_LINES_PER_DATA_ROW;
|
| 582 | int cursor_x = (sy == VERTICAL_CURSOR) ? HORIZONTAL_CURSOR : -1;
|
| 583 | UINT16 addr = TABLE_START + (sy * CHARACTERS_PER_DATA_ROW);
|
| 584 | UINT8 data = devcb_call_read8(&crt9007->in_vd_func, addr);
|
| 585 |
|
| 586 | crt9007->draw_scanline_func(device, bitmap, cliprect, addr, sl, data, y, 0, CHARACTERS_PER_DATA_ROW, cursor_x);
|
| 587 | |
| 588 | addr++;
|
| 589 | }
|
| 590 | }
|
| 591 | else
|
| 592 | {
|
| 593 | bitmap_fill(bitmap, cliprect, get_black_pen(device->machine));
|
| 594 | }
|
| 265 | 595 | }
|
| 266 | 596 | |
| 267 | 597 | /*-------------------------------------------------
|
| r7485 | r7486 | |
| 280 | 610 | devcb_resolve_write_line(&crt9007->out_vs_func, &intf->out_vs_func, device);
|
| 281 | 611 | devcb_resolve_read8(&crt9007->in_vd_func, &intf->in_vd_func, device);
|
| 282 | 612 | |
| 613 | crt9007->draw_scanline_func = intf->draw_scanline_func;
|
| 614 | assert(crt9007->draw_scanline_func != NULL);
|
| 615 | |
| 616 | /* get the screen device */
|
| 617 | crt9007->screen = devtag_get_device(device->machine, intf->screen_tag);
|
| 618 | assert(crt9007->screen != NULL);
|
| 619 | |
| 620 | /* set horizontal pixels per column */
|
| 621 | crt9007->hpixels_per_column = intf->hpixels_per_column;
|
| 622 | |
| 623 | /* create the timers */
|
| 624 | crt9007->vsync_timer = timer_alloc(device->machine, vsync_tick, (void *)device);
|
| 625 | crt9007->hsync_timer = timer_alloc(device->machine, hsync_tick, (void *)device);
|
| 626 | |
| 283 | 627 | /* register for state saving */
|
| 284 | 628 | // state_save_register_device_item(device, 0, crt9007->);
|
| 285 | 629 | }
|