src/mess/machine/microtan.c
| r7489 | r7490 | |
| 24 | 24 | |
| 25 | 25 | /* Devices */ |
| 26 | 26 | #include "devices/cassette.h" |
| 27 | | #include "devices/snapquik.h" |
| 27 | //#include "devices/snapquik.h" |
| 28 | 28 | |
| 29 | 29 | |
| 30 | 30 | #ifndef VERBOSE |
| r7489 | r7490 | |
| 416 | 416 | } |
| 417 | 417 | } |
| 418 | 418 | |
| 419 | | static int microtan_varify_snapshot(UINT8 *data, int size) |
| 420 | | { |
| 421 | | if (size == 8263) |
| 422 | | { |
| 423 | | LOG(("microtan_snapshot_id: magic size %d found\n", size)); |
| 424 | | return IMAGE_VERIFY_PASS; |
| 425 | | } |
| 426 | | else |
| 427 | | { |
| 428 | | if (4 + data[2] + 256 * data[3] + 1 + 16 + 16 + 16 + 1 + 1 + 16 + 16 + 64 + 7 == size) |
| 429 | | { |
| 430 | | LOG(("microtan_snapshot_id: header RAM size + structures matches filesize %d\n", size)); |
| 431 | | return IMAGE_VERIFY_PASS; |
| 432 | | } |
| 433 | | } |
| 434 | | |
| 435 | | return IMAGE_VERIFY_FAIL; |
| 436 | | } |
| 437 | | |
| 438 | | static int parse_intel_hex(UINT8 *snapshot_buff, char *src) |
| 439 | | { |
| 440 | | char line[128]; |
| 441 | | int /*row = 0,*/ column = 0, last_addr = 0, last_size = 0; |
| 442 | | |
| 443 | | while (*src) |
| 444 | | { |
| 445 | | if (*src == '\r' || *src == '\n') |
| 446 | | { |
| 447 | | if (column) |
| 448 | | { |
| 449 | | unsigned int size, addr, null, b[32], cs, n; |
| 450 | | |
| 451 | | line[column] = '\0'; |
| 452 | | /*row++;*/ |
| 453 | | n = sscanf(line, ":%02x%04x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", |
| 454 | | &size, &addr, &null, |
| 455 | | &b[ 0], &b[ 1], &b[ 2], &b[ 3], &b[ 4], &b[ 5], &b[ 6], &b[ 7], |
| 456 | | &b[ 8], &b[ 9], &b[10], &b[11], &b[12], &b[13], &b[14], &b[15], |
| 457 | | &b[16], &b[17], &b[18], &b[19], &b[20], &b[21], &b[22], &b[23], |
| 458 | | &b[24], &b[25], &b[26], &b[27], &b[28], &b[29], &b[30], &b[31], |
| 459 | | &cs); |
| 460 | | if (n == 0) |
| 461 | | { |
| 462 | | LOG(("parse_intel_hex: malformed line [%s]\n", line)); |
| 463 | | } |
| 464 | | else if (n == 1) |
| 465 | | { |
| 466 | | LOG(("parse_intel_hex: only size found [%s]\n", line)); |
| 467 | | } |
| 468 | | else if (n == 2) |
| 469 | | { |
| 470 | | LOG(("parse_intel_hex: only size and addr found [%s]\n", line)); |
| 471 | | } |
| 472 | | else if (n == 3) |
| 473 | | { |
| 474 | | LOG(("parse_intel_hex: only size, addr and null found [%s]\n", line)); |
| 475 | | } |
| 476 | | else |
| 477 | | if (null != 0) |
| 478 | | { |
| 479 | | LOG(("parse_intel_hex: warning null byte is != 0 [%s]\n", line)); |
| 480 | | } |
| 481 | | else |
| 482 | | { |
| 483 | | int i, sum; |
| 484 | | |
| 485 | | n -= 3; |
| 486 | | |
| 487 | | sum = size + (addr & 0xff) + ((addr >> 8) & 0xff); |
| 488 | | if (n != 32 + 1) |
| 489 | | cs = b[n-1]; |
| 490 | | |
| 491 | | last_addr = addr; |
| 492 | | last_size = n-1; |
| 493 | | LOG(("parse_intel_hex: %04X", addr)); |
| 494 | | for (i = 0; i < n-1; i++) |
| 495 | | { |
| 496 | | sum += b[i]; |
| 497 | | snapshot_buff[addr++] = b[i]; |
| 498 | | } |
| 499 | | LOG(("-%04X checksum %02X+%02X = %02X\n", addr-1, cs, sum & 0xff, (cs + sum) & 0xff)); |
| 500 | | } |
| 501 | | } |
| 502 | | column = 0; |
| 503 | | } |
| 504 | | else |
| 505 | | { |
| 506 | | line[column++] = *src; |
| 507 | | } |
| 508 | | src++; |
| 509 | | } |
| 510 | | /* register preset? */ |
| 511 | | if (last_size == 7) |
| 512 | | { |
| 513 | | LOG(("parse_intel_hex: registers (?) at %04X\n", last_addr)); |
| 514 | | memcpy(&snapshot_buff[8192+64], &snapshot_buff[last_addr], last_size); |
| 515 | | } |
| 516 | | return INIT_PASS; |
| 517 | | } |
| 518 | | |
| 519 | | static int parse_zillion_hex(UINT8 *snapshot_buff, char *src) |
| 520 | | { |
| 521 | | char line[128]; |
| 522 | | int parsing = 0, /*row = 0,*/ column = 0; |
| 523 | | |
| 524 | | while (*src) |
| 525 | | { |
| 526 | | if (parsing) |
| 527 | | { |
| 528 | | if (*src == '}') |
| 529 | | parsing = 0; |
| 530 | | else |
| 531 | | { |
| 532 | | if (*src == '\r' || *src == '\n') |
| 533 | | { |
| 534 | | if (column) |
| 535 | | { |
| 536 | | unsigned int addr, b[8], n; |
| 537 | | |
| 538 | | line[column] = '\0'; |
| 539 | | /*row++;*/ |
| 540 | | n = sscanf(line, "%x %x %x %x %x %x %x %x %x", &addr, &b[0], &b[1], &b[2], &b[3], &b[4], &b[5], &b[6], &b[7]); |
| 541 | | if (n == 0) |
| 542 | | { |
| 543 | | LOG(("parse_zillion_hex: malformed line [%s]\n", line)); |
| 544 | | } |
| 545 | | else if (n == 1) |
| 546 | | { |
| 547 | | LOG(("parse_zillion_hex: only addr found [%s]\n", line)); |
| 548 | | } |
| 549 | | else |
| 550 | | { |
| 551 | | int i; |
| 552 | | |
| 553 | | LOG(("parse_zillion_hex: %04X", addr)); |
| 554 | | for (i = 0; i < n-1; i++) |
| 555 | | snapshot_buff[addr++] = b[i]; |
| 556 | | LOG(("-%04X\n", addr-1)); |
| 557 | | } |
| 558 | | } |
| 559 | | column = 0; |
| 560 | | } |
| 561 | | else |
| 562 | | { |
| 563 | | line[column++] = *src; |
| 564 | | } |
| 565 | | } |
| 566 | | } |
| 567 | | else |
| 568 | | { |
| 569 | | if (*src == '\r' || *src == '\n') |
| 570 | | { |
| 571 | | if (column) |
| 572 | | { |
| 573 | | int addr, n; |
| 574 | | |
| 575 | | /*row++;*/ |
| 576 | | line[column] = '\0'; |
| 577 | | n = sscanf(line, "G%x", (unsigned int *) &addr); |
| 578 | | if (n == 1 && !snapshot_buff[8192+64+1] && !snapshot_buff[8192+64+1]) |
| 579 | | { |
| 580 | | LOG(("microtan_hexfile_init: go addr %04X\n", addr)); |
| 581 | | snapshot_buff[8192+64+0] = addr & 0xff; |
| 582 | | snapshot_buff[8192+64+1] = (addr >> 8) & 0xff; |
| 583 | | } |
| 584 | | } |
| 585 | | column = 0; |
| 586 | | } |
| 587 | | else |
| 588 | | { |
| 589 | | line[column++] = *src; |
| 590 | | } |
| 591 | | if (*src == '{') |
| 592 | | { |
| 593 | | parsing = 1; |
| 594 | | column = 0; |
| 595 | | } |
| 596 | | } |
| 597 | | src++; |
| 598 | | } |
| 599 | | return INIT_PASS; |
| 600 | | } |
| 601 | | |
| 602 | 419 | static void store_key(running_machine *machine, int key) |
| 603 | 420 | { |
| 604 | 421 | LOG(("microtan: store key '%c'\n", key)); |
| r7489 | r7490 | |
| 697 | 514 | } |
| 698 | 515 | } |
| 699 | 516 | |
| 700 | | static void microtan_set_cpu_regs(running_machine *machine,const UINT8 *snapshot_buff, int base) |
| 701 | | { |
| 702 | | LOG(("microtan_snapshot_copy: PC:%02X%02X P:%02X A:%02X X:%02X Y:%02X SP:1%02X", |
| 703 | | snapshot_buff[base+1], snapshot_buff[base+0], snapshot_buff[base+2], snapshot_buff[base+3], |
| 704 | | snapshot_buff[base+4], snapshot_buff[base+5], snapshot_buff[base+6]); |
| 705 | | cpu_set_reg(devtag_get_device(machine, "maincpu"), M6502_PC, snapshot_buff[base+0] + 256 * snapshot_buff[base+1])); |
| 706 | | cpu_set_reg(devtag_get_device(machine, "maincpu"), M6502_P, snapshot_buff[base+2]); |
| 707 | | cpu_set_reg(devtag_get_device(machine, "maincpu"), M6502_A, snapshot_buff[base+3]); |
| 708 | | cpu_set_reg(devtag_get_device(machine, "maincpu"), M6502_X, snapshot_buff[base+4]); |
| 709 | | cpu_set_reg(devtag_get_device(machine, "maincpu"), M6502_Y, snapshot_buff[base+5]); |
| 710 | | cpu_set_reg(devtag_get_device(machine, "maincpu"), M6502_S, snapshot_buff[base+6]); |
| 711 | | } |
| 712 | | |
| 713 | | static void microtan_snapshot_copy(running_machine *machine, UINT8 *snapshot_buff, int snapshot_size) |
| 714 | | { |
| 715 | | UINT8 *RAM = memory_region(machine, "maincpu"); |
| 716 | | const address_space *space = cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM); |
| 717 | | running_device *via_0 = devtag_get_device(machine, "via6522_0"); |
| 718 | | running_device *via_1 = devtag_get_device(machine, "via6522_1"); |
| 719 | | running_device *ay8910 = devtag_get_device(machine, "ay8910.1"); |
| 720 | | |
| 721 | | /* check for .DMP file format */ |
| 722 | | if (snapshot_size == 8263) |
| 723 | | { |
| 724 | | int i, base; |
| 725 | | /********** DMP format |
| 726 | | * Lower 8k of RAM (0000 to 1fff) |
| 727 | | * 64 bytes of chunky graphics bits (first byte bit is for character at 0200, bit 1=0201, etc) |
| 728 | | * 7 bytes of CPU registers (PCL, PCH, PSW, A, IX, IY, SP) |
| 729 | | */ |
| 730 | | LOG(("microtan_snapshot_copy: magic size %d found, assuming *.DMP format\n", snapshot_size)); |
| 731 | | |
| 732 | | base = 0; |
| 733 | | /* 8K of RAM from 0000 to 1fff */ |
| 734 | | memcpy(RAM, &snapshot_buff[base], 8192); |
| 735 | | base += 8192; |
| 736 | | /* 64 bytes of chunky graphics info */ |
| 737 | | for (i = 0; i < 32*16; i++) |
| 738 | | { |
| 739 | | microtan_chunky_buffer[i] = (snapshot_buff[base+i/8] >> (i&7)) & 1; |
| 740 | | } |
| 741 | | base += 64; |
| 742 | | microtan_set_cpu_regs(machine, snapshot_buff, base); |
| 743 | | } |
| 744 | | else |
| 745 | | { |
| 746 | | int i, ramend, base; |
| 747 | | /********** M65 format ************************************ |
| 748 | | * 2 bytes: File version |
| 749 | | * 2 bytes: RAM size |
| 750 | | * n bytes: RAM (0000 to RAM Size) |
| 751 | | * 16 bytes: 1st 6522 (0xbfc0 to 0xbfcf) |
| 752 | | * 16 bytes: 2ns 6522 (0xbfe0 to 0xbfef) |
| 753 | | * 16 bytes: Microtan IO (0xbff0 to 0xbfff) |
| 754 | | * 1 byte : Invaders sound (0xbc04) |
| 755 | | * 1 byte : Chunky graphics state (0=off, 1=on) |
| 756 | | * 16 bytes: 1st AY8910 registers |
| 757 | | * 16 bytes: 2nd AY8910 registers |
| 758 | | * 64 bytes: Chunky graphics bits (first byte bit 0 is for character at 0200, bit 1=0201, etc) |
| 759 | | * 7 bytes: CPU registers (PCL, PCH, PSW, A, IX, IY, SP) |
| 760 | | */ |
| 761 | | ramend = snapshot_buff[2] + 256 * snapshot_buff[3]; |
| 762 | | if (2 + 2 + ramend + 1 + 16 + 16 + 16 + 1 + 1 + 16 + 16 + 64 + 7 != snapshot_size) |
| 763 | | { |
| 764 | | LOG(("microtan_snapshot_copy: size %d doesn't match RAM size %d + structure size\n", snapshot_size, ramend+1)); |
| 765 | | return; |
| 766 | | } |
| 767 | | |
| 768 | | LOG(("microtan_snapshot_copy: size %d found, assuming *.M65 format\n", snapshot_size)); |
| 769 | | base = 4; |
| 770 | | memcpy(RAM, &snapshot_buff[base], snapshot_buff[2] + 256 * snapshot_buff[3] + 1); |
| 771 | | base += ramend + 1; |
| 772 | | |
| 773 | | /* first set of VIA6522 registers */ |
| 774 | | for (i = 0; i < 16; i++ ) |
| 775 | | via_w(via_0, i, snapshot_buff[base++]); |
| 776 | | |
| 777 | | /* second set of VIA6522 registers */ |
| 778 | | for (i = 0; i < 16; i++ ) |
| 779 | | via_w(via_1, i, snapshot_buff[base++]); |
| 780 | | |
| 781 | | /* microtan IO bff0-bfff */ |
| 782 | | for (i = 0; i < 16; i++ ) |
| 783 | | { |
| 784 | | RAM[0xbff0+i] = snapshot_buff[base++]; |
| 785 | | if (i < 4) |
| 786 | | microtan_bffx_w(space, i, RAM[0xbff0+i]); |
| 787 | | } |
| 788 | | |
| 789 | | microtan_sound_w(space, 0, snapshot_buff[base++]); |
| 790 | | microtan_chunky_graphics = snapshot_buff[base++]; |
| 791 | | |
| 792 | | /* first set of AY8910 registers */ |
| 793 | | for (i = 0; i < 16; i++ ) |
| 794 | | { |
| 795 | | ay8910_address_w(ay8910, 0, i); |
| 796 | | ay8910_data_w(ay8910, 0, snapshot_buff[base++]); |
| 797 | | } |
| 798 | | |
| 799 | | /* second set of AY8910 registers */ |
| 800 | | for (i = 0; i < 16; i++ ) |
| 801 | | { |
| 802 | | ay8910_address_w(ay8910, 0, i); |
| 803 | | ay8910_data_w(ay8910, 0, snapshot_buff[base++]); |
| 804 | | } |
| 805 | | |
| 806 | | for (i = 0; i < 32*16; i++) |
| 807 | | { |
| 808 | | microtan_chunky_buffer[i] = (snapshot_buff[base+i/8] >> (i&7)) & 1; |
| 809 | | } |
| 810 | | base += 64; |
| 811 | | |
| 812 | | microtan_set_cpu_regs(machine, snapshot_buff, base); |
| 813 | | } |
| 814 | | } |
| 815 | | |
| 816 | | SNAPSHOT_LOAD( microtan ) |
| 817 | | { |
| 818 | | UINT8 *snapshot_buff; |
| 819 | | |
| 820 | | snapshot_buff = (UINT8*)image_ptr(image); |
| 821 | | if (!snapshot_buff) |
| 822 | | return INIT_FAIL; |
| 823 | | |
| 824 | | if (microtan_varify_snapshot(snapshot_buff, snapshot_size)==IMAGE_VERIFY_FAIL) |
| 825 | | return INIT_FAIL; |
| 826 | | |
| 827 | | microtan_snapshot_copy(image->machine, snapshot_buff, snapshot_size); |
| 828 | | return INIT_PASS; |
| 829 | | } |
| 830 | | |
| 831 | | QUICKLOAD_LOAD( microtan_hexfile ) |
| 832 | | { |
| 833 | | int snapshot_size; |
| 834 | | UINT8 *snapshot_buff; |
| 835 | | char *buff; |
| 836 | | int rc; |
| 837 | | |
| 838 | | snapshot_size = 8263; /* magic size */ |
| 839 | | snapshot_buff = (UINT8*)malloc(snapshot_size); |
| 840 | | if (!snapshot_buff) |
| 841 | | { |
| 842 | | LOG(("microtan_hexfile_load: could not allocate %d bytes of buffer\n", snapshot_size)); |
| 843 | | return INIT_FAIL; |
| 844 | | } |
| 845 | | memset(snapshot_buff, 0, snapshot_size); |
| 846 | | |
| 847 | | buff = (char*)malloc(quickload_size + 1); |
| 848 | | if (!buff) |
| 849 | | { |
| 850 | | free(snapshot_buff); |
| 851 | | LOG(("microtan_hexfile_load: could not allocate %d bytes of buffer\n", quickload_size)); |
| 852 | | return INIT_FAIL; |
| 853 | | } |
| 854 | | image_fread(image, buff, quickload_size); |
| 855 | | |
| 856 | | buff[quickload_size] = '\0'; |
| 857 | | |
| 858 | | if (buff[0] == ':') |
| 859 | | rc = parse_intel_hex(snapshot_buff, buff); |
| 860 | | else |
| 861 | | rc = parse_zillion_hex(snapshot_buff, buff); |
| 862 | | if (rc == INIT_PASS) |
| 863 | | microtan_snapshot_copy(image->machine, snapshot_buff, snapshot_size); |
| 864 | | free(snapshot_buff); |
| 865 | | return rc; |
| 866 | | } |
| 867 | | |
| 868 | 517 | DRIVER_INIT( microtan ) |
| 869 | 518 | { |
| 870 | 519 | UINT8 *dst = memory_region(machine, "gfx2"); |