trunk/src/emu/video/pc_vga.c
r17493 | r17494 | |
186 | 186 | bool ext_reg_ena; |
187 | 187 | }et4k; |
188 | 188 | |
| 189 | enum |
| 190 | { |
| 191 | S3_IDLE = 0, |
| 192 | S3_DRAWING_RECT, |
| 193 | S3_DRAWING_LINE, |
| 194 | S3_DRAWING_BITBLT |
| 195 | }; |
| 196 | |
189 | 197 | static struct |
190 | 198 | { |
191 | 199 | UINT8 memory_config; |
r17493 | r17494 | |
206 | 214 | UINT32 fgcolour; |
207 | 215 | UINT32 bgcolour; |
208 | 216 | UINT32 pixel_xfer; |
| 217 | UINT16 wait_rect_x; |
| 218 | UINT16 wait_rect_y; |
| 219 | UINT8 bus_size; |
209 | 220 | UINT8 multifunc_sel; |
| 221 | bool gpbusy; |
| 222 | int state; |
210 | 223 | }s3; |
211 | 224 | |
212 | 225 | #define CRTC_PORT_ADDR ((vga.miscellaneous_output&1)?0x3d0:0x3b0) |
r17493 | r17494 | |
2579 | 2592 | break; |
2580 | 2593 | case 0x40: |
2581 | 2594 | s3.enable_8514 = data & 0x01; // enable 8514/A registers (x2e8, x6e8, xae8, xee8) |
| 2595 | if(data & 0x01) |
| 2596 | s3.state = S3_IDLE; |
2582 | 2597 | break; |
2583 | 2598 | case 0x51: |
2584 | 2599 | vga.crtc.start_addr &= ~0xc0000; |
r17493 | r17494 | |
2726 | 2741 | */ |
2727 | 2742 | READ16_HANDLER(s3_gpstatus_r) |
2728 | 2743 | { |
| 2744 | UINT16 ret = 0x0000; |
| 2745 | |
2729 | 2746 | logerror("S3: 9AE8 read\n"); |
2730 | 2747 | if(s3.enable_8514 != 0) |
2731 | | return 0; |
| 2748 | { |
| 2749 | if(s3.gpbusy == true) |
| 2750 | ret |= 0x0200; |
| 2751 | return ret; |
| 2752 | } |
2732 | 2753 | else |
2733 | 2754 | return 0xffff; |
2734 | 2755 | } |
r17493 | r17494 | |
2818 | 2839 | */ |
2819 | 2840 | WRITE16_HANDLER(s3_cmd_w) |
2820 | 2841 | { |
2821 | | /* really needs to be 16-bit... */ |
2822 | 2842 | if(s3.enable_8514 != 0) |
2823 | 2843 | { |
2824 | 2844 | int x,y; |
r17493 | r17494 | |
2828 | 2848 | switch(data & 0xe000) |
2829 | 2849 | { |
2830 | 2850 | case 0x0000: // NOP (for "Short Stroke Vectors") |
| 2851 | s3.gpbusy = false; |
2831 | 2852 | logerror("S3: Command (%04x) - NOP\n",s3.current_cmd); |
2832 | 2853 | break; |
2833 | 2854 | case 0x2000: // Line |
| 2855 | s3.gpbusy = false; |
2834 | 2856 | logerror("S3: Command (%04x) - Line\n",s3.current_cmd); |
2835 | 2857 | break; |
2836 | 2858 | case 0x4000: // Rectangle Fill |
2837 | | // TODO: handle wait-per-pixel drawing |
| 2859 | if(data & 0x0100) // WAIT (for read/write of PIXEL TRANSFER (E2E8)) |
| 2860 | { |
| 2861 | s3.state = S3_DRAWING_RECT; |
| 2862 | s3.gpbusy = true; |
| 2863 | s3.wait_rect_x = s3.curr_x; |
| 2864 | s3.wait_rect_y = s3.curr_y; |
| 2865 | s3.bus_size = (data & 0x0600) >> 9; |
| 2866 | break; |
| 2867 | } |
2838 | 2868 | offset = VGA_START_ADDRESS; |
2839 | 2869 | offset += (VGA_LINE_LENGTH * s3.curr_y); |
2840 | 2870 | offset += s3.curr_x; |
2841 | | if(s3.current_cmd & 0x0010) // INC_X (rectangle horizontal direction) |
2842 | | dir_x = 2; |
2843 | | else |
2844 | | dir_x = -2; |
2845 | | for(y=0;y<s3.rect_height;y++) |
| 2871 | dir_x = 2; |
| 2872 | for(y=0;y<=s3.rect_height;y++) |
2846 | 2873 | { |
2847 | | for(x=0;x<s3.rect_width;x+=dir_x) |
| 2874 | for(x=0;x<=s3.rect_width;x+=dir_x) |
2848 | 2875 | { |
2849 | 2876 | vga.memory[(offset+x) % vga.svga_intf.vram_size] = s3.fgcolour & 0x000000ff; // TODO: handle 16-bit or 32-bit transfers |
2850 | 2877 | vga.memory[(offset+x+1) % vga.svga_intf.vram_size] = (s3.fgcolour & 0x0000ff00) >> 8; |
2851 | 2878 | } |
2852 | | if(s3.current_cmd & 0x0040) // INC_Y (rectangle vertical direction) |
2853 | | offset += VGA_LINE_LENGTH; |
2854 | | else |
2855 | | offset -= VGA_LINE_LENGTH; |
| 2879 | offset += VGA_LINE_LENGTH; |
2856 | 2880 | } |
2857 | 2881 | logerror("S3: Command (%04x) - Rectangle Fill %i,%i Width: %i Height: %i Colour: %08x\n",s3.current_cmd,s3.curr_x,s3.curr_y,s3.rect_width,s3.rect_height,s3.fgcolour); |
2858 | 2882 | break; |
2859 | 2883 | case 0xc000: // BitBLT |
| 2884 | s3.gpbusy = false; |
2860 | 2885 | logerror("S3: Command (%04x) - BitBLT\n",s3.current_cmd); |
2861 | 2886 | break; |
2862 | 2887 | case 0xe000: // Pattern Fill |
| 2888 | s3.gpbusy = false; |
2863 | 2889 | logerror("S3: Command (%04x) - Pattern Fill\n",s3.current_cmd); |
2864 | 2890 | break; |
2865 | 2891 | default: |
| 2892 | s3.gpbusy = false; |
2866 | 2893 | logerror("S3: Unknown command: %04x\n",data); |
2867 | 2894 | } |
2868 | 2895 | } |
r17493 | r17494 | |
3043 | 3070 | |
3044 | 3071 | WRITE16_HANDLER(s3_pixel_xfer_w) |
3045 | 3072 | { |
| 3073 | int x,data_size; |
| 3074 | UINT32 off,xfer = 0; |
| 3075 | |
3046 | 3076 | if(offset == 1) |
3047 | 3077 | s3.pixel_xfer = (s3.pixel_xfer & 0x0000ffff) | (data << 16); |
3048 | 3078 | else |
3049 | 3079 | s3.pixel_xfer = (s3.pixel_xfer & 0xffff0000) | data; |
| 3080 | |
| 3081 | if(s3.state == S3_DRAWING_RECT) |
| 3082 | { |
| 3083 | // the data in the pixel transfer register masks the rectangle output(?) |
| 3084 | if(s3.bus_size == 0) // 8-bit |
| 3085 | data_size = 8; |
| 3086 | if(s3.bus_size == 1) // 16-bit |
| 3087 | data_size = 16; |
| 3088 | if(s3.bus_size == 2) // 32-bit |
| 3089 | data_size = 32; |
| 3090 | off = VGA_START_ADDRESS; |
| 3091 | off += (VGA_LINE_LENGTH * s3.wait_rect_y); |
| 3092 | off += s3.wait_rect_x; |
| 3093 | for(x=0;x<data_size;x++) |
| 3094 | { |
| 3095 | if(s3.current_cmd & 0x1000) |
| 3096 | { |
| 3097 | xfer = ((s3.pixel_xfer & 0x000000ff) << 8) | ((s3.pixel_xfer & 0x0000ff00) >> 8) |
| 3098 | | ((s3.pixel_xfer & 0x00ff0000) << 8) | ((s3.pixel_xfer & 0xff000000) >> 8); |
| 3099 | } |
| 3100 | else |
| 3101 | xfer = s3.pixel_xfer; |
| 3102 | if((xfer & ((1<<(data_size-1))>>x)) != 0) |
| 3103 | vga.memory[off] = s3.fgcolour & 0x00ff; |
| 3104 | off++; |
| 3105 | s3.wait_rect_x++; |
| 3106 | if(s3.wait_rect_x > s3.curr_x + s3.rect_width) |
| 3107 | { |
| 3108 | s3.wait_rect_x = s3.curr_x; |
| 3109 | s3.wait_rect_y++; |
| 3110 | if(s3.wait_rect_y > s3.curr_y + s3.rect_height) |
| 3111 | { |
| 3112 | s3.state = S3_IDLE; |
| 3113 | s3.gpbusy = false; |
| 3114 | } |
| 3115 | } |
| 3116 | } |
| 3117 | } |
| 3118 | |
| 3119 | logerror("S3: Pixel Transfer = %08x\n",s3.pixel_xfer); |
3050 | 3120 | } |
3051 | 3121 | |
3052 | 3122 | READ8_HANDLER( s3_mem_r ) |