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 |