src/mess/drivers/vk100.c
| r15636 | r15637 | |
| 6 | 6 | 28/07/2009 added Guru-readme(TM) |
| 7 | 7 | |
| 8 | 8 | Todo: |
| 9 | handle blink attribute in the vram display renderer |
| 9 | 10 | emulate vector generator hardware enough to write stuff to vram |
| 10 | 11 | * note that since two proms aren't dumped yet some stuff will have to be HLE'd for now |
| 11 | 12 | hook up baud generator to i8251 rx and tx clocks |
| r15636 | r15637 | |
| 121 | 122 | required_device<device_t> m_uart; |
| 122 | 123 | |
| 123 | 124 | UINT8* m_vram; |
| 125 | UINT8* m_trans; |
| 126 | UINT8* m_pattern; |
| 124 | 127 | UINT16 m_vgX; |
| 125 | 128 | UINT16 m_vgY; |
| 126 | 129 | UINT8 m_vgERR; |
| 127 | 130 | UINT8 m_vgSOPS; |
| 128 | 131 | UINT8 m_vgPAT; |
| 129 | | UINT8 m_vgPMUL; |
| 132 | UINT8 m_vgPAT_Shift; // holds the shifted pattern |
| 133 | UINT8 m_vgPMUL; // reload value for pmul_count |
| 134 | UINT8 m_vgPMUL_Count; |
| 130 | 135 | UINT8 m_vgDU; |
| 131 | 136 | UINT8 m_vgDVM; |
| 132 | 137 | UINT8 m_vgDIR; |
| 133 | 138 | UINT8 m_vgWOPS; |
| 134 | 139 | UINT8 m_BAUD; |
| 140 | UINT8 m_EX_TYPE; |
| 141 | UINT8 m_LASTVRAM; |
| 135 | 142 | UINT8 m_GO; |
| 136 | 143 | |
| 137 | 144 | DECLARE_WRITE8_MEMBER(vgLD_X); |
| r15636 | r15637 | |
| 151 | 158 | DECLARE_WRITE8_MEMBER(KBDW); |
| 152 | 159 | DECLARE_WRITE8_MEMBER(BAUD); |
| 153 | 160 | DECLARE_READ8_MEMBER(vk100_keyboard_column_r); |
| 154 | | //DECLARE_READ8_MEMBER(SYSTAT_A); |
| 161 | DECLARE_READ8_MEMBER(SYSTAT_A); |
| 155 | 162 | DECLARE_READ8_MEMBER(SYSTAT_B); |
| 156 | 163 | }; |
| 157 | 164 | |
| 165 | static TIMER_CALLBACK( execute_vg ) |
| 166 | { |
| 167 | /* figure out ram address based on tech manual page 5-24: |
| 168 | * real address to 16-bit chunk a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 |
| 169 | * X+Y input Y8 Y7 Y6 Y5 Y4 Y3 Y2 Y1 X9' X8' X7' X6' X5' X4' |
| 170 | X3' and X2' choose a 4-bit block, X1 and X0 choose a bit within that. |
| 171 | */ |
| 172 | vk100_state *state = machine.driver_data<vk100_state>(); |
| 173 | while (state->m_GO) // temporary hack to draw the entire vector in one call |
| 174 | { |
| 175 | UINT16 X_prime = state->m_trans[state->m_vgX>>2]<<2; |
| 176 | UINT16 EA = (state->m_vgY&0x1FE)<<5|(X_prime>>4); |
| 177 | EA <<= 1; |
| 178 | //UINT16 block = state->m_vram[(EA+(2*i))+1] | (state->m_vram[(EA+(2*i))]<<8); |
| 179 | // pattern rom addressing is a complex mess. see the pattern rom def later in this file. |
| 180 | if (!(X_prime&0x4)) |
| 181 | { // modify the left nybble only |
| 182 | UINT8 tempnyb = (state->m_vram[EA+((X_prime&0x8)>>3)]&0xF0)>>4; |
| 183 | state->m_LASTVRAM = tempnyb; |
| 184 | UINT8 othernyb = (state->m_vram[EA+((X_prime&0x8)>>3)]&0x0F); |
| 185 | tempnyb = state->m_pattern[((state->m_vgPAT&state->m_vgPAT_Shift)?0x200:0)|((state->m_vgWOPS&7)<<6)|((state->m_vgX&3)<<4)|state->m_LASTVRAM]; |
| 186 | tempnyb <<= 4; |
| 187 | state->m_vram[EA+((X_prime&0x8)>>3)] = tempnyb | othernyb; |
| 188 | } |
| 189 | else |
| 190 | { // modify the right nybble only |
| 191 | UINT8 tempnyb = (state->m_vram[EA+((X_prime&0x8)>>3)]&0x0F); |
| 192 | state->m_LASTVRAM = tempnyb; |
| 193 | UINT8 othernyb = (state->m_vram[EA+((X_prime&0x8)>>3)]&0xF0); |
| 194 | tempnyb = state->m_pattern[((state->m_vgPAT&state->m_vgPAT_Shift)?0x200:0)|((state->m_vgWOPS&7)<<6)|((state->m_vgX&3)<<4)|state->m_LASTVRAM]; |
| 195 | state->m_vram[EA+((X_prime&0x8)>>3)] = tempnyb | othernyb; |
| 196 | } |
| 197 | if (state->m_vgWOPS&0x08) state->m_vram[EA+1] = (state->m_vgWOPS&0xF0)>>4; |
| 198 | state->m_vgX++;// TODO: since the direction rom is missing; the vector generator direction is FIXED rightward! |
| 199 | //printf("VG state: EA: %d, lastvram: %d, curvram: %d, pmulcount: %d |
| 200 | if (((++state->m_vgPMUL_Count)&0xF)==0) { |
| 201 | state->m_vgPMUL_Count = state->m_vgPMUL; // reload counter |
| 202 | if (state->m_vgPAT_Shift == 0x01) state->m_GO = 0; // check if the pattern shifter is empty, if so we're done |
| 203 | state->m_vgPAT_Shift >>= 1; |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | |
| 158 | 208 | /* |
| 159 | 209 | void drawVector(UINT16 px, UINT16 py, UINT16 x, UINT16 y, int pattern) |
| 160 | 210 | { |
| r15636 | r15637 | |
| 276 | 326 | #endif |
| 277 | 327 | // TODO: short term: do some calculations here and print the expected starting ram address etc |
| 278 | 328 | // TODO: long term: fire a timer and actually move the ram with correct timing |
| 329 | m_vgPMUL_Count = m_vgPMUL; // load PMUL_Count |
| 330 | m_vgPAT_Shift = 0x80; // load vgPAT_Shift |
| 331 | m_EX_TYPE = 0; |
| 279 | 332 | m_GO = 1; |
| 333 | machine().scheduler().timer_set(attotime::zero, FUNC(execute_vg)); |
| 280 | 334 | } |
| 281 | 335 | |
| 282 | 336 | /* port 0x65: "EX DOT" execute a dot (start the state machine) */ |
| r15636 | r15637 | |
| 287 | 341 | #endif |
| 288 | 342 | // TODO: short term: do some calculations here and print the expected starting ram address etc |
| 289 | 343 | // TODO: long term: fire a timer and actually draw the dot to ram with correct timing |
| 344 | m_vgPMUL_Count = m_vgPMUL; // load PMUL_Count |
| 345 | m_vgPAT_Shift = 0x80; // load vgPAT_Shift |
| 346 | m_EX_TYPE = 1; |
| 290 | 347 | m_GO = 1; |
| 348 | machine().scheduler().timer_set(attotime::zero, FUNC(execute_vg)); |
| 291 | 349 | } |
| 292 | 350 | |
| 293 | 351 | /* port 0x66: "EX VEC" execute a pattern (8 fixed direction) vector (start the state machine) */ |
| r15636 | r15637 | |
| 298 | 356 | #endif |
| 299 | 357 | // TODO: short term: do some calculations here and print the expected starting ram address etc |
| 300 | 358 | // TODO: long term: fire a timer and actually draw the vector to ram with correct timing |
| 359 | m_vgPMUL_Count = m_vgPMUL; // load PMUL_Count |
| 360 | m_vgPAT_Shift = 0x80; // load vgPAT_Shift |
| 361 | m_EX_TYPE = 2; |
| 301 | 362 | m_GO = 1; |
| 363 | machine().scheduler().timer_set(attotime::zero, FUNC(execute_vg)); |
| 302 | 364 | } |
| 303 | 365 | |
| 304 | 366 | /* port 0x67: "EX ER" execute an arbitrary bresenham vector (start the state machine) */ |
| r15636 | r15637 | |
| 309 | 371 | #endif |
| 310 | 372 | // TODO: short term: do some calculations here and print the expected starting ram address etc |
| 311 | 373 | // TODO: long term: fire a timer and actually use the state machine to draw the vector to ram with correct timing |
| 374 | m_vgPMUL_Count = m_vgPMUL; // load PMUL_Count |
| 375 | m_vgPAT_Shift = 0x80; // load vgPAT_Shift |
| 376 | m_EX_TYPE = 3; |
| 312 | 377 | m_GO = 1; |
| 378 | machine().scheduler().timer_set(attotime::zero, FUNC(execute_vg)); |
| 313 | 379 | } |
| 314 | 380 | |
| 315 | 381 | /* port 0x68: "KBDW" d7 is beeper, d6 is keyclick, d5-d0 are keyboard LEDS */ |
| r15636 | r15637 | |
| 347 | 413 | 299 reads, rotates result right 3 times and ANDs the result with 0x0F |
| 348 | 414 | 2A4 reads, rotates result left 1 time and ANDS the result with 0xF0 |
| 349 | 415 | */ |
| 350 | | /*READ8_MEMBER(vk100_state::SYSTAT_A) |
| 416 | READ8_MEMBER(vk100_state::SYSTAT_A) |
| 351 | 417 | { |
| 352 | | return ((1-m_GO)<<7)|0x7F; |
| 353 | | }*/ |
| 418 | return ((m_GO?0:1)<<7)|(m_LASTVRAM<<3)|0x7; |
| 419 | } |
| 354 | 420 | |
| 355 | 421 | /* port 0x48: "SYSTAT B"; NOT documented in the tech manual */ |
| 356 | 422 | READ8_MEMBER(vk100_state::SYSTAT_B) |
| r15636 | r15637 | |
| 404 | 470 | //AM_RANGE (0x74, 0x74) AM_WRITE(unknown_74) |
| 405 | 471 | //AM_RANGE (0x78, 0x78) AM_WRITE(kbdw) //KBDW ?(mirror?) |
| 406 | 472 | //AM_RANGE (0x7C, 0x7C) AM_WRITE(unknown_7C) |
| 407 | | //AM_RANGE (0x40, 0x40) AM_READ(SYSTAT_A) // SYSTAT A (state machine done and last 4 bits of vram) |
| 473 | AM_RANGE (0x40, 0x40) AM_READ(SYSTAT_A) // SYSTAT A (state machine done and last 4 bits of vram) |
| 408 | 474 | AM_RANGE (0x48, 0x48) AM_READ(SYSTAT_B) // SYSTAT B (dipswitches?) |
| 409 | 475 | AM_RANGE(0x50, 0x50) AM_DEVREAD("i8251", i8251_device, data_r) // UART O |
| 410 | 476 | AM_RANGE(0x51, 0x51) AM_DEVREAD("i8251", i8251_device, status_r) // UAR |
| r15636 | r15637 | |
| 589 | 655 | state->m_vgERR = 0; |
| 590 | 656 | state->m_vgSOPS = 0; |
| 591 | 657 | state->m_vgPAT = 0; |
| 658 | state->m_vgPAT_Shift = 0x80; |
| 592 | 659 | state->m_vgPMUL = 0; |
| 660 | state->m_vgPMUL_Count = 0; |
| 593 | 661 | state->m_vgDU = 0; |
| 594 | 662 | state->m_vgDVM = 0; |
| 595 | 663 | state->m_vgDIR = 0; |
| 596 | 664 | state->m_vgWOPS = 0; |
| 597 | 665 | state->m_BAUD = 0; |
| 666 | state->m_EX_TYPE = 0; |
| 667 | state->m_LASTVRAM = 0xF; |
| 598 | 668 | state->m_GO = 0; |
| 599 | 669 | } |
| 600 | 670 | |
| 601 | 671 | static DRIVER_INIT( vk100 ) |
| 602 | 672 | { |
| 603 | 673 | UINT8 *gfx = machine.root_device().memregion("vram")->base(); |
| 604 | | int i; |
| 605 | | for (i = 0; i < 0x8000; i++) |
| 606 | | gfx[i] = (((i&0x1)?0x00:0xFF)^((i&0x100)?0x00:0xff)); |
| 674 | // for debug purposes, set the entire screen to black but with the attributes of all pixels set to white |
| 675 | for (int i = 1; i < 0x8000; i+=2) |
| 676 | gfx[i] = 0xF; |
| 677 | //gfx[i] = (((i&0x1)?0x00:0xFF)^((i&0x100)?0x00:0xff)); |
| 607 | 678 | } |
| 608 | 679 | |
| 609 | 680 | static PALETTE_INIT( vk100 ) |
| r15636 | r15637 | |
| 619 | 690 | vk100_state *state = device->machine().driver_data<vk100_state>(); |
| 620 | 691 | device_set_input_line(state->m_maincpu, I8085_RST75_LINE, ASSERT_LINE); |
| 621 | 692 | device_set_input_line(state->m_maincpu, I8085_RST75_LINE, CLEAR_LINE); |
| 622 | | state->m_GO = 0; // hack for now until the state machine works |
| 623 | 693 | } |
| 624 | 694 | |
| 625 | 695 | static WRITE_LINE_DEVICE_HANDLER(i8251_rxrdy_int) |
| r15636 | r15637 | |
| 638 | 708 | { |
| 639 | 709 | vk100_state *state = machine.driver_data<vk100_state>(); |
| 640 | 710 | state->m_vram = state->memregion("vram")->base(); |
| 711 | state->m_trans = state->memregion("trans")->base(); |
| 712 | state->m_pattern = state->memregion("pattern")->base(); |
| 641 | 713 | } |
| 642 | 714 | |
| 643 | 715 | static MC6845_UPDATE_ROW( vk100_update_row ) |
| r15636 | r15637 | |
| 658 | 730 | { |
| 659 | 731 | UINT16 block = state->m_vram[(EA+(2*i))+1] | (state->m_vram[(EA+(2*i))]<<8); |
| 660 | 732 | UINT8 fgColor = block&7; |
| 733 | // TODO: blink is NOT HANDLED YET!; is this done by using the cursor output of the CRTC somehow? |
| 661 | 734 | //UINT8 blink = (block&8)>>3; |
| 662 | 735 | UINT8 bgColor = (state->m_vgSOPS&0x70)>>4; |
| 663 | | if (state->m_vgSOPS&1) // reverse fg/bg colors |
| 664 | | { |
| 665 | | UINT8 temp = fgColor; |
| 666 | | fgColor = bgColor; |
| 667 | | bgColor = temp; |
| 668 | | } |
| 669 | 736 | // display a 12-bit wide chunk |
| 670 | 737 | for (int j = 0; j < 12; j++) |
| 671 | 738 | { |
| 672 | | bitmap.pix32(y, (12*i)+j) = (block&(0x10<<j))?colorTable[fgColor]:colorTable[bgColor]; |
| 739 | bitmap.pix32(y, (12*i)+j) = ((block&(0x10<<j))^(state->m_vgSOPS&1))?colorTable[fgColor]:colorTable[bgColor]; |
| 673 | 740 | } |
| 674 | 741 | } |
| 675 | 742 | } |
| r15636 | r15637 | |
| 741 | 808 | ROM_LOAD( "23-018e4-00.rom3.ic53", 0x4000, 0x2000, CRC(b3e7903b) SHA1(8ad6ed25cd9b04a9968aa09ab69ba526d35ca550)) |
| 742 | 809 | ROM_LOAD( "23-190e2-00.rom4.ic54", 0x6000, 0x1000, CRC(ad596fa5) SHA1(b30a24155640d32c1b47a3a16ea33cd8df2624f6)) |
| 743 | 810 | |
| 744 | | ROM_REGION( 0x8000, "vram", ROMREGION_ERASEFF ) // 32k of vram |
| 811 | ROM_REGION( 0x8000, "vram", ROMREGION_ERASE00 ) // 32k of vram |
| 745 | 812 | |
| 746 | 813 | ROM_REGION( 0x400, "pattern", ROMREGION_ERASEFF ) |
| 747 | 814 | /* This is the "PATTERN ROM", (1k*4, 82s137) |
| r15636 | r15637 | |
| 753 | 820 | i.e. addr bits 9876543210 |
| 754 | 821 | ||||||\\\\- input from ram A |
| 755 | 822 | ||||\\----- bit select (from x reg lsb) |
| 756 | | |||\------- negate N |
| 757 | | |\\-------- function |
| 823 | |||\------- negate N \___ low 3 bits of WOPS |
| 824 | |\\-------- function / |
| 758 | 825 | \---------- pattern bit P |
| 759 | 826 | functions are: |
| 760 | 827 | Overlay: M=A|(P^N) |
| r15636 | r15637 | |
| 763 | 830 | Erase: M=N |
| 764 | 831 | */ |
| 765 | 832 | ROM_LOAD( "wb8201_656f1.m1-7643-5.pr4.ic17", 0x0000, 0x0400, CRC(e8ecf59f) SHA1(49e9d109dad3d203d45471a3f4ca4985d556161f)) // label verified from nigwil's board |
| 766 | | |
| 767 | | ROM_REGION( 0x10000, "proms", ROMREGION_ERASEFF ) |
| 833 | |
| 834 | ROM_REGION(0x100, "trans", ROMREGION_ERASEFF ) |
| 835 | // this is definitely the "TRANSLATOR ROM" described in figure 5-17 on page 5-27 (256*8, 82s135) |
| 836 | // it contains a table of 256 values which skips every fourth value so 00 01 02 04 05 06 08.. etc, wraps at the end |
| 837 | ROM_LOAD( "wb---0_060b1.6309.pr2.ic77", 0x0000, 0x0100, CRC(198317fc) SHA1(00e97104952b3fbe03a4f18d800d608b837d10ae)) // label verified from nigwil's board |
| 838 | |
| 839 | ROM_REGION( 0x400, "proms", ROMREGION_ERASEFF ) |
| 768 | 840 | // not sure what this prom is, it may relate somehow to addressing or modifying vram. (256*4, 82s129) |
| 769 | 841 | ROM_LOAD( "wb8151_573a2.6301.pr3.ic44", 0x0000, 0x0100, CRC(75885a9f) SHA1(c721dad6a69c291dd86dad102ed3a8ddd620ecc4)) // label verified from nigwil's and andy's board |
| 770 | 842 | // this is probably the "SYNC ROM" since only addresses 0-6 are used within every 8 byte chunk. (256*8, 82s135) |
| 771 | 843 | ROM_LOAD( "wb8146_058b1.6309.pr1.ic99", 0x0100, 0x0100, CRC(71b01864) SHA1(e552f5b0bc3f443299282b1da7e9dbfec60e12bf)) // label verified from nigwil's and andy's board |
| 772 | | // this is definitely the "TRANSLATOR ROM" described in figure 5-17 on page 5-27 (256*8, 82s135) |
| 773 | | // it contains a table of 256 values which skips every fourth value so 00 01 02 04 05 06 08.. etc, wraps at the end |
| 774 | | ROM_LOAD( "wb---0_060b1.6309.pr2.ic77", 0x0200, 0x0100, CRC(198317fc) SHA1(00e97104952b3fbe03a4f18d800d608b837d10ae)) // label verified from nigwil's board |
| 775 | 844 | // the following == mb6309 (256x8, 82s135) // probably direction rom |
| 776 | | ROM_LOAD( "wb8141_059b1.tbp18s22n.pr5.ic108", 0x0300, 0x0100, NO_DUMP) // label verified from andy's board |
| 845 | ROM_LOAD( "wb8141_059b1.tbp18s22n.pr5.ic108", 0x0200, 0x0100, NO_DUMP) // label verified from andy's board |
| 777 | 846 | // the following = mb6331 (32x8, 82s123) // MAYBE vector rom |
| 778 | | ROM_LOAD( "wb8214_297a1.74s288.pr6.ic89", 0x0400, 0x0100, NO_DUMP) // label verified from nigwil's and andy's board |
| 847 | ROM_LOAD( "wb8214_297a1.74s288.pr6.ic89", 0x0300, 0x0100, NO_DUMP) // label verified from nigwil's and andy's board |
| 779 | 848 | ROM_END |
| 780 | 849 | |
| 781 | 850 | /* Driver */ |