src/mess/video/hd61830.c
| r9363 | r9364 | |
| 7 | 7 | |
| 8 | 8 | **********************************************************************/ |
| 9 | 9 | |
| 10 | | /* |
| 11 | | |
| 12 | | TODO: |
| 13 | | |
| 14 | | - external ROM |
| 15 | | - slave mode |
| 16 | | |
| 17 | | */ |
| 18 | | |
| 19 | 10 | #include "emu.h" |
| 20 | 11 | #include "hd61830.h" |
| 21 | 12 | |
| r9363 | r9364 | |
| 46 | 37 | 4, 4, 4, 4, 4, -1, -1, -1, 4, 4, 4, 4, 6, 6, 36, 36 |
| 47 | 38 | }; |
| 48 | 39 | |
| 49 | | #define HD61830_MODE_EXTERNAL_CG 0x01 /* not supported */ |
| 40 | #define HD61830_MODE_EXTERNAL_CG 0x01 |
| 50 | 41 | #define HD61830_MODE_GRAPHIC 0x02 |
| 51 | 42 | #define HD61830_MODE_CURSOR 0x04 |
| 52 | 43 | #define HD61830_MODE_BLINK 0x08 |
| 53 | | #define HD61830_MODE_MASTER 0x10 /* not supported */ |
| 44 | #define HD61830_MODE_MASTER 0x10 |
| 54 | 45 | #define HD61830_MODE_DISPLAY_ON 0x20 |
| 55 | 46 | |
| 56 | 47 | /*************************************************************************** |
| r9363 | r9364 | |
| 61 | 52 | struct _hd61830_t |
| 62 | 53 | { |
| 63 | 54 | address_space *ram; /* video RAM memory space */ |
| 64 | | address_space *rom; /* character ROM memory space */ |
| 55 | hd61830_rd_read rd_r; |
| 65 | 56 | |
| 66 | 57 | int bf; /* busy flag */ |
| 67 | 58 | |
| r9363 | r9364 | |
| 78 | 69 | int nx; /* number of time divisions */ |
| 79 | 70 | int cp; /* cursor position */ |
| 80 | 71 | |
| 81 | | UINT8 blink; /* blinking */ |
| 72 | int blink; /* blinking */ |
| 73 | int cursor; |
| 82 | 74 | |
| 83 | 75 | /* devices */ |
| 84 | 76 | screen_device *screen; |
| r9363 | r9364 | |
| 94 | 86 | INLINE hd61830_t *get_safe_token(running_device *device) |
| 95 | 87 | { |
| 96 | 88 | assert(device != NULL); |
| 89 | assert(device->type() == HD61830); |
| 97 | 90 | return (hd61830_t *)downcast<legacy_device_base *>(device)->token(); |
| 98 | 91 | } |
| 99 | 92 | |
| 100 | | INLINE hd61830_config *get_safe_config(running_device *device) |
| 93 | INLINE const hd61830_interface *get_interface(running_device *device) |
| 101 | 94 | { |
| 102 | 95 | assert(device != NULL); |
| 103 | 96 | assert(device->type() == HD61830); |
| 104 | | return (hd61830_config *)downcast<const legacy_device_config_base &>(device->baseconfig()).inline_config(); |
| 97 | return (const hd61830_interface *) device->baseconfig().static_config(); |
| 105 | 98 | } |
| 106 | 99 | |
| 107 | 100 | /*************************************************************************** |
| r9363 | r9364 | |
| 319 | 312 | |
| 320 | 313 | for (int x = 0; x < hd61830->hp; x++) |
| 321 | 314 | { |
| 322 | | *BITMAP_ADDR16(bitmap, y, (sx * hd61830->hp) + x) = BIT(data, 0); |
| 323 | | data >>= 1; |
| 315 | *BITMAP_ADDR16(bitmap, y, (sx * hd61830->hp) + x) = BIT(data, x); |
| 324 | 316 | } |
| 325 | 317 | } |
| 326 | 318 | } |
| r9363 | r9364 | |
| 350 | 342 | draw_char - draw a char |
| 351 | 343 | -------------------------------------------------*/ |
| 352 | 344 | |
| 353 | | static void draw_char(running_device *device, bitmap_t *bitmap, const rectangle *cliprect, int x, int y, UINT8 char_code) |
| 345 | static void draw_char(running_device *device, bitmap_t *bitmap, const rectangle *cliprect, UINT16 ma, int x, int y, UINT8 md) |
| 354 | 346 | { |
| 355 | 347 | hd61830_t *hd61830 = get_safe_token(device); |
| 356 | 348 | |
| 357 | | if (char_code < 0x20 || char_code > 0x7f) |
| 358 | | return; |
| 359 | | |
| 360 | | for (int cl = 0; cl < 7; cl++) |
| 349 | for (int cl = 0; cl < hd61830->vp; cl++) |
| 361 | 350 | { |
| 362 | | for (int cr = 0; cr < 5; cr++) |
| 351 | for (int cr = 0; cr < hd61830->hp; cr++) |
| 363 | 352 | { |
| 364 | | if ((hd61830->screen->height() > y * hd61830->vp + cl) && (hd61830->screen->width() > x * hd61830->hp + cr)) |
| 353 | int sy = y * hd61830->vp + cl; |
| 354 | int sx = x * hd61830->hp + cr; |
| 355 | UINT8 data = 0; |
| 356 | |
| 357 | if (hd61830->mcr & HD61830_MODE_EXTERNAL_CG) |
| 365 | 358 | { |
| 366 | | *BITMAP_ADDR16(bitmap, y * hd61830->vp + cl, x * hd61830->hp + cr) = device->subregion("hd61830")->u8(((char_code - 0x20) * 7 + cl)) & (1<<(4 - cr)) ? 1 : 0; |
| 359 | data = hd61830->rd_r(device, (cl << 12) | (ma & 0xfff), md); |
| 367 | 360 | } |
| 361 | else |
| 362 | { |
| 363 | UINT16 addr = 0; |
| 364 | |
| 365 | if (md >= 0x20 && md < 0x80 && cl < 7) |
| 366 | { |
| 367 | // 5x7 characters 0x20..0x7f |
| 368 | addr = (md - 0x20) * 7 + cl; |
| 369 | } |
| 370 | else if (md >= 0xa0 && md < 0xe0 && cl < 7) |
| 371 | { |
| 372 | // 5x7 characters 0xa0..0xdf |
| 373 | addr = 96*7 + (md - 0xa0) * 7 + cl; |
| 374 | } |
| 375 | else if (md >= 0xe0 && cl < 11) |
| 376 | { |
| 377 | // 5x11 characters 0xe0..0xff |
| 378 | addr = 160*7 + (md - 0xe0) * 11 + cl; |
| 379 | } |
| 380 | |
| 381 | data = device->subregion("hd61830")->u8(addr); |
| 382 | } |
| 383 | |
| 384 | int cursor = hd61830->mcr & HD61830_MODE_CURSOR; |
| 385 | int blink = hd61830->mcr & HD61830_MODE_BLINK; |
| 386 | |
| 387 | // cursor off |
| 388 | int pixel = BIT(data, cr); |
| 389 | |
| 390 | if (blink && (ma == hd61830->cac)) |
| 391 | { |
| 392 | // cursor off, character blink |
| 393 | if (!cursor) |
| 394 | pixel = hd61830->cursor ? pixel : 0; |
| 395 | |
| 396 | // cursor blink |
| 397 | if (cursor && (cl == hd61830->cp)) |
| 398 | pixel = hd61830->cursor; |
| 399 | } |
| 400 | else |
| 401 | { |
| 402 | // cursor on |
| 403 | if (cursor && (cl == hd61830->cp)) |
| 404 | pixel = hd61830->cursor; |
| 405 | } |
| 406 | |
| 407 | *BITMAP_ADDR16(bitmap, sy, sx) = pixel; |
| 368 | 408 | } |
| 369 | 409 | } |
| 370 | 410 | } |
| 371 | 411 | |
| 372 | 412 | /*------------------------------------------------- |
| 373 | | update_text- draw text mode screen |
| 413 | update_text - draw text mode screen |
| 374 | 414 | -------------------------------------------------*/ |
| 375 | 415 | |
| 376 | 416 | static void update_text(running_device *device, bitmap_t *bitmap, const rectangle *cliprect) |
| 377 | 417 | { |
| 378 | 418 | hd61830_t *hd61830 = get_safe_token(device); |
| 379 | 419 | |
| 380 | | hd61830->blink++; |
| 381 | | |
| 382 | | for (int y = 0; y < 8; y++) |
| 420 | for (int y = 0; y < (hd61830->nx / hd61830->vp); y++) |
| 383 | 421 | { |
| 384 | 422 | for (int x = 0; x < hd61830->hn; x++) |
| 385 | 423 | { |
| 386 | | UINT8 char_code = hd61830->ram->read_byte(y * hd61830->hn + x); |
| 424 | UINT16 ma = y * hd61830->hn + x; |
| 425 | UINT8 md = hd61830->ram->read_byte(ma); |
| 387 | 426 | |
| 388 | | if (hd61830->cac == y * hd61830->hn + x) |
| 389 | | { |
| 390 | | /* update cursor */ |
| 391 | | switch ((hd61830->mcr >> 2) & 0x03) |
| 392 | | { |
| 393 | | case 0: //cursor OFF |
| 394 | | draw_char(device, bitmap, cliprect, x, y, char_code); |
| 395 | | break; |
| 396 | | |
| 397 | | case 1: //cursor ON |
| 398 | | if (hd61830->blink & 0x20) |
| 399 | | { |
| 400 | | for(int cr = 0; cr < hd61830->hp; cr++) |
| 401 | | { |
| 402 | | *BITMAP_ADDR16(bitmap, y * hd61830->vp + (hd61830->cp - 1), x * hd61830->hp + cr) = 1; |
| 403 | | } |
| 404 | | } |
| 405 | | else |
| 406 | | { |
| 407 | | draw_char(device, bitmap, cliprect, x, y, char_code); |
| 408 | | } |
| 409 | | break; |
| 410 | | |
| 411 | | case 2: //cursor OFF character blink |
| 412 | | case 3: //cursor blank |
| 413 | | if (hd61830->blink & 0x20) |
| 414 | | { |
| 415 | | draw_char(device, bitmap, cliprect, x, y, 0x20); |
| 416 | | } |
| 417 | | else |
| 418 | | { |
| 419 | | draw_char(device, bitmap, cliprect, x, y, char_code); |
| 420 | | } |
| 421 | | break; |
| 422 | | } |
| 423 | | } |
| 424 | | else |
| 425 | | { |
| 426 | | draw_char(device, bitmap, cliprect, x, y, char_code); |
| 427 | | } |
| 427 | draw_char(device, bitmap, cliprect, ma, x, y, md); |
| 428 | 428 | } |
| 429 | 429 | } |
| 430 | 430 | } |
| r9363 | r9364 | |
| 437 | 437 | { |
| 438 | 438 | hd61830_t *hd61830 = get_safe_token(device); |
| 439 | 439 | |
| 440 | | if (hd61830->mcr & HD61830_MODE_GRAPHIC) |
| 440 | if (hd61830->mcr & HD61830_MODE_DISPLAY_ON) |
| 441 | 441 | { |
| 442 | | update_graphics(device, bitmap, cliprect); |
| 442 | if (hd61830->mcr & HD61830_MODE_GRAPHIC) |
| 443 | { |
| 444 | update_graphics(device, bitmap, cliprect); |
| 445 | } |
| 446 | else |
| 447 | { |
| 448 | update_text(device, bitmap, cliprect); |
| 449 | } |
| 443 | 450 | } |
| 444 | 451 | else |
| 445 | 452 | { |
| 446 | | update_text(device, bitmap, cliprect); |
| 453 | bitmap_fill(bitmap, cliprect, 0); |
| 447 | 454 | } |
| 455 | |
| 456 | hd61830->blink++; |
| 457 | |
| 458 | if (hd61830->blink == 0x20) |
| 459 | { |
| 460 | hd61830->blink = 0; |
| 461 | hd61830->cursor = !hd61830->cursor; |
| 462 | } |
| 448 | 463 | } |
| 449 | 464 | |
| 450 | 465 | /*------------------------------------------------- |
| r9363 | r9364 | |
| 470 | 485 | -------------------------------------------------*/ |
| 471 | 486 | |
| 472 | 487 | ROM_START( hd61830 ) |
| 473 | | ROM_REGION( 0x398, "hd61830", ROMREGION_LOADBYNAME ) |
| 474 | | /* this is a fake charset used only for testing, the internal charset is still not dumped */ |
| 475 | | ROM_LOAD( "hd61830.bin", 0x000, 0x2a0, BAD_DUMP CRC(8faff7b9) SHA1(9626d4ace32d495f9840e456a501845fe60ad64c) ) /* internal 7360-bit chargen ROM */ |
| 488 | ROM_REGION( 0x5c0, "hd61830", ROMREGION_LOADBYNAME ) // internal 7360-bit chargen ROM |
| 489 | ROM_LOAD( "hd61830.bin", 0x000, 0x5c0, BAD_DUMP CRC(06a934da) SHA1(bf3f074db5dc92e6f530cb18d6c013563099a87d) ) // typed in from manual |
| 476 | 490 | ROM_END |
| 477 | 491 | |
| 478 | 492 | /*------------------------------------------------- |
| r9363 | r9364 | |
| 483 | 497 | AM_RANGE(0x0000, 0xffff) AM_RAM |
| 484 | 498 | ADDRESS_MAP_END |
| 485 | 499 | |
| 486 | | static ADDRESS_MAP_START( hd61380_rom, 1, 8 ) |
| 487 | | AM_RANGE(0x0000, 0xffff) AM_UNMAP |
| 488 | | ADDRESS_MAP_END |
| 489 | | |
| 490 | 500 | /*------------------------------------------------- |
| 491 | 501 | DEVICE_START( hd61830 ) |
| 492 | 502 | -------------------------------------------------*/ |
| r9363 | r9364 | |
| 494 | 504 | static DEVICE_START( hd61830 ) |
| 495 | 505 | { |
| 496 | 506 | hd61830_t *hd61830 = get_safe_token(device); |
| 497 | | const hd61830_config *config = get_safe_config(device); |
| 507 | const hd61830_interface *intf = get_interface(device); |
| 498 | 508 | |
| 509 | hd61830->rd_r = intf->rd_r; |
| 510 | |
| 499 | 511 | /* get the screen device */ |
| 500 | | hd61830->screen = device->machine->device<screen_device>(config->screen_tag); |
| 512 | hd61830->screen = device->machine->device<screen_device>(intf->screen_tag); |
| 501 | 513 | assert(hd61830->screen != NULL); |
| 502 | 514 | |
| 503 | 515 | hd61830->ram = device_get_space(device, ADDRESS_SPACE_0); |
| 504 | | hd61830->rom = device_get_space(device, ADDRESS_SPACE_1); |
| 505 | 516 | |
| 506 | 517 | /* create the busy timer */ |
| 507 | 518 | hd61830->busy_timer = timer_alloc(device->machine, busy_tick, (void *)device); |
| r9363 | r9364 | |
| 518 | 529 | state_save_register_device_item(device, 0, hd61830->hn); |
| 519 | 530 | state_save_register_device_item(device, 0, hd61830->nx); |
| 520 | 531 | state_save_register_device_item(device, 0, hd61830->cp); |
| 532 | state_save_register_device_item(device, 0, hd61830->blink); |
| 533 | state_save_register_device_item(device, 0, hd61830->cursor); |
| 521 | 534 | } |
| 522 | 535 | |
| 523 | 536 | /*------------------------------------------------- |
| r9363 | r9364 | |
| 542 | 555 | { |
| 543 | 556 | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 544 | 557 | case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(hd61830_t); break; |
| 545 | | case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = sizeof(hd61830_config); break; |
| 558 | case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; |
| 546 | 559 | case DEVINFO_INT_DATABUS_WIDTH_0: info->i = 8; break; |
| 547 | 560 | case DEVINFO_INT_ADDRBUS_WIDTH_0: info->i = 16; break; |
| 548 | 561 | case DEVINFO_INT_ADDRBUS_SHIFT_0: info->i = 0; break; |
| 549 | | case DEVINFO_INT_DATABUS_WIDTH_1: info->i = 8; break; |
| 550 | | case DEVINFO_INT_ADDRBUS_WIDTH_1: info->i = 16; break; |
| 551 | | case DEVINFO_INT_ADDRBUS_SHIFT_1: info->i = 0; break; |
| 552 | 562 | |
| 553 | 563 | /* --- the following bits of info are returned as pointers --- */ |
| 554 | 564 | case DEVINFO_PTR_ROM_REGION: info->romregion = ROM_NAME(hd61830); break; |
| 555 | 565 | |
| 556 | 566 | /* --- the following bits of info are returned as pointers to data --- */ |
| 557 | 567 | case DEVINFO_PTR_DEFAULT_MEMORY_MAP_0: info->default_map8 = ADDRESS_MAP_NAME(hd61380_ram); break; |
| 558 | | case DEVINFO_PTR_DEFAULT_MEMORY_MAP_1: info->default_map8 = ADDRESS_MAP_NAME(hd61380_rom); break; |
| 559 | 568 | |
| 560 | 569 | /* --- the following bits of info are returned as pointers to functions --- */ |
| 561 | 570 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(hd61830); break; |
src/mess/drivers/portfoli.c
| r9363 | r9364 | |
| 513 | 513 | AM_RANGE(0x807f, 0x807f) AM_READWRITE(pid_r, sivr_w) |
| 514 | 514 | ADDRESS_MAP_END |
| 515 | 515 | |
| 516 | | //------------------------------------------------- |
| 517 | | // ADDRESS_MAP( portfolio_lcdc ) |
| 518 | | //------------------------------------------------- |
| 519 | | |
| 520 | | static ADDRESS_MAP_START( portfolio_lcdc, 0, 8 ) |
| 521 | | AM_RANGE(0x0000, 0x07ff) AM_ROM AM_REGION(HD61830_TAG, 0) |
| 522 | | ADDRESS_MAP_END |
| 523 | | |
| 524 | 516 | //************************************************************************** |
| 525 | 517 | // INPUT PORTS |
| 526 | 518 | //************************************************************************** |
| r9363 | r9364 | |
| 649 | 641 | return 0; |
| 650 | 642 | } |
| 651 | 643 | |
| 644 | //------------------------------------------------- |
| 645 | // HD61830_INTERFACE( lcdc_intf ) |
| 646 | //------------------------------------------------- |
| 647 | |
| 648 | static HD61830_RD_READ( hd61830_rd_r ) |
| 649 | { |
| 650 | UINT16 address = (md << 3) | ((ma >> 12) & 0x07); |
| 651 | UINT8 data = memory_region(device->machine, HD61830_TAG)[address]; |
| 652 | |
| 653 | return data; |
| 654 | } |
| 655 | |
| 656 | static HD61830_INTERFACE( lcdc_intf ) |
| 657 | { |
| 658 | SCREEN_TAG, |
| 659 | hd61830_rd_r |
| 660 | }; |
| 661 | |
| 662 | //------------------------------------------------- |
| 663 | // gfx_layout charlayout |
| 664 | //------------------------------------------------- |
| 665 | |
| 666 | static const gfx_layout charlayout = |
| 667 | { |
| 668 | 6, 8, |
| 669 | 256, |
| 670 | 1, |
| 671 | { 0 }, |
| 672 | { 7, 6, 5, 4, 3, 2 }, |
| 673 | { 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8 }, |
| 674 | 8*8 |
| 675 | }; |
| 676 | |
| 677 | //------------------------------------------------- |
| 678 | // GFXDECODE( portfolio ) |
| 679 | //------------------------------------------------- |
| 680 | |
| 681 | static GFXDECODE_START( portfolio ) |
| 682 | GFXDECODE_ENTRY( HD61830_TAG, 0, charlayout, 0, 2 ) |
| 683 | GFXDECODE_END |
| 684 | |
| 652 | 685 | //************************************************************************** |
| 653 | 686 | // DEVICE CONFIGURATION |
| 654 | 687 | //************************************************************************** |
| r9363 | r9364 | |
| 884 | 917 | MDRV_PALETTE_INIT(portfolio) |
| 885 | 918 | |
| 886 | 919 | MDRV_VIDEO_UPDATE(portfolio) |
| 920 | MDRV_GFXDECODE(portfolio) |
| 887 | 921 | |
| 888 | | MDRV_HD61830_CGROM_ADD(HD61830_TAG, XTAL_4_9152MHz/2/2, SCREEN_TAG, portfolio_lcdc) |
| 922 | MDRV_HD61830_ADD(HD61830_TAG, XTAL_4_9152MHz/2/2, lcdc_intf) |
| 889 | 923 | |
| 890 | 924 | /* sound hardware */ |
| 891 | 925 | MDRV_SPEAKER_STANDARD_MONO("mono") |
| r9363 | r9364 | |
| 946 | 980 | ROMX_LOAD( "rom a.u3", 0x20000, 0x20000, BAD_DUMP CRC(b8fb730d) SHA1(1b9d82b824cab830256d34912a643a7d048cd401), ROM_BIOS(1) ) // dumped with debug.com |
| 947 | 981 | |
| 948 | 982 | ROM_REGION( 0x800, HD61830_TAG, 0 ) |
| 949 | | ROM_LOAD( "hd61830 external character generator", 0x000, 0x800, NO_DUMP ) |
| 983 | ROM_LOAD( "hd61830 external character generator", 0x000, 0x800, BAD_DUMP CRC(747a1db3) SHA1(a4b29678fdb43791a8ce4c1ec778f3231bb422c5) ) // typed in from manual |
| 950 | 984 | ROM_END |
| 951 | 985 | |
| 952 | 986 | //************************************************************************** |
| r9363 | r9364 | |
| 954 | 988 | //************************************************************************** |
| 955 | 989 | |
| 956 | 990 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ |
| 957 | | COMP( 1989, pofo, 0, 0, portfolio, portfolio, 0, "Atari", "Portfolio", GAME_NOT_WORKING | GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |
| 991 | COMP( 1989, pofo, 0, 0, portfolio, portfolio, 0, "Atari", "Portfolio", GAME_NOT_WORKING | GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) |