trunk/src/emu/video/mc6845.c
| r18677 | r18678 | |
| 30 | 30 | |
| 31 | 31 | - horizontal scroll |
| 32 | 32 | - vertical scroll |
| 33 | | - pixel double width |
| 34 | 33 | - bitmap modes |
| 35 | 34 | - display enable begin/end |
| 36 | 35 | |
| r18677 | r18678 | |
| 78 | 77 | #define HSS_TEXT BIT(m_horiz_scroll, 7) |
| 79 | 78 | |
| 80 | 79 | #define ATTR_COLOR (attr & 0x0f) |
| 80 | #define ATTR_BACKGROUND (attr & 0x0f) |
| 81 | #define ATTR_FOREGROUND (attr >> 4) |
| 81 | 82 | #define ATTR_BLINK BIT(attr, 4) |
| 82 | 83 | #define ATTR_UNDERLINE BIT(attr, 5) |
| 83 | 84 | #define ATTR_REVERSE BIT(attr, 6) |
| r18677 | r18678 | |
| 276 | 277 | WRITE8_MEMBER( mos8563_device::address_w ) |
| 277 | 278 | { |
| 278 | 279 | m_register_address_latch = data & 0x3f; |
| 279 | | |
| 280 | | m_update_ready_bit = 0; |
| 281 | 280 | } |
| 282 | 281 | |
| 283 | 282 | |
| 284 | 283 | READ8_MEMBER( mos8563_device::status_r ) |
| 285 | 284 | { |
| 286 | | UINT8 ret = 0; |
| 285 | UINT8 ret = m_revision; |
| 287 | 286 | |
| 288 | 287 | /* VBLANK bit */ |
| 289 | 288 | if (!m_line_enable_ff) |
| r18677 | r18678 | |
| 297 | 296 | if (m_update_ready_bit) |
| 298 | 297 | ret = ret | 0x80; |
| 299 | 298 | |
| 300 | | m_update_ready_bit = 1; |
| 301 | | |
| 302 | 299 | return ret; |
| 303 | 300 | } |
| 304 | 301 | |
| r18677 | r18678 | |
| 314 | 311 | case 0x02: ret = m_horiz_sync_pos; break; |
| 315 | 312 | case 0x03: ret = m_sync_width; break; |
| 316 | 313 | case 0x04: ret = m_vert_char_total; break; |
| 317 | | case 0x05: ret = m_vert_total_adj; break; |
| 314 | case 0x05: ret = m_vert_total_adj | 0xc0; break; |
| 318 | 315 | case 0x06: ret = m_vert_disp; break; |
| 319 | 316 | case 0x07: ret = m_vert_sync_pos; break; |
| 320 | | case 0x08: ret = m_mode_control; break; |
| 321 | | case 0x09: ret = m_max_ras_addr; break; |
| 322 | | case 0x0a: ret = m_cursor_start_ras; break; |
| 323 | | case 0x0b: ret = m_cursor_end_ras; break; |
| 317 | case 0x08: ret = m_mode_control | 0xfc; break; |
| 318 | case 0x09: ret = m_max_ras_addr | 0xe0; break; |
| 319 | case 0x0a: ret = m_cursor_start_ras | 0x80; break; |
| 320 | case 0x0b: ret = m_cursor_end_ras | 0xe0; break; |
| 324 | 321 | case 0x0c: ret = (m_disp_start_addr >> 8) & 0xff; break; |
| 325 | 322 | case 0x0d: ret = (m_disp_start_addr >> 0) & 0xff; break; |
| 326 | 323 | case 0x0e: ret = (m_cursor_addr >> 8) & 0xff; break; |
| r18677 | r18678 | |
| 332 | 329 | case 0x14: ret = (m_attribute_addr >> 8) & 0xff; break; |
| 333 | 330 | case 0x15: ret = (m_attribute_addr >> 0) & 0xff; break; |
| 334 | 331 | case 0x16: ret = m_horiz_char; break; |
| 335 | | case 0x17: ret = m_vert_char_disp; break; |
| 332 | case 0x17: ret = m_vert_char_disp | 0xe0; break; |
| 336 | 333 | case 0x18: ret = m_vert_scroll; break; |
| 337 | 334 | case 0x19: ret = m_horiz_scroll; break; |
| 338 | 335 | case 0x1a: ret = m_color; break; |
| 339 | 336 | case 0x1b: ret = m_row_addr_incr; break; |
| 340 | | case 0x1c: ret = m_char_base_addr; break; |
| 341 | | case 0x1d: ret = m_underline_ras; break; |
| 342 | | case 0x1e: ret = 0; break; |
| 337 | case 0x1c: ret = m_char_base_addr | 0x1f; break; |
| 338 | case 0x1d: ret = m_underline_ras | 0xe0; break; |
| 339 | case 0x1e: ret = m_word_count; break; |
| 343 | 340 | case 0x1f: ret = read_videoram(m_update_addr++); break; |
| 344 | 341 | case 0x20: ret = (m_block_addr >> 8) & 0xff; break; |
| 345 | 342 | case 0x21: ret = (m_block_addr >> 0) & 0xff; break; |
| 346 | 343 | case 0x22: ret = (m_de_begin >> 8) & 0xff; break; |
| 347 | 344 | case 0x23: ret = (m_de_begin >> 0) & 0xff; break; |
| 348 | | case 0x24: ret = m_dram_refresh; break; |
| 345 | case 0x24: ret = m_dram_refresh | 0xf0; break; |
| 349 | 346 | case 0x25: ret = m_sync_polarity | 0x3f; break; |
| 350 | 347 | } |
| 351 | 348 | |
| r18677 | r18678 | |
| 384 | 381 | case 0x16: m_horiz_char = data & 0xff; break; |
| 385 | 382 | case 0x17: m_vert_char_disp = data & 0x1f; break; |
| 386 | 383 | case 0x18: m_vert_scroll = data & 0xff; break; |
| 387 | | case 0x19: m_horiz_scroll = data & 0xff; break; |
| 384 | case 0x19: |
| 385 | { |
| 386 | int dbl = HSS_DBL; |
| 387 | m_horiz_scroll = data & 0xff; |
| 388 | if (dbl && !HSS_DBL) set_clock(m_clock << 1); |
| 389 | if (!dbl && HSS_DBL) set_clock(m_clock >> 1); |
| 390 | break; |
| 391 | } |
| 388 | 392 | case 0x1a: m_color = data & 0xff; break; |
| 389 | 393 | case 0x1b: m_row_addr_incr = data & 0xff; break; |
| 390 | | case 0x1c: m_char_base_addr = data & 0xf0; break; |
| 394 | case 0x1c: m_char_base_addr = data & 0xe0; break; |
| 391 | 395 | case 0x1d: m_underline_ras = data & 0x1f; break; |
| 392 | 396 | case 0x1e: |
| 393 | 397 | m_word_count = data & 0xff; |
| 394 | | |
| 395 | | do |
| 396 | | { |
| 397 | | UINT8 byte = VSS_COPY ? read_videoram(m_block_addr++) : m_data; |
| 398 | | |
| 399 | | write_videoram(m_update_addr++, byte); |
| 400 | | } while (m_word_count-- > 0); |
| 398 | m_update_ready_bit = 0; |
| 399 | m_block_copy_timer->adjust( attotime::from_ticks( 1, m_clock ) ); |
| 401 | 400 | break; |
| 402 | 401 | case 0x1f: |
| 403 | 402 | m_data = data & 0xff; |
| 404 | | |
| 405 | 403 | write_videoram(m_update_addr++, m_data); |
| 406 | 404 | break; |
| 407 | 405 | case 0x20: m_block_addr = ((data & 0xff) << 8) | (m_block_addr & 0x00ff); break; |
| r18677 | r18678 | |
| 791 | 789 | } |
| 792 | 790 | |
| 793 | 791 | |
| 792 | void mos8563_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 793 | { |
| 794 | switch (id) |
| 795 | { |
| 796 | case TIMER_BLOCK_COPY: |
| 797 | { |
| 798 | UINT8 data = VSS_COPY ? read_videoram(m_block_addr++) : m_data; |
| 799 | |
| 800 | write_videoram(m_update_addr++, data); |
| 801 | |
| 802 | if (--m_word_count) |
| 803 | { |
| 804 | m_block_copy_timer->adjust( attotime::from_ticks( 1, m_clock ) ); |
| 805 | } |
| 806 | else |
| 807 | { |
| 808 | m_update_ready_bit = 1; |
| 809 | } |
| 810 | break; |
| 811 | } |
| 812 | default: |
| 813 | mc6845_device::device_timer(timer, id, param, ptr); |
| 814 | break; |
| 815 | } |
| 816 | } |
| 817 | |
| 818 | |
| 794 | 819 | UINT16 mc6845_device::get_ma() |
| 795 | 820 | { |
| 796 | 821 | update_counters(); |
| r18677 | r18678 | |
| 1186 | 1211 | { |
| 1187 | 1212 | mc6845_device::device_start(); |
| 1188 | 1213 | |
| 1214 | /* create the timers */ |
| 1215 | m_block_copy_timer = timer_alloc(TIMER_BLOCK_COPY); |
| 1216 | |
| 1189 | 1217 | m_supports_status_reg_d5 = true; |
| 1190 | 1218 | m_supports_status_reg_d6 = true; |
| 1191 | 1219 | m_supports_status_reg_d7 = true; |
| r18677 | r18678 | |
| 1210 | 1238 | m_de_begin = 0; |
| 1211 | 1239 | m_dram_refresh = 0; |
| 1212 | 1240 | m_sync_polarity = 0; |
| 1241 | |
| 1242 | m_revision = 1; |
| 1213 | 1243 | |
| 1244 | // initialize video RAM |
| 1245 | UINT8 data = 0xff; |
| 1246 | |
| 1247 | for (offs_t offset = 0; offset < 0x10000; offset++) |
| 1248 | { |
| 1249 | write_videoram(offset, data); |
| 1250 | data ^= 0xff; |
| 1251 | } |
| 1252 | |
| 1214 | 1253 | save_item(NAME(m_char_buffer)); |
| 1215 | 1254 | save_item(NAME(m_attr_buffer)); |
| 1216 | 1255 | save_item(NAME(m_attribute_addr)); |
| r18677 | r18678 | |
| 1228 | 1267 | save_item(NAME(m_de_begin)); |
| 1229 | 1268 | save_item(NAME(m_dram_refresh)); |
| 1230 | 1269 | save_item(NAME(m_sync_polarity)); |
| 1270 | save_item(NAME(m_revision)); |
| 1231 | 1271 | } |
| 1232 | 1272 | |
| 1233 | 1273 | |
| r18677 | r18678 | |
| 1382 | 1422 | // VICE palette |
| 1383 | 1423 | static const rgb_t MOS8563_PALETTE[] = |
| 1384 | 1424 | { |
| 1385 | | MAKE_RGB(0x00, 0x00, 0x00), |
| 1386 | | MAKE_RGB(0x20, 0x20, 0x20), |
| 1387 | | MAKE_RGB(0x00, 0x00, 0x80), |
| 1388 | | MAKE_RGB(0x00, 0x00, 0xff), |
| 1389 | | MAKE_RGB(0x00, 0x80, 0x00), |
| 1390 | | MAKE_RGB(0x00, 0xff, 0x00), |
| 1391 | | MAKE_RGB(0x00, 0x80, 0x80), |
| 1392 | | MAKE_RGB(0x00, 0xff, 0xff), |
| 1393 | | MAKE_RGB(0x80, 0x00, 0x00), |
| 1394 | | MAKE_RGB(0xff, 0x00, 0x00), |
| 1395 | | MAKE_RGB(0x80, 0x00, 0x80), |
| 1396 | | MAKE_RGB(0xff, 0x00, 0xff), |
| 1397 | | MAKE_RGB(0x80, 0x80, 0x00), |
| 1398 | | MAKE_RGB(0xff, 0xff, 0x00), |
| 1399 | | MAKE_RGB(0xc0, 0xc0, 0xc0), |
| 1400 | | MAKE_RGB(0xff, 0xff, 0xff) |
| 1425 | RGB_BLACK, |
| 1426 | MAKE_RGB(0x55, 0x55, 0x55), |
| 1427 | MAKE_RGB(0x00, 0x00, 0xaa), |
| 1428 | MAKE_RGB(0x55, 0x55, 0xff), |
| 1429 | MAKE_RGB(0x00, 0xaa, 0x00), |
| 1430 | MAKE_RGB(0x55, 0xff, 0x55), |
| 1431 | MAKE_RGB(0x00, 0xaa, 0xaa), |
| 1432 | MAKE_RGB(0x55, 0xff, 0xff), |
| 1433 | MAKE_RGB(0xaa, 0x00, 0x00), |
| 1434 | MAKE_RGB(0xff, 0x55, 0x55), |
| 1435 | MAKE_RGB(0xaa, 0x00, 0xaa), |
| 1436 | MAKE_RGB(0xff, 0x55, 0xff), |
| 1437 | MAKE_RGB(0xaa, 0x55, 0x00), |
| 1438 | MAKE_RGB(0xff, 0xff, 0x55), |
| 1439 | MAKE_RGB(0xaa, 0xaa, 0xaa), |
| 1440 | RGB_WHITE |
| 1401 | 1441 | }; |
| 1402 | 1442 | |
| 1403 | 1443 | |
| r18677 | r18678 | |
| 1436 | 1476 | |
| 1437 | 1477 | void mos8563_device::update_row(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 ma, UINT8 ra, UINT16 y, UINT8 x_count, INT8 cursor_x, void *param) |
| 1438 | 1478 | { |
| 1479 | ra += (m_vert_scroll & 0x0f); |
| 1480 | ra &= 0x0f; |
| 1481 | |
| 1482 | UINT8 cth = (m_horiz_char >> 4) + (HSS_DBL ? 0 : 1); |
| 1483 | UINT8 cdh = (m_horiz_char & 0x0f) + (HSS_DBL ? 0 : 1); |
| 1484 | UINT8 cdv = m_vert_char_disp; |
| 1485 | |
| 1439 | 1486 | for (int column = 0; column < x_count; column++) |
| 1440 | 1487 | { |
| 1441 | | if (HSS_TEXT) |
| 1488 | UINT8 code = read_videoram(ma + column); |
| 1489 | UINT8 attr = 0; |
| 1490 | |
| 1491 | int fg = m_color >> 4; |
| 1492 | int bg = m_color & 0x0f; |
| 1493 | |
| 1494 | if (HSS_ATTR) |
| 1442 | 1495 | { |
| 1443 | | // TODO graphics |
| 1496 | offs_t attr_addr = m_attribute_addr + ma + column; |
| 1497 | attr = read_videoram(attr_addr); |
| 1444 | 1498 | } |
| 1445 | | else |
| 1499 | |
| 1500 | if (HSS_TEXT) |
| 1446 | 1501 | { |
| 1447 | | UINT16 code = read_videoram(ma + column); |
| 1502 | if (HSS_ATTR) |
| 1503 | { |
| 1504 | fg = ATTR_FOREGROUND; |
| 1505 | bg = ATTR_BACKGROUND; |
| 1506 | } |
| 1448 | 1507 | |
| 1449 | | offs_t attr_addr = m_attribute_addr + (ma - m_disp_start_addr) + column; |
| 1450 | | UINT8 attr = 0; |
| 1508 | if (VSS_RVS) code ^= 0xff; |
| 1451 | 1509 | |
| 1452 | | UINT8 cth = (m_horiz_char >> 4) + 1; |
| 1453 | | UINT8 cdh = (m_horiz_char & 0x0f) + 1; |
| 1454 | | UINT8 cdv = m_vert_char_disp; |
| 1510 | for (int bit = 0; bit < cdh; bit++) |
| 1511 | { |
| 1512 | int x = (m_horiz_scroll & 0x0f) - cth + (column * cth) + bit; |
| 1513 | if (x < 0) x = 0; |
| 1514 | int color = BIT(code, 7) ? fg : bg; |
| 1455 | 1515 | |
| 1456 | | // attributes |
| 1457 | | int fg; |
| 1458 | | int bg = m_color & 0x0f; |
| 1459 | | |
| 1516 | bitmap.pix32(y, x) = MOS8563_PALETTE[color]; |
| 1517 | } |
| 1518 | } |
| 1519 | else |
| 1520 | { |
| 1460 | 1521 | if (HSS_ATTR) |
| 1461 | 1522 | { |
| 1462 | | attr = read_videoram(attr_addr); |
| 1463 | 1523 | fg = ATTR_COLOR; |
| 1464 | 1524 | } |
| 1465 | | else |
| 1466 | | { |
| 1467 | | fg = m_color >> 4; |
| 1468 | | } |
| 1469 | 1525 | |
| 1470 | 1526 | offs_t font_addr; |
| 1471 | 1527 | |
| 1472 | | code |= ATTR_ALTERNATE_CHARSET << 8; |
| 1473 | | |
| 1474 | 1528 | if (m_max_ras_addr < 16) |
| 1475 | | font_addr = ((m_char_base_addr >> 5) << 13) | (code << 4) | ra; |
| 1529 | { |
| 1530 | font_addr = ((m_char_base_addr & 0xe0) << 8) | (ATTR_ALTERNATE_CHARSET << 12) | (code << 4) | (ra & 0x0f); |
| 1531 | } |
| 1476 | 1532 | else |
| 1477 | | font_addr = ((m_char_base_addr >> 5) << 13) | (code << 5) | ra; |
| 1478 | | |
| 1533 | { |
| 1534 | font_addr = ((m_char_base_addr & 0xc0) << 8) | (ATTR_ALTERNATE_CHARSET << 13) | (code << 5) | (ra & 0x1f); |
| 1535 | } |
| 1536 | |
| 1479 | 1537 | UINT8 data = read_videoram(font_addr); |
| 1480 | 1538 | |
| 1481 | | if (column == cursor_x) data = 0xff; |
| 1482 | 1539 | if (ra >= cdv) data = 0; |
| 1483 | 1540 | if (ATTR_UNDERLINE && (ra == m_underline_ras)) data = 0xff; |
| 1484 | 1541 | if (ATTR_BLINK && !m_char_blink_state) data = 0; |
| 1542 | if (ATTR_REVERSE) data ^= 0xff; |
| 1543 | if (column == cursor_x) data ^= 0xff; |
| 1544 | if (VSS_RVS) data ^= 0xff; |
| 1485 | 1545 | |
| 1486 | | if (ATTR_REVERSE) |
| 1487 | | { |
| 1488 | | int temp = bg; |
| 1489 | | bg = fg; |
| 1490 | | fg = temp; |
| 1491 | | } |
| 1492 | | |
| 1493 | 1546 | for (int bit = 0; bit < cdh; bit++) |
| 1494 | 1547 | { |
| 1495 | | int x = (column * cth) + bit; |
| 1548 | int x = (m_horiz_scroll & 0x0f) - cth + (column * cth) + bit; |
| 1549 | if (x < 0) x = 0; |
| 1550 | int color = BIT(data, 7) ? fg : bg; |
| 1496 | 1551 | |
| 1497 | | bitmap.pix32(y, x) = MOS8563_PALETTE[(BIT(data, 7) ^ VSS_RVS) ? fg : bg]; |
| 1552 | bitmap.pix32(y, x) = MOS8563_PALETTE[color]; |
| 1498 | 1553 | |
| 1499 | 1554 | if ((bit < 8) || !HSS_SEMI) data <<= 1; |
| 1500 | 1555 | } |