trunk/src/emu/video/pc_vga.c
r17589 | r17590 | |
203 | 203 | UINT8 reg_lock1; |
204 | 204 | UINT8 reg_lock2; |
205 | 205 | UINT8 enable_8514; |
| 206 | UINT8 cr53; |
206 | 207 | UINT16 current_cmd; |
207 | 208 | INT16 dest_x; |
208 | 209 | INT16 dest_y; |
209 | 210 | INT16 curr_x; |
210 | 211 | INT16 curr_y; |
| 212 | INT16 prev_x; |
| 213 | INT16 prev_y; |
| 214 | UINT16 src_x; |
| 215 | UINT16 src_y; |
211 | 216 | UINT16 line_axial_step; |
212 | 217 | UINT16 line_diagonal_step; |
| 218 | UINT16 line_errorterm; |
213 | 219 | UINT16 rect_width; |
214 | 220 | UINT16 rect_height; |
215 | 221 | UINT32 fgcolour; |
r17589 | r17590 | |
217 | 223 | UINT16 fgmix; |
218 | 224 | UINT16 bgmix; |
219 | 225 | UINT32 pixel_xfer; |
220 | | INT16 wait_rect_x; |
221 | | INT16 wait_rect_y; |
222 | 226 | INT16 scissors_left; |
223 | 227 | INT16 scissors_right; |
224 | 228 | INT16 scissors_top; |
225 | 229 | INT16 scissors_bottom; |
| 230 | UINT16 pixel_control; |
226 | 231 | UINT8 bus_size; |
227 | 232 | UINT8 multifunc_sel; |
228 | 233 | UINT8 write_count; |
| 234 | |
| 235 | // data for memory-mapped I/O |
| 236 | UINT16 mmio_9ae8; |
| 237 | UINT16 mmio_bee8; |
| 238 | |
229 | 239 | bool gpbusy; |
230 | 240 | int state; |
231 | 241 | }s3; |
r17589 | r17590 | |
2611 | 2621 | vga.crtc.start_addr &= ~0xc0000; |
2612 | 2622 | vga.crtc.start_addr |= ((data & 0x3) << 18); |
2613 | 2623 | break; |
| 2624 | case 0x53: |
| 2625 | s3.cr53 = data; |
| 2626 | break; |
2614 | 2627 | case 0x67: |
2615 | 2628 | s3.ext_misc_ctrl_2 = data; |
2616 | 2629 | s3_define_video_mode(); |
r17589 | r17590 | |
2624 | 2637 | fatalerror("TODO: s3 bank selects above 1M"); |
2625 | 2638 | break; |
2626 | 2639 | default: |
2627 | | //printf("%02x %02x\n",index,data); |
| 2640 | logerror("S3: 3D4 index %02x write %02x\n",index,data); |
2628 | 2641 | break; |
2629 | 2642 | } |
2630 | 2643 | } |
r17589 | r17590 | |
2737 | 2750 | UINT8 dst = vga.memory[offset]; |
2738 | 2751 | UINT8 src = 0; |
2739 | 2752 | |
| 2753 | // check clipping rectangle |
| 2754 | if(s3.curr_x < s3.scissors_left || s3.curr_x > s3.scissors_right || s3.curr_y < s3.scissors_top || s3.curr_y > s3.scissors_bottom) |
| 2755 | return; // do nothing |
| 2756 | |
2740 | 2757 | // determine source |
2741 | 2758 | switch(s3.fgmix & 0x0060) |
2742 | 2759 | { |
r17589 | r17590 | |
2750 | 2767 | src = s3.pixel_xfer; |
2751 | 2768 | break; |
2752 | 2769 | case 0x0060: |
2753 | | // TODO: Bitmap data; |
| 2770 | // video memory - presume the memory is sourced from the current X/Y co-ords |
| 2771 | src = vga.memory[(VGA_START_ADDRESS + (s3.curr_y * VGA_LINE_LENGTH) + s3.curr_x) % vga.svga_intf.vram_size]; |
2754 | 2772 | break; |
2755 | 2773 | } |
2756 | 2774 | |
r17589 | r17590 | |
2761 | 2779 | vga.memory[offset] = ~dst; |
2762 | 2780 | break; |
2763 | 2781 | case 0x0001: |
2764 | | vga.memory[offset] = 0x00; // is this correct? |
| 2782 | vga.memory[offset] = 0x00; |
2765 | 2783 | break; |
2766 | 2784 | case 0x0002: |
2767 | | vga.memory[offset] = 0xff; // is this correct? |
| 2785 | vga.memory[offset] = 0xff; |
2768 | 2786 | break; |
2769 | 2787 | case 0x0003: |
2770 | 2788 | // change nothing, pixel is unchanged |
r17589 | r17590 | |
2812 | 2830 | { |
2813 | 2831 | UINT8 dst = vga.memory[offset]; |
2814 | 2832 | UINT8 src = 0; |
| 2833 | |
| 2834 | // check clipping rectangle |
| 2835 | if(s3.curr_x < s3.scissors_left || s3.curr_x > s3.scissors_right || s3.curr_y < s3.scissors_top || s3.curr_y > s3.scissors_bottom) |
| 2836 | return; // do nothing |
| 2837 | |
2815 | 2838 | // determine source |
2816 | 2839 | switch(s3.bgmix & 0x0060) |
2817 | 2840 | { |
r17589 | r17590 | |
2825 | 2848 | src = s3.pixel_xfer; |
2826 | 2849 | break; |
2827 | 2850 | case 0x0060: |
2828 | | // TODO: Bitmap data; |
| 2851 | // video memory - presume the memory is sourced from the current X/Y co-ords |
| 2852 | src = vga.memory[(VGA_START_ADDRESS + (s3.curr_y * VGA_LINE_LENGTH) + s3.curr_x) % vga.svga_intf.vram_size]; |
2829 | 2853 | break; |
2830 | 2854 | } |
2831 | 2855 | |
r17589 | r17590 | |
2836 | 2860 | vga.memory[offset] = ~dst; |
2837 | 2861 | break; |
2838 | 2862 | case 0x0001: |
2839 | | vga.memory[offset] = 0x00; // is this correct? |
| 2863 | vga.memory[offset] = 0x00; |
2840 | 2864 | break; |
2841 | 2865 | case 0x0002: |
2842 | | vga.memory[offset] = 0xff; // is this correct? |
| 2866 | vga.memory[offset] = 0xff; |
2843 | 2867 | break; |
2844 | 2868 | case 0x0003: |
2845 | 2869 | // change nothing, pixel is unchanged |
r17589 | r17590 | |
2882 | 2906 | break; |
2883 | 2907 | } |
2884 | 2908 | } |
| 2909 | |
| 2910 | void s3_write(UINT32 offset, UINT32 src) |
| 2911 | { |
| 2912 | int data_size = 8; |
| 2913 | UINT32 xfer = 0; |
| 2914 | |
| 2915 | switch(s3.pixel_control & 0x00c0) |
| 2916 | { |
| 2917 | case 0x0000: // Foreground Mix only |
| 2918 | // check clipping rectangle |
| 2919 | if(s3.curr_x < s3.scissors_left || s3.curr_x > s3.scissors_right || s3.curr_y < s3.scissors_top || s3.curr_y > s3.scissors_bottom) |
| 2920 | return; // do nothing |
| 2921 | s3_write_fg(offset); |
| 2922 | break; |
| 2923 | case 0x0040: // fixed pattern (?) |
| 2924 | // TODO |
| 2925 | break; |
| 2926 | case 0x0080: // use pixel transfer register |
| 2927 | if(s3.bus_size == 0) // 8-bit |
| 2928 | data_size = 8; |
| 2929 | if(s3.bus_size == 1) // 16-bit |
| 2930 | data_size = 16; |
| 2931 | if(s3.bus_size == 2) // 32-bit |
| 2932 | data_size = 32; |
| 2933 | if((s3.current_cmd & 0x1000) && (data_size != 8)) |
| 2934 | { |
| 2935 | xfer = ((s3.pixel_xfer & 0x000000ff) << 8) | ((s3.pixel_xfer & 0x0000ff00) >> 8) |
| 2936 | | ((s3.pixel_xfer & 0x00ff0000) << 8) | ((s3.pixel_xfer & 0xff000000) >> 8); |
| 2937 | } |
| 2938 | else |
| 2939 | xfer = s3.pixel_xfer; |
| 2940 | if(s3.current_cmd & 0x0002) |
| 2941 | { |
| 2942 | if((xfer & ((1<<(data_size-1))>>s3.src_x)) != 0) |
| 2943 | s3_write_fg(offset); |
| 2944 | else |
| 2945 | s3_write_bg(offset); |
| 2946 | } |
| 2947 | else |
| 2948 | { |
| 2949 | s3_write_fg(offset); |
| 2950 | } |
| 2951 | s3.src_x++; |
| 2952 | if(s3.src_x >= data_size) |
| 2953 | s3.src_x = 0; |
| 2954 | break; |
| 2955 | case 0x00c0: // use source plane |
| 2956 | if(vga.memory[(src) % vga.svga_intf.vram_size] != 0x00) |
| 2957 | s3_write_fg(offset); |
| 2958 | else |
| 2959 | s3_write_bg(offset); |
| 2960 | break; |
| 2961 | } |
| 2962 | } |
| 2963 | |
2885 | 2964 | /* |
| 2965 | 92E8h W(R/W): Line Error Term Read/Write Register (ERR_TERM). |
| 2966 | bit 0-12 (911/924) LINE PARAMETER/ERROR TERM. For Line Drawing this is the |
| 2967 | Bresenham Initial Error Term 2*dminor-dmajor (one less if the |
| 2968 | starting X is less than the ending X) in two's complement format. |
| 2969 | (dminor is the length of the line projected onto the minor or |
| 2970 | dependent axis, dmajor is the length of the line projected onto |
| 2971 | the major or independent axis). |
| 2972 | 0-13 (80x +) LINE PARAMETER/ERROR TERM. See above. |
| 2973 | */ |
| 2974 | READ16_HANDLER(s3_line_error_r) |
| 2975 | { |
| 2976 | return s3.line_errorterm; |
| 2977 | } |
| 2978 | |
| 2979 | WRITE16_HANDLER(s3_line_error_w) |
| 2980 | { |
| 2981 | s3.line_errorterm = data & 0x3fff; |
| 2982 | logerror("S3: Line Parameter/Error Term write %04x\n",data); |
| 2983 | } |
| 2984 | |
| 2985 | /* |
2886 | 2986 | 9AE8h W(R): Graphics Processor Status Register (GP_STAT) |
2887 | 2987 | bit 0-7 Queue State. |
2888 | 2988 | 00h = 8 words available - queue is empty |
r17589 | r17590 | |
3010 | 3110 | UINT32 offset,src; |
3011 | 3111 | |
3012 | 3112 | s3.current_cmd = data; |
| 3113 | s3.src_x = 0; |
| 3114 | s3.src_y = 0; |
3013 | 3115 | switch(data & 0xe000) |
3014 | 3116 | { |
3015 | 3117 | case 0x0000: // NOP (for "Short Stroke Vectors") |
r17589 | r17590 | |
3027 | 3129 | { |
3028 | 3130 | s3.state = S3_DRAWING_RECT; |
3029 | 3131 | //s3.gpbusy = true; // DirectX 5 keeps waiting for the busy bit to be clear... |
3030 | | s3.wait_rect_x = s3.curr_x; |
3031 | | s3.wait_rect_y = s3.curr_y; |
3032 | 3132 | s3.bus_size = (data & 0x0600) >> 9; |
3033 | 3133 | logerror("S3: Command (%04x) - Rectangle Fill (WAIT) %i,%i Width: %i Height: %i Colour: %08x\n",s3.current_cmd,s3.curr_x, |
3034 | 3134 | s3.curr_y,s3.rect_width,s3.rect_height,s3.fgcolour); |
r17589 | r17590 | |
3041 | 3141 | { |
3042 | 3142 | for(x=0;x<=s3.rect_width;x++) |
3043 | 3143 | { |
3044 | | if(data & 0x0020) |
3045 | | s3_write_fg((offset+x) % vga.svga_intf.vram_size); |
| 3144 | if(data & 0x0020) // source pattern is always based on current X/Y? |
| 3145 | s3_write((offset+x) % vga.svga_intf.vram_size,(offset+x) % vga.svga_intf.vram_size); |
3046 | 3146 | else |
3047 | | s3_write_fg((offset-x) % vga.svga_intf.vram_size); |
| 3147 | s3_write((offset-x) % vga.svga_intf.vram_size,(offset-x) % vga.svga_intf.vram_size); |
| 3148 | if(s3.current_cmd & 0x0020) |
| 3149 | { |
| 3150 | s3.curr_x++; |
| 3151 | if(s3.curr_x > s3.prev_x + s3.rect_width) |
| 3152 | { |
| 3153 | s3.curr_x = s3.prev_x; |
| 3154 | s3.src_x = 0; |
| 3155 | if(s3.current_cmd & 0x0080) |
| 3156 | s3.curr_y++; |
| 3157 | else |
| 3158 | s3.curr_y--; |
| 3159 | } |
| 3160 | } |
| 3161 | else |
| 3162 | { |
| 3163 | s3.curr_x--; |
| 3164 | if(s3.curr_x < s3.prev_x - s3.rect_width) |
| 3165 | { |
| 3166 | s3.curr_x = s3.prev_x; |
| 3167 | s3.src_x = 0; |
| 3168 | if(s3.current_cmd & 0x0080) |
| 3169 | s3.curr_y++; |
| 3170 | else |
| 3171 | s3.curr_y--; |
| 3172 | } |
| 3173 | } |
3048 | 3174 | } |
3049 | 3175 | if(data & 0x0080) |
3050 | 3176 | offset += VGA_LINE_LENGTH; |
r17589 | r17590 | |
3071 | 3197 | vga.memory[(offset+x) % vga.svga_intf.vram_size] = vga.memory[(src+x) % vga.svga_intf.vram_size]; |
3072 | 3198 | else |
3073 | 3199 | vga.memory[(offset-x) % vga.svga_intf.vram_size] = vga.memory[(src-x) % vga.svga_intf.vram_size]; |
| 3200 | if(s3.current_cmd & 0x0020) |
| 3201 | { |
| 3202 | s3.curr_x++; |
| 3203 | if(s3.curr_x > s3.prev_x + s3.rect_width) |
| 3204 | { |
| 3205 | s3.curr_x = s3.prev_x; |
| 3206 | s3.src_x = 0; |
| 3207 | if(s3.current_cmd & 0x0080) |
| 3208 | s3.curr_y++; |
| 3209 | else |
| 3210 | s3.curr_y--; |
| 3211 | } |
| 3212 | } |
| 3213 | else |
| 3214 | { |
| 3215 | s3.curr_x--; |
| 3216 | if(s3.curr_x < s3.prev_x - s3.rect_width) |
| 3217 | { |
| 3218 | s3.curr_x = s3.prev_x; |
| 3219 | s3.src_x = 0; |
| 3220 | if(s3.current_cmd & 0x0080) |
| 3221 | s3.curr_y++; |
| 3222 | else |
| 3223 | s3.curr_y--; |
| 3224 | } |
| 3225 | } |
3074 | 3226 | } |
3075 | 3227 | if(data & 0x0080) |
3076 | 3228 | { |
r17589 | r17590 | |
3110 | 3262 | { |
3111 | 3263 | if(data & 0x0020) |
3112 | 3264 | { |
3113 | | if(vga.memory[(src+pattern_x) % vga.svga_intf.vram_size] == 0x00) |
3114 | | s3_write_fg(offset+x); |
3115 | | else |
3116 | | s3_write_bg(offset+x); |
| 3265 | s3_write(offset+x,src+pattern_x); |
3117 | 3266 | pattern_x++; |
3118 | 3267 | if(pattern_x >= 8) |
3119 | 3268 | pattern_x = 0; |
3120 | 3269 | } |
3121 | 3270 | else |
3122 | 3271 | { |
3123 | | if(vga.memory[(src-pattern_x) % vga.svga_intf.vram_size] == 0x00) |
3124 | | s3_write_fg(offset-x); |
3125 | | else |
3126 | | s3_write_bg(offset-x); |
| 3272 | s3_write(offset-x,src-pattern_x); |
3127 | 3273 | pattern_x--; |
3128 | 3274 | if(pattern_x < 0) |
3129 | 3275 | pattern_x = 7; |
r17589 | r17590 | |
3250 | 3396 | WRITE16_HANDLER(s3_currentx_w) |
3251 | 3397 | { |
3252 | 3398 | s3.curr_x = data; |
| 3399 | s3.prev_x = data; |
3253 | 3400 | logerror("S3: Current X set to %04x (%i)\n",data,s3.curr_x); |
3254 | 3401 | } |
3255 | 3402 | |
r17589 | r17590 | |
3261 | 3408 | WRITE16_HANDLER(s3_currenty_w) |
3262 | 3409 | { |
3263 | 3410 | s3.curr_y = data; |
| 3411 | s3.prev_y = data; |
3264 | 3412 | logerror("S3: Current Y set to %04x (%i)\n",data,s3.curr_y); |
3265 | 3413 | } |
3266 | 3414 | |
r17589 | r17590 | |
3359 | 3507 | logerror("S3: Scissors Right write %04x\n",data); |
3360 | 3508 | break; |
3361 | 3509 | /* |
| 3510 | BEE8h index 0Ah W(R/W): Pixel Control Register (PIX_CNTL). |
| 3511 | BIT 2 (911-928) Pack Data. If set image read data is a monochrome bitmap, |
| 3512 | if clear it is a bitmap of the current pixel depth |
| 3513 | 6-7 DT-EX-DRC. Select Mix Select. |
| 3514 | 0 Foreground Mix is always used. |
| 3515 | 1 use fixed pattern to decide which mix setting to use on a pixel |
| 3516 | 2 CPU Data (Pixel Transfer register) determines the Mix register used. |
| 3517 | 3 Video memory determines the Mix register used. |
| 3518 | */ |
| 3519 | case 0xa000: |
| 3520 | s3.pixel_control = data; |
| 3521 | logerror("S3: Pixel control write %04x\n",data); |
| 3522 | break; |
| 3523 | /* |
3362 | 3524 | BEE8h index 0Fh W(W): Read Register Select Register (READ_SEL) (801/5,928) |
3363 | 3525 | bit 0-2 (911-928) READ-REG-SEL. Read Register Select. Selects the register |
3364 | 3526 | that is actually read when a read of BEE8h happens. Each read of |
r17589 | r17590 | |
3385 | 3547 | |
3386 | 3548 | static void s3_wait_draw() |
3387 | 3549 | { |
3388 | | int x,data_size = 0; |
3389 | | UINT32 off,xfer = 0; |
| 3550 | int x, data_size = 8; |
| 3551 | UINT32 off; |
3390 | 3552 | |
3391 | 3553 | // the data in the pixel transfer register or written to VRAM masks the rectangle output |
3392 | 3554 | if(s3.bus_size == 0) // 8-bit |
r17589 | r17590 | |
3396 | 3558 | if(s3.bus_size == 2) // 32-bit |
3397 | 3559 | data_size = 32; |
3398 | 3560 | off = VGA_START_ADDRESS; |
3399 | | off += (VGA_LINE_LENGTH * s3.wait_rect_y); |
3400 | | off += s3.wait_rect_x; |
3401 | | for(x=0;x<data_size;x++) |
| 3561 | off += (VGA_LINE_LENGTH * s3.curr_y); |
| 3562 | off += s3.curr_x; |
| 3563 | if(s3.current_cmd & 0x02) // "across plane mode" |
3402 | 3564 | { |
3403 | | if(s3.wait_rect_x >= 0 && s3.wait_rect_y >= 0) |
| 3565 | for(x=0;x<data_size;x++) |
3404 | 3566 | { |
3405 | | // check clipping rectangle |
3406 | | if(s3.wait_rect_x >= s3.scissors_left && s3.wait_rect_x <= s3.scissors_right && s3.wait_rect_y >= s3.scissors_top && s3.wait_rect_y <= s3.scissors_bottom) |
| 3567 | s3_write(off % vga.svga_intf.vram_size,off % vga.svga_intf.vram_size); |
| 3568 | if(s3.current_cmd & 0x0020) |
3407 | 3569 | { |
3408 | | if((s3.current_cmd & 0x1000) && (data_size != 8)) |
| 3570 | off++; |
| 3571 | s3.curr_x++; |
| 3572 | if(s3.curr_x > s3.prev_x + s3.rect_width) |
3409 | 3573 | { |
3410 | | xfer = ((s3.pixel_xfer & 0x000000ff) << 8) | ((s3.pixel_xfer & 0x0000ff00) >> 8) |
3411 | | | ((s3.pixel_xfer & 0x00ff0000) << 8) | ((s3.pixel_xfer & 0xff000000) >> 8); |
| 3574 | s3.curr_x = s3.prev_x; |
| 3575 | s3.src_x = 0; |
| 3576 | if(s3.current_cmd & 0x0080) |
| 3577 | { |
| 3578 | s3.curr_y++; |
| 3579 | if(s3.curr_y > s3.prev_y + s3.rect_height) |
| 3580 | { |
| 3581 | s3.state = S3_IDLE; |
| 3582 | s3.gpbusy = false; |
| 3583 | } |
| 3584 | } |
| 3585 | else |
| 3586 | { |
| 3587 | s3.curr_y--; |
| 3588 | if(s3.curr_y < s3.prev_y - s3.rect_height) |
| 3589 | { |
| 3590 | s3.state = S3_IDLE; |
| 3591 | s3.gpbusy = false; |
| 3592 | } |
| 3593 | } |
| 3594 | return; |
3412 | 3595 | } |
3413 | | else |
3414 | | xfer = s3.pixel_xfer; |
3415 | | if((xfer & ((1<<(data_size-1))>>x)) != 0) |
3416 | | s3_write_fg(off % vga.svga_intf.vram_size); |
3417 | | else |
3418 | | s3_write_bg(off % vga.svga_intf.vram_size); |
3419 | 3596 | } |
3420 | | } |
3421 | | if(s3.current_cmd & 0x0020) |
3422 | | { |
3423 | | off++; |
3424 | | s3.wait_rect_x++; |
3425 | | if(s3.wait_rect_x > s3.curr_x + s3.rect_width) |
| 3597 | else |
3426 | 3598 | { |
3427 | | s3.wait_rect_x = s3.curr_x; |
3428 | | if(s3.current_cmd & 0x0080) |
| 3599 | off--; |
| 3600 | s3.curr_x--; |
| 3601 | if(s3.curr_x < s3.prev_x - s3.rect_width) |
3429 | 3602 | { |
3430 | | s3.wait_rect_y++; |
3431 | | if(s3.wait_rect_y > s3.curr_y + s3.rect_height) |
| 3603 | s3.curr_x = s3.prev_x; |
| 3604 | s3.src_x = 0; |
| 3605 | if(s3.current_cmd & 0x0080) |
3432 | 3606 | { |
3433 | | s3.state = S3_IDLE; |
3434 | | s3.gpbusy = false; |
| 3607 | s3.curr_y++; |
| 3608 | if(s3.curr_y > s3.prev_y + s3.rect_height) |
| 3609 | { |
| 3610 | s3.state = S3_IDLE; |
| 3611 | s3.gpbusy = false; |
| 3612 | } |
3435 | 3613 | } |
3436 | | } |
3437 | | else |
3438 | | { |
3439 | | s3.wait_rect_y--; |
3440 | | if(s3.wait_rect_y < s3.curr_y - s3.rect_height) |
| 3614 | else |
3441 | 3615 | { |
3442 | | s3.state = S3_IDLE; |
3443 | | s3.gpbusy = false; |
| 3616 | s3.curr_y--; |
| 3617 | if(s3.curr_y < s3.prev_y - s3.rect_height) |
| 3618 | { |
| 3619 | s3.state = S3_IDLE; |
| 3620 | s3.gpbusy = false; |
| 3621 | } |
3444 | 3622 | } |
| 3623 | return; |
3445 | 3624 | } |
3446 | | return; |
3447 | 3625 | } |
3448 | 3626 | } |
3449 | | else |
| 3627 | } |
| 3628 | else |
| 3629 | { |
| 3630 | // "through plane" mode (single pixel) |
| 3631 | for(x=0;x<data_size;x+=8) |
3450 | 3632 | { |
3451 | | off--; |
3452 | | s3.wait_rect_x--; |
3453 | | if(s3.wait_rect_x < s3.curr_x - s3.rect_width) |
| 3633 | s3_write(off % vga.svga_intf.vram_size,off % vga.svga_intf.vram_size); |
| 3634 | |
| 3635 | if(s3.current_cmd & 0x0020) |
3454 | 3636 | { |
3455 | | s3.wait_rect_x = s3.curr_x; |
3456 | | if(s3.current_cmd & 0x0080) |
| 3637 | off++; |
| 3638 | s3.curr_x++; |
| 3639 | if(s3.curr_x > s3.prev_x + s3.rect_width) |
3457 | 3640 | { |
3458 | | s3.wait_rect_y++; |
3459 | | if(s3.wait_rect_y > s3.curr_y + s3.rect_height) |
| 3641 | s3.curr_x = s3.prev_x; |
| 3642 | s3.src_x = 0; |
| 3643 | if(s3.current_cmd & 0x0080) |
3460 | 3644 | { |
3461 | | s3.state = S3_IDLE; |
3462 | | s3.gpbusy = false; |
| 3645 | s3.curr_y++; |
| 3646 | if(s3.curr_y > s3.prev_y + s3.rect_height) |
| 3647 | { |
| 3648 | s3.state = S3_IDLE; |
| 3649 | s3.gpbusy = false; |
| 3650 | } |
3463 | 3651 | } |
| 3652 | else |
| 3653 | { |
| 3654 | s3.curr_y--; |
| 3655 | if(s3.curr_y < s3.prev_y - s3.rect_height) |
| 3656 | { |
| 3657 | s3.state = S3_IDLE; |
| 3658 | s3.gpbusy = false; |
| 3659 | } |
| 3660 | } |
| 3661 | return; |
3464 | 3662 | } |
3465 | | else |
| 3663 | } |
| 3664 | else |
| 3665 | { |
| 3666 | off--; |
| 3667 | s3.curr_x--; |
| 3668 | if(s3.curr_x < s3.prev_x - s3.rect_width) |
3466 | 3669 | { |
3467 | | s3.wait_rect_y--; |
3468 | | if(s3.wait_rect_y < s3.curr_y - s3.rect_height) |
| 3670 | s3.curr_x = s3.prev_x; |
| 3671 | s3.src_x = 0; |
| 3672 | if(s3.current_cmd & 0x0080) |
3469 | 3673 | { |
3470 | | s3.state = S3_IDLE; |
3471 | | s3.gpbusy = false; |
| 3674 | s3.curr_y++; |
| 3675 | if(s3.curr_y > s3.prev_y + s3.rect_height) |
| 3676 | { |
| 3677 | s3.state = S3_IDLE; |
| 3678 | s3.gpbusy = false; |
| 3679 | } |
3472 | 3680 | } |
| 3681 | else |
| 3682 | { |
| 3683 | s3.curr_y--; |
| 3684 | if(s3.curr_y < s3.prev_y - s3.rect_height) |
| 3685 | { |
| 3686 | s3.state = S3_IDLE; |
| 3687 | s3.gpbusy = false; |
| 3688 | } |
| 3689 | } |
| 3690 | return; |
3473 | 3691 | } |
3474 | | return; |
3475 | 3692 | } |
3476 | 3693 | } |
3477 | 3694 | } |
r17589 | r17590 | |
3576 | 3793 | |
3577 | 3794 | WRITE8_HANDLER( s3_mem_w ) |
3578 | 3795 | { |
3579 | | if(s3.state != S3_IDLE) |
| 3796 | // bit 4 of CR53 enables memory-mapped I/O |
| 3797 | // 0xA0000-0xA7ffff maps to port 0xE2E8 (pixel transfer) |
| 3798 | if(s3.cr53 & 0x10) |
3580 | 3799 | { |
3581 | | // pass through to the pixel transfer register (DirectX 5 wants this) |
3582 | | if(s3.bus_size == 0) |
| 3800 | if(offset < 0x8000) |
3583 | 3801 | { |
3584 | | s3.pixel_xfer = (s3.pixel_xfer & 0xffffff00) | data; |
3585 | | s3_wait_draw(); |
3586 | | } |
3587 | | if(s3.bus_size == 1) |
3588 | | { |
3589 | | switch(offset & 0x0001) |
| 3802 | // pass through to the pixel transfer register (DirectX 5 wants this) |
| 3803 | if(s3.bus_size == 0) |
3590 | 3804 | { |
3591 | | case 0: |
3592 | | default: |
3593 | 3805 | s3.pixel_xfer = (s3.pixel_xfer & 0xffffff00) | data; |
3594 | | break; |
3595 | | case 1: |
3596 | | s3.pixel_xfer = (s3.pixel_xfer & 0xffff00ff) | (data << 8); |
3597 | 3806 | s3_wait_draw(); |
3598 | | break; |
3599 | 3807 | } |
3600 | | } |
3601 | | if(s3.bus_size == 2) |
3602 | | { |
3603 | | switch(offset & 0x0003) |
| 3808 | if(s3.bus_size == 1) |
3604 | 3809 | { |
3605 | | case 0: |
3606 | | default: |
3607 | | s3.pixel_xfer = (s3.pixel_xfer & 0xffffff00) | data; |
3608 | | break; |
3609 | | case 1: |
3610 | | s3.pixel_xfer = (s3.pixel_xfer & 0xffff00ff) | (data << 8); |
3611 | | break; |
3612 | | case 2: |
3613 | | s3.pixel_xfer = (s3.pixel_xfer & 0xff00ffff) | (data << 16); |
3614 | | break; |
3615 | | case 3: |
3616 | | s3.pixel_xfer = (s3.pixel_xfer & 0x00ffffff) | (data << 24); |
3617 | | s3_wait_draw(); |
3618 | | break; |
| 3810 | switch(offset & 0x0001) |
| 3811 | { |
| 3812 | case 0: |
| 3813 | default: |
| 3814 | s3.pixel_xfer = (s3.pixel_xfer & 0xffffff00) | data; |
| 3815 | break; |
| 3816 | case 1: |
| 3817 | s3.pixel_xfer = (s3.pixel_xfer & 0xffff00ff) | (data << 8); |
| 3818 | s3_wait_draw(); |
| 3819 | break; |
| 3820 | } |
3619 | 3821 | } |
| 3822 | if(s3.bus_size == 2) |
| 3823 | { |
| 3824 | switch(offset & 0x0003) |
| 3825 | { |
| 3826 | case 0: |
| 3827 | default: |
| 3828 | s3.pixel_xfer = (s3.pixel_xfer & 0xffffff00) | data; |
| 3829 | break; |
| 3830 | case 1: |
| 3831 | s3.pixel_xfer = (s3.pixel_xfer & 0xffff00ff) | (data << 8); |
| 3832 | break; |
| 3833 | case 2: |
| 3834 | s3.pixel_xfer = (s3.pixel_xfer & 0xff00ffff) | (data << 16); |
| 3835 | break; |
| 3836 | case 3: |
| 3837 | s3.pixel_xfer = (s3.pixel_xfer & 0x00ffffff) | (data << 24); |
| 3838 | s3_wait_draw(); |
| 3839 | break; |
| 3840 | } |
| 3841 | } |
| 3842 | return; |
3620 | 3843 | } |
| 3844 | switch(offset) |
| 3845 | { |
| 3846 | case 0x8100: |
| 3847 | case 0x82e8: |
| 3848 | s3.curr_y = (s3.curr_y & 0xff00) | data; |
| 3849 | s3.prev_y = (s3.prev_y & 0xff00) | data; |
| 3850 | break; |
| 3851 | case 0x8101: |
| 3852 | case 0x82e9: |
| 3853 | s3.curr_y = (s3.curr_y & 0x00ff) | (data << 8); |
| 3854 | s3.prev_y = (s3.prev_y & 0x00ff) | (data << 8); |
| 3855 | break; |
| 3856 | case 0x8102: |
| 3857 | case 0x86e8: |
| 3858 | s3.curr_x = (s3.curr_x & 0xff00) | data; |
| 3859 | s3.prev_x = (s3.prev_x & 0xff00) | data; |
| 3860 | break; |
| 3861 | case 0x8103: |
| 3862 | case 0x86e9: |
| 3863 | s3.curr_x = (s3.curr_x & 0x00ff) | (data << 8); |
| 3864 | s3.prev_x = (s3.prev_x & 0x00ff) | (data << 8); |
| 3865 | break; |
| 3866 | case 0x8108: |
| 3867 | case 0x8ae8: |
| 3868 | s3.line_axial_step = (s3.line_axial_step & 0xff00) | data; |
| 3869 | s3.dest_y = (s3.dest_y & 0xff00) | data; |
| 3870 | break; |
| 3871 | case 0x8109: |
| 3872 | case 0x8ae9: |
| 3873 | s3.line_axial_step = (s3.line_axial_step & 0x00ff) | ((data & 0x3f) << 8); |
| 3874 | s3.dest_y = (s3.dest_y & 0x00ff) | (data << 8); |
| 3875 | break; |
| 3876 | case 0x810a: |
| 3877 | case 0x8ee8: |
| 3878 | s3.line_diagonal_step = (s3.line_diagonal_step & 0xff00) | data; |
| 3879 | s3.dest_x = (s3.dest_x & 0xff00) | data; |
| 3880 | break; |
| 3881 | case 0x810b: |
| 3882 | case 0x8ee9: |
| 3883 | s3.line_diagonal_step = (s3.line_diagonal_step & 0x00ff) | ((data & 0x3f) << 8); |
| 3884 | s3.dest_x = (s3.dest_x & 0x00ff) | (data << 8); |
| 3885 | break; |
| 3886 | case 0x8118: |
| 3887 | case 0x9ae8: |
| 3888 | s3.mmio_9ae8 = (s3.mmio_9ae8 & 0xff00) | data; |
| 3889 | break; |
| 3890 | case 0x8119: |
| 3891 | case 0x9ae9: |
| 3892 | s3.mmio_9ae8 = (s3.mmio_9ae8 & 0x00ff) | (data << 8); |
| 3893 | s3_cmd_w(space,0,s3.mmio_9ae8,0xffff); |
| 3894 | break; |
| 3895 | case 0x8120: |
| 3896 | case 0xa2e8: |
| 3897 | s3.bgcolour = (s3.bgcolour & 0xff00) | data; |
| 3898 | break; |
| 3899 | case 0x8121: |
| 3900 | case 0xa2e9: |
| 3901 | s3.bgcolour = (s3.bgcolour & 0x00ff) | (data << 8); |
| 3902 | break; |
| 3903 | case 0x8124: |
| 3904 | case 0xa6e8: |
| 3905 | s3.fgcolour = (s3.fgcolour & 0xff00) | data; |
| 3906 | break; |
| 3907 | case 0x8125: |
| 3908 | case 0xa6e9: |
| 3909 | s3.fgcolour = (s3.fgcolour & 0x00ff) | (data << 8); |
| 3910 | break; |
| 3911 | case 0xb6e8: |
| 3912 | case 0x8134: |
| 3913 | s3.bgmix = (s3.bgmix & 0xff00) | data; |
| 3914 | break; |
| 3915 | case 0x8135: |
| 3916 | case 0xb6e9: |
| 3917 | s3.bgmix = (s3.bgmix & 0x00ff) | (data << 8); |
| 3918 | break; |
| 3919 | case 0x8136: |
| 3920 | case 0xbae8: |
| 3921 | s3.fgmix = (s3.fgmix & 0xff00) | data; |
| 3922 | break; |
| 3923 | case 0xbae9: |
| 3924 | case 0x8137: |
| 3925 | s3.fgmix = (s3.fgmix & 0x00ff) | (data << 8); |
| 3926 | break; |
| 3927 | case 0x8138: |
| 3928 | s3.scissors_top = (s3.scissors_top & 0xff00) | data; |
| 3929 | break; |
| 3930 | case 0x8139: |
| 3931 | s3.scissors_top = (s3.scissors_top & 0x00ff) | (data << 8); |
| 3932 | break; |
| 3933 | case 0x813a: |
| 3934 | s3.scissors_left = (s3.scissors_left & 0xff00) | data; |
| 3935 | break; |
| 3936 | case 0x813b: |
| 3937 | s3.scissors_left = (s3.scissors_left & 0x00ff) | (data << 8); |
| 3938 | break; |
| 3939 | case 0x813c: |
| 3940 | s3.scissors_bottom = (s3.scissors_bottom & 0xff00) | data; |
| 3941 | break; |
| 3942 | case 0x813d: |
| 3943 | s3.scissors_bottom = (s3.scissors_bottom & 0x00ff) | (data << 8); |
| 3944 | break; |
| 3945 | case 0x813e: |
| 3946 | s3.scissors_right = (s3.scissors_right & 0xff00) | data; |
| 3947 | break; |
| 3948 | case 0x813f: |
| 3949 | s3.scissors_right = (s3.scissors_right & 0x00ff) | (data << 8); |
| 3950 | break; |
| 3951 | case 0x8140: |
| 3952 | s3.pixel_control = (s3.pixel_control & 0xff00) | data; |
| 3953 | break; |
| 3954 | case 0x8141: |
| 3955 | s3.pixel_control = (s3.pixel_control & 0x00ff) | (data << 8); |
| 3956 | break; |
| 3957 | case 0x8146: |
| 3958 | s3.multifunc_sel = (s3.multifunc_sel & 0xff00) | data; |
| 3959 | break; |
| 3960 | case 0x8148: |
| 3961 | s3.rect_height = (s3.rect_height & 0xff00) | data; |
| 3962 | break; |
| 3963 | case 0x8149: |
| 3964 | s3.rect_height = (s3.rect_height & 0x00ff) | (data << 8); |
| 3965 | break; |
| 3966 | case 0x814a: |
| 3967 | s3.rect_width = (s3.rect_width & 0xff00) | data; |
| 3968 | break; |
| 3969 | case 0x814b: |
| 3970 | s3.rect_width = (s3.rect_width & 0x00ff) | (data << 8); |
| 3971 | break; |
| 3972 | case 0xbee8: |
| 3973 | s3.mmio_bee8 = (s3.mmio_bee8 & 0xff00) | data; |
| 3974 | break; |
| 3975 | case 0xbee9: |
| 3976 | s3.mmio_bee8 = (s3.mmio_bee8 & 0x00ff) | (data << 8); |
| 3977 | s3_multifunc_w(space,0,s3.mmio_bee8,0xffff); |
| 3978 | break; |
| 3979 | default: |
| 3980 | logerror("S3: MMIO offset %05x write %02x\n",offset+0xa0000,data); |
| 3981 | } |
3621 | 3982 | return; |
3622 | 3983 | } |
3623 | 3984 | |