trunk/src/emu/video/upd7220.c
| r32712 | r32713 | |
| 18 | 18 | - DMAR |
| 19 | 19 | - DMAW |
| 20 | 20 | - incomplete / unimplemented FIGD / GCHRD draw modes |
| 21 | | - Arc |
| 22 | 21 | - FIGD character |
| 23 | 22 | - slanted character |
| 24 | | - GCHRD character (needs rewrite) |
| 25 | 23 | - read-modify-write cycle |
| 26 | 24 | - read data |
| 27 | 25 | - modify data |
| r32712 | r32713 | |
| 134 | 132 | |
| 135 | 133 | static const int x_dir[8] = { 0, 1, 1, 1, 0,-1,-1,-1}; |
| 136 | 134 | static const int y_dir[8] = { 1, 1, 0,-1,-1,-1, 0, 1}; |
| 137 | | static const int x_dir_dot[8] = { 1, 1, 0,-1,-1,-1, 0, 1}; |
| 138 | | static const int y_dir_dot[8] = { 0,-1,-1,-1, 0, 1, 1, 1}; |
| 139 | 135 | |
| 140 | 136 | |
| 141 | | |
| 142 | 137 | //************************************************************************** |
| 143 | 138 | // GLOBAL VARIABLES |
| 144 | 139 | //************************************************************************** |
| r32712 | r32713 | |
| 206 | 201 | space().write_byte(address, data); |
| 207 | 202 | } |
| 208 | 203 | |
| 209 | | |
| 210 | 204 | //------------------------------------------------- |
| 211 | 205 | // fifo_clear - |
| 212 | 206 | //------------------------------------------------- |
| r32712 | r32713 | |
| 429 | 423 | |
| 430 | 424 | |
| 431 | 425 | //------------------------------------------------- |
| 432 | | // advance_ead - |
| 433 | | //------------------------------------------------- |
| 434 | | |
| 435 | | inline void upd7220_device::advance_ead() |
| 436 | | { |
| 437 | | #define EAD m_ead |
| 438 | | #define DAD m_dad |
| 439 | | #define P x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch) |
| 440 | | #define MSB(value) (BIT(value, 15)) |
| 441 | | #define LSB(value) (BIT(value, 0)) |
| 442 | | #define LR(value) ((value << 1) | MSB(value)) |
| 443 | | #define RR(value) ((LSB(value) << 15) | (value >> 1)) |
| 444 | | |
| 445 | | switch (m_draw_mode & 0x07) |
| 446 | | { |
| 447 | | case 0: |
| 448 | | EAD += P; |
| 449 | | break; |
| 450 | | |
| 451 | | case 1: |
| 452 | | EAD += P; |
| 453 | | if (MSB(DAD)) EAD++; |
| 454 | | DAD = LR(DAD); |
| 455 | | break; |
| 456 | | |
| 457 | | case 2: |
| 458 | | if (MSB(DAD)) EAD++; |
| 459 | | DAD = LR(DAD); |
| 460 | | break; |
| 461 | | |
| 462 | | case 3: |
| 463 | | EAD -= P; |
| 464 | | if (MSB(DAD)) EAD++; |
| 465 | | DAD = LR(DAD); |
| 466 | | break; |
| 467 | | |
| 468 | | case 4: |
| 469 | | EAD -= P; |
| 470 | | break; |
| 471 | | |
| 472 | | case 5: |
| 473 | | EAD -= P; |
| 474 | | if (LSB(DAD)) EAD--; |
| 475 | | DAD = RR(DAD); |
| 476 | | break; |
| 477 | | |
| 478 | | case 6: |
| 479 | | if (LSB(DAD)) EAD--; |
| 480 | | DAD = RR(DAD); |
| 481 | | break; |
| 482 | | |
| 483 | | case 7: |
| 484 | | EAD += P; |
| 485 | | if (LSB(DAD)) EAD--; |
| 486 | | DAD = RR(DAD); |
| 487 | | break; |
| 488 | | } |
| 489 | | |
| 490 | | EAD &= 0x3ffff; |
| 491 | | } |
| 492 | | |
| 493 | | |
| 494 | | //------------------------------------------------- |
| 495 | 426 | // read_vram - |
| 496 | 427 | //------------------------------------------------- |
| 497 | 428 | |
| r32712 | r32713 | |
| 523 | 454 | } |
| 524 | 455 | |
| 525 | 456 | m_figs.m_dc--; |
| 526 | | advance_ead(); |
| 457 | m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); |
| 458 | m_ead &= 0x3ffff; |
| 527 | 459 | } |
| 528 | 460 | |
| 529 | 461 | if (m_figs.m_dc == 0) |
| r32712 | r32713 | |
| 601 | 533 | break; |
| 602 | 534 | } |
| 603 | 535 | |
| 604 | | advance_ead(); |
| 536 | m_ead += x_dir[m_figs.m_dir] + (y_dir[m_figs.m_dir] * m_pitch); |
| 537 | m_ead &= 0x3ffff; |
| 605 | 538 | } |
| 606 | 539 | } |
| 607 | 540 | |
| 608 | 541 | |
| 609 | 542 | //------------------------------------------------- |
| 610 | | // check_pattern - |
| 611 | | //------------------------------------------------- |
| 612 | | |
| 613 | | inline UINT16 upd7220_device::check_pattern(UINT16 pattern) |
| 614 | | { |
| 615 | | UINT16 res = 0; |
| 616 | | |
| 617 | | switch (m_bitmap_mod & 3) |
| 618 | | { |
| 619 | | case 0: res = pattern; break; //replace |
| 620 | | case 1: res = pattern; break; //complement |
| 621 | | case 2: res = 0; break; //reset to zero |
| 622 | | case 3: res |= 0xffff; break; //set to one |
| 623 | | } |
| 624 | | |
| 625 | | return res; |
| 626 | | } |
| 627 | | |
| 628 | | |
| 629 | | //------------------------------------------------- |
| 630 | 543 | // get_text_partition - |
| 631 | 544 | //------------------------------------------------- |
| 632 | 545 | |
| r32712 | r32713 | |
| 681 | 594 | m_fifo_ptr(-1), |
| 682 | 595 | m_fifo_dir(0), |
| 683 | 596 | m_mode(0), |
| 684 | | m_draw_mode(0), |
| 685 | 597 | m_de(0), |
| 686 | 598 | m_m(0), |
| 687 | 599 | m_aw(0), |
| r32712 | r32713 | |
| 846 | 758 | // draw_pixel - |
| 847 | 759 | //------------------------------------------------- |
| 848 | 760 | |
| 849 | | void upd7220_device::draw_pixel(int x, int y, UINT8 tile_data) |
| 761 | void upd7220_device::draw_pixel(int x, int y, int xi, UINT16 tile_data) |
| 850 | 762 | { |
| 851 | 763 | UINT32 addr = (y * m_pitch * 2 + (x >> 3)) & 0x3ffff; |
| 852 | | int dad = x & 0x7; |
| 853 | 764 | UINT8 data = readbyte(addr); |
| 854 | | UINT8 new_pixel = (tile_data) & (0x80 >> (dad)); |
| 765 | UINT8 new_pixel = (xi & 8 ? tile_data >> 8 : tile_data & 0xff) & (0x80 >> (xi & 7)); |
| 766 | new_pixel = new_pixel ? (0xff & (0x80 >> (x & 7))) : 0; |
| 855 | 767 | |
| 856 | 768 | switch(m_bitmap_mod) |
| 857 | 769 | { |
| 858 | 770 | case 0: //replace |
| 859 | | writebyte(addr, data & ~(0x80 >> (dad))); |
| 860 | | writebyte(addr, data | new_pixel); |
| 771 | writebyte(addr, (data & ~(0x80 >> (x & 7))) | new_pixel); |
| 861 | 772 | break; |
| 862 | 773 | case 1: //complement |
| 863 | | writebyte(addr, data ^ (new_pixel)); |
| 774 | writebyte(addr, data ^ new_pixel); |
| 864 | 775 | break; |
| 865 | 776 | case 2: //reset |
| 866 | | writebyte(addr, data & ((new_pixel) ? 0xff : ~(0x80 >> (dad)))); |
| 777 | writebyte(addr, data & ~new_pixel); |
| 867 | 778 | break; |
| 868 | 779 | case 3: //set |
| 869 | 780 | writebyte(addr, data | new_pixel); |
| r32712 | r32713 | |
| 883 | 794 | const int line_y_dir[8] = { 1, 0, 0,-1,-1, 0, 0, 1}; |
| 884 | 795 | const int line_x_step[8] = { 1, 0, 0, 1,-1, 0, 0,-1 }; |
| 885 | 796 | const int line_y_step[8] = { 0, 1,-1, 0, 0,-1, 1, 0 }; |
| 886 | | UINT16 line_pattern; |
| 797 | UINT16 pattern = (m_ra[8]) | (m_ra[9]<<8); |
| 887 | 798 | int line_step = 0; |
| 888 | | UINT8 dot; |
| 889 | 799 | |
| 890 | | line_size = m_figs.m_dc + 1; |
| 891 | | line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8)); |
| 800 | LOG(("uPD7220 line check: %d %d %02x %08x %d %d\n",x,y,m_figs.m_dir,m_ead,m_figs.m_d1,m_figs.m_dc)); |
| 892 | 801 | |
| 802 | line_size = m_figs.m_dc; |
| 803 | |
| 893 | 804 | for(i = 0;i<line_size;i++) |
| 894 | 805 | { |
| 895 | 806 | line_step = (m_figs.m_d1 * i); |
| 896 | | line_step/= (m_figs.m_dc + 1); |
| 897 | | line_step >>= 1; |
| 898 | | dot = ((line_pattern >> (i & 0xf)) & 1) << 7; |
| 899 | | draw_pixel(x + (line_step*line_x_step[m_figs.m_dir]),y + (line_step*line_y_step[m_figs.m_dir]),dot >> ((x + line_step*line_x_step[m_figs.m_dir]) & 0x7)); |
| 807 | line_step/= m_figs.m_dc; |
| 808 | ++line_step >>= 1; |
| 809 | draw_pixel(x + (line_step*line_x_step[m_figs.m_dir]),y + (line_step*line_y_step[m_figs.m_dir]),i,pattern); |
| 900 | 810 | x += line_x_dir[m_figs.m_dir]; |
| 901 | 811 | y += line_y_dir[m_figs.m_dir]; |
| 902 | 812 | } |
| r32712 | r32713 | |
| 909 | 819 | m_dad = x & 0x0f; |
| 910 | 820 | } |
| 911 | 821 | |
| 822 | //------------------------------------------------- |
| 823 | // draw_arc - |
| 824 | //------------------------------------------------- |
| 912 | 825 | |
| 826 | void upd7220_device::draw_arc(int x, int y) |
| 827 | { |
| 828 | int len, xi = m_figs.m_d + 1, yi = 0, err = -m_figs.m_d; |
| 829 | int x0, y0; |
| 830 | UINT16 pattern = (m_ra[8]) | (m_ra[9]<<8); |
| 831 | const int dot_dir[4] = {1, -1, -1, 1}; |
| 832 | |
| 833 | switch(m_figs.m_dir & 3) |
| 834 | { |
| 835 | case 1: |
| 836 | case 2: |
| 837 | x0 = x; |
| 838 | y0 = y + xi * dot_dir[m_figs.m_dir >> 1]; |
| 839 | break; |
| 840 | default: |
| 841 | x0 = x + xi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3]; |
| 842 | y0 = y; |
| 843 | break; |
| 844 | } |
| 845 | |
| 846 | LOG(("uPD7220 arc check: %d %d %02x %08x %d %d %d\n",x,y,m_figs.m_dir,m_ead,m_figs.m_dm,m_figs.m_dc,m_figs.m_d)); |
| 847 | |
| 848 | for(int i = 0; i < m_figs.m_dc; i++) |
| 849 | { |
| 850 | if(i >= m_figs.m_dm) |
| 851 | { |
| 852 | switch(m_figs.m_dir & 3) |
| 853 | { |
| 854 | case 1: |
| 855 | case 2: |
| 856 | draw_pixel(yi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + x0, xi * dot_dir[m_figs.m_dir >> 1] + y0, i, pattern); |
| 857 | break; |
| 858 | default: |
| 859 | draw_pixel(xi * dot_dir[m_figs.m_dir >> 1] + x0, yi * dot_dir[((m_figs.m_dir >> 1) + 3) & 3] + y0, i, pattern); |
| 860 | break; |
| 861 | } |
| 862 | } |
| 863 | yi++; |
| 864 | if(err < 0) |
| 865 | err += (yi + 1) << 1; |
| 866 | else |
| 867 | { |
| 868 | xi--; |
| 869 | err += (yi - xi + 1) << 1; |
| 870 | } |
| 871 | } |
| 872 | switch(m_figs.m_dir & 3) |
| 873 | { |
| 874 | case 1: |
| 875 | case 2: |
| 876 | x += m_figs.m_dc * dot_dir[((m_figs.m_dir >> 1) + 3) & 3]; |
| 877 | break; |
| 878 | default: |
| 879 | y += m_figs.m_dc * dot_dir[m_figs.m_dir >> 1]; |
| 880 | break; |
| 881 | } |
| 882 | |
| 883 | m_ead = (x >> 4) + (y * m_pitch); |
| 884 | m_dad = x & 0x0f; |
| 885 | } |
| 886 | |
| 913 | 887 | //------------------------------------------------- |
| 914 | 888 | // draw_rectangle - |
| 915 | 889 | //------------------------------------------------- |
| r32712 | r32713 | |
| 920 | 894 | const int rect_x_dir[8] = { 0, 1, 0,-1, 1, 1,-1,-1 }; |
| 921 | 895 | const int rect_y_dir[8] = { 1, 0,-1, 0, 1,-1,-1, 1 }; |
| 922 | 896 | UINT8 rect_type,rect_dir; |
| 923 | | UINT16 line_pattern; |
| 924 | | UINT8 dot; |
| 897 | UINT16 pattern = (m_ra[8]) | (m_ra[9]<<8); |
| 925 | 898 | |
| 926 | 899 | LOG(("uPD7220 rectangle check: %d %d %02x %08x\n",x,y,m_figs.m_dir,m_ead)); |
| 927 | 900 | |
| 928 | | line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8)); |
| 929 | 901 | rect_type = (m_figs.m_dir & 1) << 2; |
| 930 | 902 | rect_dir = rect_type | (((m_figs.m_dir >> 1) + 0) & 3); |
| 931 | 903 | |
| 932 | 904 | for(i = 0;i < m_figs.m_d;i++) |
| 933 | 905 | { |
| 934 | | dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7; |
| 935 | | draw_pixel(x,y,dot >> (x & 0x7)); |
| 906 | draw_pixel(x,y,i,pattern); |
| 936 | 907 | x+=rect_x_dir[rect_dir]; |
| 937 | 908 | y+=rect_y_dir[rect_dir]; |
| 938 | 909 | } |
| r32712 | r32713 | |
| 941 | 912 | |
| 942 | 913 | for(i = 0;i < m_figs.m_d2;i++) |
| 943 | 914 | { |
| 944 | | dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7; |
| 945 | | draw_pixel(x,y,dot >> (x & 0x7)); |
| 915 | draw_pixel(x,y,i,pattern); |
| 946 | 916 | x+=rect_x_dir[rect_dir]; |
| 947 | 917 | y+=rect_y_dir[rect_dir]; |
| 948 | 918 | } |
| r32712 | r32713 | |
| 951 | 921 | |
| 952 | 922 | for(i = 0;i < m_figs.m_d;i++) |
| 953 | 923 | { |
| 954 | | dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7; |
| 955 | | draw_pixel(x,y,dot >> (x & 0x7)); |
| 924 | draw_pixel(x,y,i,pattern); |
| 956 | 925 | x+=rect_x_dir[rect_dir]; |
| 957 | 926 | y+=rect_y_dir[rect_dir]; |
| 958 | 927 | } |
| r32712 | r32713 | |
| 961 | 930 | |
| 962 | 931 | for(i = 0;i < m_figs.m_d2;i++) |
| 963 | 932 | { |
| 964 | | dot = ((line_pattern >> ((i+m_dad) & 0xf)) & 1) << 7; |
| 965 | | draw_pixel(x,y,dot >> (x & 0x7)); |
| 933 | draw_pixel(x,y,i,pattern); |
| 966 | 934 | x+=rect_x_dir[rect_dir]; |
| 967 | 935 | y+=rect_y_dir[rect_dir]; |
| 968 | 936 | } |
| r32712 | r32713 | |
| 979 | 947 | |
| 980 | 948 | void upd7220_device::draw_char(int x, int y) |
| 981 | 949 | { |
| 982 | | int xi,yi; |
| 983 | | int xsize,ysize; |
| 984 | | UINT8 tile_data; |
| 950 | int isize,psize; |
| 951 | UINT16 tile_data = 0; |
| 985 | 952 | |
| 986 | | /* snippet for character checking */ |
| 987 | | #if 0 |
| 988 | | if((m_figs.m_dir & 7) == 3) |
| 989 | | for(yi=0;yi<8;yi++) |
| 990 | | { |
| 991 | | for(xi=0;xi<8;xi++) |
| 992 | | { |
| 993 | | printf("%d",(m_ra[(yi & 7) | 8] >> xi) & 1); |
| 994 | | } |
| 995 | | printf("\n"); |
| 996 | | } |
| 997 | | #endif |
| 953 | LOG(("uPD7220 char check: %d %d %02x %08x %d %d\n",x,y,m_figs.m_dir,m_ead,m_figs.m_d,m_figs.m_dc)); |
| 998 | 954 | |
| 999 | | xsize = m_figs.m_d & 0x3ff; |
| 955 | isize = m_figs.m_d & 0x3ff; |
| 1000 | 956 | /* Guess: D has presumably upper bits for ysize, QX-10 relies on this (TODO: check this on any real HW) */ |
| 1001 | | ysize = ((m_figs.m_d & 0x400) + m_figs.m_dc) + 1; |
| 957 | psize = ((m_figs.m_d & 0x400) + m_figs.m_dc) + 1; |
| 1002 | 958 | |
| 1003 | | /* TODO: internal direction, zooming, size stuff bigger than 8, rewrite using draw_pixel function */ |
| 1004 | | if((m_figs.m_dir & 7) == 0) |
| 1005 | | { |
| 1006 | | for(yi=0;yi<8;yi++) |
| 1007 | | { |
| 1008 | | for(xi=0;xi<8;xi++) |
| 1009 | | { |
| 1010 | | UINT8 dot = (m_ra[((7-xi) & 7) | 8]); |
| 1011 | | dot >>= yi; |
| 1012 | | dot &= 1; |
| 1013 | | dot*=0xff; |
| 1014 | | draw_pixel(x+xi,y+yi,dot); |
| 1015 | | } |
| 1016 | | } |
| 1017 | | } |
| 1018 | | else |
| 959 | for(int pi = 0; pi < psize; pi++) |
| 1019 | 960 | { |
| 1020 | | for(yi=0;yi<ysize;yi++) |
| 961 | tile_data = BITSWAP8(m_ra[((psize-1-pi) & 7) | 8],0,1,2,3,4,5,6,7); |
| 962 | tile_data = (tile_data << 8) | (tile_data & 0xff); |
| 963 | for(int pz = 0; pz <= m_gchr; pz++) |
| 1021 | 964 | { |
| 1022 | | switch(m_figs.m_dir & 7) |
| 965 | for(int ii = 0, curpixel = 0; ii < isize; ii++) |
| 1023 | 966 | { |
| 1024 | | case 2: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],0,1,2,3,4,5,6,7); break; |
| 1025 | | case 6: tile_data = BITSWAP8(m_ra[((ysize-1-yi) & 7) | 8],7,6,5,4,3,2,1,0); break; |
| 1026 | | default: tile_data = BITSWAP8(m_ra[((yi) & 7) | 8],7,6,5,4,3,2,1,0); |
| 1027 | | logerror("upd7220 draw char: %d %d %d\n",m_figs.m_dir,xsize,ysize); |
| 1028 | | break; |
| 967 | for(int iz = 0; iz <= m_gchr; iz++) |
| 968 | { |
| 969 | draw_pixel(x + (curpixel * x_dir[m_figs.m_dir]), y + (curpixel * y_dir[m_figs.m_dir]), ii, tile_data); |
| 970 | curpixel++; |
| 971 | } |
| 1029 | 972 | } |
| 1030 | | |
| 1031 | | for(xi=0;xi<xsize;xi++) |
| 1032 | | { |
| 1033 | | UINT32 addr = ((y+yi) * m_pitch * 2) + ((x+xi) >> 3); |
| 1034 | | |
| 1035 | | writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) & ~(1 << (xi & 7))); |
| 1036 | | writebyte(addr & 0x3ffff, readbyte(addr & 0x3ffff) | ((tile_data) & (1 << (xi & 7)))); |
| 1037 | | } |
| 973 | x += x_dir[(m_figs.m_dir + 2) & 7]; |
| 974 | y += y_dir[(m_figs.m_dir + 2) & 7]; |
| 1038 | 975 | } |
| 1039 | 976 | } |
| 1040 | | m_ead = ((x+8*x_dir_dot[m_figs.m_dir]) >> 4) + ((y+8*y_dir_dot[m_figs.m_dir]) * m_pitch); |
| 1041 | | m_dad = ((x+8*x_dir_dot[m_figs.m_dir]) & 0xf); |
| 977 | |
| 978 | m_ead = (x >> 4) + (y * m_pitch); |
| 979 | m_dad = (x & 0xf); |
| 1042 | 980 | } |
| 1043 | 981 | |
| 1044 | 982 | |
| r32712 | r32713 | |
| 1359 | 1297 | break; |
| 1360 | 1298 | |
| 1361 | 1299 | case COMMAND_FIGD: /* figure draw start */ |
| 1362 | | if(m_figs.m_figure_type == 0 || m_figs.m_figure_type == 4) |
| 1363 | | { |
| 1364 | | UINT16 line_pattern = check_pattern((m_ra[8]) | (m_ra[9]<<8)); |
| 1365 | | UINT8 dot = ((line_pattern >> (0 & 0xf)) & 1) << 7; |
| 1366 | | |
| 1367 | | draw_pixel(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch),dot); |
| 1368 | | } |
| 1300 | if(m_figs.m_figure_type == 0) |
| 1301 | draw_pixel(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch),m_dad,(m_ra[8]) | (m_ra[9]<<8)); |
| 1369 | 1302 | else if(m_figs.m_figure_type == 1) |
| 1370 | 1303 | draw_line(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch)); |
| 1304 | else if(m_figs.m_figure_type == 4) |
| 1305 | draw_arc(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch)); |
| 1371 | 1306 | else if(m_figs.m_figure_type == 8) |
| 1372 | 1307 | draw_rectangle(((m_ead % m_pitch) << 4) | (m_dad & 0xf),(m_ead / m_pitch)); |
| 1373 | 1308 | else |