1 /////////////////////////////////////////////////////////////////////////
2 // $Id: banshee.cc 14310 2021-07-08 14:43:18Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2017-2021 The Bochs Project
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21
22 /*
23 * Portion of this software comes with the following license
24 */
25
26 /***************************************************************************
27
28 Copyright Aaron Giles
29 All rights reserved.
30
31 Redistribution and use in source and binary forms, with or without
32 modification, are permitted provided that the following conditions are
33 met:
34
35 * Redistributions of source code must retain the above copyright
36 notice, this list of conditions and the following disclaimer.
37 * Redistributions in binary form must reproduce the above copyright
38 notice, this list of conditions and the following disclaimer in
39 the documentation and/or other materials provided with the
40 distribution.
41 * Neither the name 'MAME' nor the names of its contributors may be
42 used to endorse or promote products derived from this software
43 without specific prior written permission.
44
45 THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
46 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
47 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48 DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
49 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
50 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
51 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
54 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
55 POSSIBILITY OF SUCH DAMAGE.
56
57 ***************************************************************************/
58
59 // 3dfx Voodoo Banshee / Voodoo3 emulation (partly based on a patch for DOSBox)
60
61 // TODO:
62 // - 2D host-to-screen stretching support
63 // - 2D screen-to-screen pattern stretching support
64 // - 2D chromaKey support
65 // - 2D reversible line drawing
66 // - pixel format conversion not supported in all cases
67 // - full AGP support
68
69 // FIXME:
70 // - Display errors in 16 bpp mode after leaving 3D mode
71 // - Display errors in 16 bpp mode with debug messages turned on (timing issue)
72 // - Bochs crashes on Windows host (MSVC in some cases, MSYS2 64-bit build also
73 // reported, but not yet reproduced)
74
75 // Define BX_PLUGGABLE in files that can be compiled into plugins. For
76 // platforms that require a special tag on exported symbols, BX_PLUGGABLE
77 // is used to know when we are exporting symbols and when we are importing.
78 #define BX_PLUGGABLE
79
80 #include "iodev.h"
81 #if BX_SUPPORT_PCI && BX_SUPPORT_VOODOO
82
83 #include "pci.h"
84 #include "vgacore.h"
85 #include "ddc.h"
86 #include "voodoo.h"
87 #include "virt_timer.h"
88 #include "bxthread.h"
89 #define BX_USE_TERNARY_ROP
90 #include "bitblt.h"
91
92 #define LOG_THIS theVoodooDevice->
93
94 const Bit8u banshee_iomask[256] = {4,0,0,0,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
95 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
96 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
97 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
98 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
99 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
100 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
101 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
102 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
103 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
104 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
105 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1,
106 7,1,3,1,7,1,3,1,7,1,3,1,7,1,3,1};
107
108 const Bit8u pxconv_table[16] = {0x3a,0x02,0x00,0x38,0x38,0x38,0x00,0x00,
109 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
110
111 #include "voodoo_types.h"
112 #include "voodoo_data.h"
113 #include "voodoo_main.h"
114
115 // Extern and forward declarations
116 extern voodoo_state *v;
117 extern BX_MUTEX(cmdfifo_mutex);
118 extern BX_MUTEX(render_mutex);
119 Bit32u register_r(Bit32u offset);
120 void register_w(Bit32u offset, Bit32u data, bool log);
121 void register_w_common(Bit32u offset, Bit32u data);
122 Bit32u lfb_r(Bit32u offset);
123 Bit32u lfb_w(Bit32u offset, Bit32u data, Bit32u mem_mask);
124 Bit32s texture_w(Bit32u offset, Bit32u data);
125 void cmdfifo_w(cmdfifo_info *f, Bit32u fbi_offset, Bit32u data);
126
127 // the class bx_banshee_c
128
bx_banshee_c()129 bx_banshee_c::bx_banshee_c() : bx_voodoo_base_c()
130 {
131 }
132
~bx_banshee_c()133 bx_banshee_c::~bx_banshee_c()
134 {
135 SIM->get_bochs_root()->remove("voodoo");
136 }
137
init_model(void)138 void bx_banshee_c::init_model(void)
139 {
140 static char model[40];
141 const char *vgabios_signature;
142
143 if (theVoodooVga == NULL) {
144 BX_PANIC(("Voodoo Banshee with VGA disabled not supported yet"));
145 }
146 is_agp = SIM->is_agp_device(BX_PLUGIN_VOODOO);
147 if (s.model == VOODOO_BANSHEE) {
148 if (!is_agp) {
149 strcpy(model, "Experimental 3dfx Voodoo Banshee PCI");
150 } else {
151 strcpy(model, "Experimental 3dfx Voodoo Banshee AGP");
152 }
153 DEV_register_pci_handlers2(this, &s.devfunc, BX_PLUGIN_VOODOO, model, is_agp);
154 init_pci_conf(0x121a, 0x0003, 0x01, 0x030000, 0x00, BX_PCI_INTA);
155 } else if (s.model == VOODOO_3) {
156 if (!is_agp) {
157 strcpy(model, "Experimental 3dfx Voodoo 3 PCI");
158 } else {
159 strcpy(model, "Experimental 3dfx Voodoo 3 AGP");
160 }
161 DEV_register_pci_handlers2(this, &s.devfunc, BX_PLUGIN_VOODOO, model, is_agp);
162 init_pci_conf(0x121a, 0x0005, 0x01, 0x030000, 0x00, BX_PCI_INTA);
163 } else {
164 BX_PANIC(("Unknown Voodoo Banshee compatible model"));
165 }
166 pci_conf[0x14] = 0x08;
167 init_bar_mem(0, 0x2000000, mem_read_handler, mem_write_handler);
168 init_bar_mem(1, 0x2000000, mem_read_handler, mem_write_handler);
169 init_bar_io(2, 256, read_handler, write_handler, banshee_iomask);
170 pci_rom_address = 0;
171 pci_rom_read_handler = mem_read_handler;
172 load_pci_rom(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr());
173 // Zero out Banshee i/o registers and init strapInfo
174 memset(v->banshee.io, 0, sizeof(v->banshee.io));
175 v->banshee.io[io_strapInfo] = 0x00000060;
176 if (is_agp) {
177 v->banshee.io[io_strapInfo] |= 0x0000000c;
178 }
179 if (pci_rom_size > 0x8000) {
180 v->banshee.io[io_strapInfo] |= 0x00000002;
181 }
182 // Modify device IDs in LGPL'd VGABIOS if required
183 vgabios_signature = (const char*)(pci_rom + 0x22);
184 if (!strncmp(vgabios_signature, "Bochs VGABios (PCI)", 19)) {
185 Bit16u pcir = pci_rom[0x18] | (pci_rom[0x19] << 8); // offset to PCIR data
186 Bit16u pci_vid = pci_rom[pcir + 4] | (pci_rom[pcir + 5] << 8);
187 if (pci_vid == 0x121a) {
188 if (s.model == VOODOO_BANSHEE) {
189 pci_rom[0x7ffa] = is_agp ? 0x03:0x04;
190 } else {
191 pci_rom[pcir + 6] = 0x05;
192 pci_rom[0x7ffa] = is_agp ? 0x52:0x36;
193 }
194 Bit8u checksum = 0;
195 for (int i = 0; i < 0x7fff; i++) {
196 checksum += pci_rom[i];
197 }
198 pci_rom[0x7fff] = -checksum;
199 }
200 }
201 }
202
reset(unsigned type)203 void bx_banshee_c::reset(unsigned type)
204 {
205 unsigned i;
206
207 static const struct reset_vals_t {
208 unsigned addr;
209 unsigned char val;
210 } reset_vals2[] = {
211 { 0x04, 0x00 }, { 0x05, 0x00 }, // command io / memory
212 { 0x06, 0x10 }, { 0x07, 0x00 }, // status
213 // capabilities pointer 0x34 - 0x37
214 { 0x34, 0x60 }, { 0x35, 0x00 },
215 { 0x36, 0x00 }, { 0x37, 0x00 },
216 { 0x3c, 0x00 }, // IRQ
217 // ACPI capabilities ID 0x60 - 0x63
218 { 0x60, 0x01 }, { 0x61, 0x00 },
219 { 0x62, 0x21 }, { 0x63, 0x00 },
220 // ACPI control/status 0x64 - 0x67
221 { 0x64, 0x00 }, { 0x65, 0x00 },
222 { 0x66, 0x00 }, { 0x67, 0x00 },
223 };
224 for (i = 0; i < sizeof(reset_vals2) / sizeof(*reset_vals2); ++i) {
225 pci_conf[reset_vals2[i].addr] = reset_vals2[i].val;
226 }
227 // AGP reported by PCI status, new capabilities and strapInfo
228 if (is_agp) {
229 pci_conf[0x06] |= 0x20;
230 pci_conf[0x34] = 0x54;
231 pci_conf[0x54] = 0x02;
232 pci_conf[0x55] = 0x60;
233 pci_conf[0x56] = 0x10;
234 pci_conf[0x57] = 0x00;
235 if (s.model == VOODOO_3) {
236 pci_conf[0x58] = 0x23;
237 } else {
238 pci_conf[0x58] = 0x21;
239 }
240 pci_conf[0x59] = 0x02;
241 pci_conf[0x5b] = 0x07;
242 }
243 for (i = 0; i < 4; i++) {
244 pci_conf[0x2c + i] = pci_rom[(pci_rom_size - 8) + i];
245 }
246 v->banshee.io[io_pciInit0] = 0x01800040;
247 v->banshee.io[io_sipMonitor] = 0x40000000;
248 v->banshee.io[io_lfbMemoryConfig] = 0x000a2200;
249 v->banshee.io[io_miscInit1] = ((v->banshee.io[io_strapInfo] & 0x1f) << 24);
250 v->banshee.io[io_dramInit0] = 0x00579d29 | ((v->banshee.io[io_strapInfo] & 0x60) << 21);
251 v->banshee.io[io_dramInit1] = 0x00f02200;
252 v->banshee.io[io_tmuGbeInit] = 0x00000bfb;
253 v->vidclk = 14318180;
254 if (theVoodooVga != NULL) {
255 theVoodooVga->banshee_set_vclk3((Bit32u)v->vidclk);
256 }
257
258 // Deassert IRQ
259 set_irq_level(0);
260 }
261
register_state(void)262 void bx_banshee_c::register_state(void)
263 {
264 bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "voodoo", "Voodoo Banshee State");
265 voodoo_register_state(list);
266 bx_list_c *banshee = new bx_list_c(list, "banshee", "Banshee State");
267 new bx_shadow_data_c(banshee, "io", (Bit8u*)v->banshee.io, 256, 1);
268 new bx_shadow_data_c(banshee, "agp", (Bit8u*)v->banshee.agp, 0x80, 1);
269 new bx_shadow_data_c(banshee, "crtc", (Bit8u*)v->banshee.crtc, 0x27, 1);
270 new bx_shadow_num_c(banshee, "disp_bpp", &v->banshee.disp_bpp);
271 BXRS_PARAM_BOOL(banshee, half_mode, v->banshee.half_mode);
272 BXRS_PARAM_BOOL(banshee, dac_8bit, v->banshee.dac_8bit);
273 BXRS_PARAM_BOOL(banshee, desktop_tiled, v->banshee.desktop_tiled);
274 BXRS_PARAM_BOOL(banshee, hwcursor_enabled, v->banshee.hwcursor.enabled);
275 BXRS_PARAM_BOOL(banshee, hwcursor_mode, v->banshee.hwcursor.mode);
276 new bx_shadow_num_c(banshee, "hwcursor_addr", &v->banshee.hwcursor.addr, BASE_HEX);
277 new bx_shadow_num_c(banshee, "hwcursor_x", &v->banshee.hwcursor.x, BASE_HEX);
278 new bx_shadow_num_c(banshee, "hwcursor_y", &v->banshee.hwcursor.y, BASE_HEX);
279 new bx_shadow_num_c(banshee, "hwcursor_color0", &v->banshee.hwcursor.color[0], BASE_HEX);
280 new bx_shadow_num_c(banshee, "hwcursor_color1", &v->banshee.hwcursor.color[1], BASE_HEX);
281 new bx_shadow_data_c(banshee, "blt_reg", (Bit8u*)v->banshee.blt.reg, 0x80, 1);
282 new bx_shadow_data_c(banshee, "blt_cpat", (Bit8u*)v->banshee.blt.cpat, 0x100, 1);
283 BXRS_PARAM_BOOL(banshee, blt_busy, v->banshee.blt.busy);
284 new bx_shadow_num_c(banshee, "blt_cmd", &v->banshee.blt.cmd);
285 BXRS_PARAM_BOOL(banshee, blt_immed, v->banshee.blt.immed);
286 BXRS_PARAM_BOOL(banshee, blt_x_dir, v->banshee.blt.x_dir);
287 BXRS_PARAM_BOOL(banshee, blt_y_dir, v->banshee.blt.y_dir);
288 BXRS_PARAM_BOOL(banshee, blt_transp, v->banshee.blt.transp);
289 new bx_shadow_num_c(banshee, "blt_patsx", &v->banshee.blt.patsx);
290 new bx_shadow_num_c(banshee, "blt_patsy", &v->banshee.blt.patsy);
291 BXRS_PARAM_BOOL(banshee, blt_clip_sel, v->banshee.blt.clip_sel);
292 new bx_shadow_num_c(banshee, "blt_rop0", &v->banshee.blt.rop[0]);
293 new bx_shadow_num_c(banshee, "blt_rop1", &v->banshee.blt.rop[1]);
294 new bx_shadow_num_c(banshee, "blt_rop2", &v->banshee.blt.rop[2]);
295 new bx_shadow_num_c(banshee, "blt_rop3", &v->banshee.blt.rop[3]);
296 new bx_shadow_num_c(banshee, "blt_src_base", &v->banshee.blt.src_base, BASE_HEX);
297 BXRS_PARAM_BOOL(banshee, blt_src_tiled, v->banshee.blt.src_tiled);
298 new bx_shadow_num_c(banshee, "blt_src_fmt", &v->banshee.blt.src_fmt);
299 new bx_shadow_num_c(banshee, "blt_src_pitch", &v->banshee.blt.src_pitch);
300 new bx_shadow_num_c(banshee, "blt_src_swizzle", &v->banshee.blt.src_swizzle);
301 new bx_shadow_num_c(banshee, "blt_src_x", &v->banshee.blt.src_x);
302 new bx_shadow_num_c(banshee, "blt_src_y", &v->banshee.blt.src_y);
303 new bx_shadow_num_c(banshee, "blt_src_w", &v->banshee.blt.src_w);
304 new bx_shadow_num_c(banshee, "blt_src_h", &v->banshee.blt.src_h);
305 new bx_shadow_num_c(banshee, "blt_dst_base", &v->banshee.blt.dst_base, BASE_HEX);
306 BXRS_PARAM_BOOL(banshee, blt_dst_tiled, v->banshee.blt.dst_tiled);
307 new bx_shadow_num_c(banshee, "blt_dst_fmt", &v->banshee.blt.dst_fmt);
308 new bx_shadow_num_c(banshee, "blt_dst_pitch", &v->banshee.blt.dst_pitch);
309 new bx_shadow_num_c(banshee, "blt_dst_x", &v->banshee.blt.dst_x);
310 new bx_shadow_num_c(banshee, "blt_dst_y", &v->banshee.blt.dst_y);
311 new bx_shadow_num_c(banshee, "blt_dst_w", &v->banshee.blt.dst_w);
312 new bx_shadow_num_c(banshee, "blt_dst_h", &v->banshee.blt.dst_h);
313 new bx_shadow_num_c(banshee, "blt_fgcolor", (Bit32u*)&v->banshee.blt.fgcolor, BASE_HEX);
314 new bx_shadow_num_c(banshee, "blt_bgcolor", (Bit32u*)&v->banshee.blt.bgcolor, BASE_HEX);
315 new bx_shadow_num_c(banshee, "blt_clipx0_0", &v->banshee.blt.clipx0[0]);
316 new bx_shadow_num_c(banshee, "blt_clipx0_1", &v->banshee.blt.clipx0[1]);
317 new bx_shadow_num_c(banshee, "blt_clipy0_0", &v->banshee.blt.clipy0[0]);
318 new bx_shadow_num_c(banshee, "blt_clipy0_1", &v->banshee.blt.clipy0[1]);
319 new bx_shadow_num_c(banshee, "blt_clipx1_0", &v->banshee.blt.clipx1[0]);
320 new bx_shadow_num_c(banshee, "blt_clipx1_1", &v->banshee.blt.clipx1[1]);
321 new bx_shadow_num_c(banshee, "blt_clipy1_0", &v->banshee.blt.clipy1[0]);
322 new bx_shadow_num_c(banshee, "blt_clipy1_1", &v->banshee.blt.clipy1[1]);
323 new bx_shadow_num_c(banshee, "blt_h2s_pitch", &v->banshee.blt.h2s_pitch);
324 new bx_shadow_num_c(banshee, "blt_h2s_pxstart", &v->banshee.blt.h2s_pxstart);
325 }
326
after_restore_state(void)327 void bx_banshee_c::after_restore_state(void)
328 {
329 bx_pci_device_c::after_restore_pci_state(mem_read_handler);
330 if ((v->banshee.io[io_vidProcCfg] & 0x01) && (theVoodooVga != NULL)) {
331 v->fbi.clut_dirty = 1;
332 update_timing();
333 theVoodooVga->banshee_update_mode();
334 }
335 start_fifo_thread();
336 }
337
update_timing(void)338 bool bx_banshee_c::update_timing(void)
339 {
340 float hfreq;
341 bx_crtc_params_t crtcp;
342 Bit32u vclock = 0;
343
344 BX_VVGA_THIS get_crtc_params(&crtcp, &vclock);
345 hfreq = vclock / (float)(crtcp.htotal * 8);
346 v->vertfreq = hfreq / (float)crtcp.vtotal;
347 s.vdraw.vtotal_usec = (unsigned)(1000000.0 / v->vertfreq);
348 s.vdraw.width = v->fbi.width;
349 s.vdraw.height = v->fbi.height;
350 vertical_timer_handler(this);
351 bx_virt_timer.activate_timer(s.vertical_timer_id, (Bit32u)s.vdraw.vtotal_usec, 1);
352 return 1;
353 }
354
set_tile_updated(unsigned xti,unsigned yti,bool flag)355 void bx_banshee_c::set_tile_updated(unsigned xti, unsigned yti, bool flag)
356 {
357 SET_TILE_UPDATED(, xti, yti, flag);
358 }
359
draw_hwcursor(unsigned xc,unsigned yc,bx_svga_tileinfo_t * info)360 void bx_banshee_c::draw_hwcursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *info)
361 {
362 unsigned cx, cy, cw, ch, px, py, w, h, x, y;
363 Bit8u *cpat0, *cpat1, *tile_ptr, *tile_ptr2, *vid_ptr;
364 Bit8u ccode, pbits, pval0, pval1;
365 Bit32u colour = 0, start;
366 Bit16u index, pitch;
367 int i;
368
369 if ((xc <= v->banshee.hwcursor.x) &&
370 ((int)(xc + X_TILESIZE) > (v->banshee.hwcursor.x - 63)) &&
371 (yc <= v->banshee.hwcursor.y) &&
372 ((int)(yc + Y_TILESIZE) > (v->banshee.hwcursor.y - 63))) {
373
374 if ((v->banshee.io[io_vidProcCfg] & 0x181) == 0x81) {
375 start = v->banshee.io[io_vidDesktopStartAddr];
376 pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
377 } else {
378 start = v->fbi.rgboffs[0];
379 pitch = (v->banshee.io[io_vidDesktopOverlayStride] >> 16) & 0x7fff;
380 }
381 Bit8u *disp_ptr = &v->fbi.ram[start & v->fbi.mask];
382 if (v->banshee.desktop_tiled) {
383 pitch *= 128;
384 }
385 tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h);
386
387 if ((v->banshee.hwcursor.x - 63) < (int)xc) {
388 cx = xc;
389 if ((v->banshee.hwcursor.x - xc + 1) > w) {
390 cw = w;
391 } else {
392 cw = v->banshee.hwcursor.x - xc + 1;
393 }
394 px = 63 - (v->banshee.hwcursor.x - xc);
395 } else {
396 cx = v->banshee.hwcursor.x - 63;
397 cw = w - (v->banshee.hwcursor.x - 63 - xc);
398 px = 0;
399 }
400 if ((v->banshee.hwcursor.y - 63) < (int)yc) {
401 cy = yc;
402 if ((v->banshee.hwcursor.y - yc + 1) > h) {
403 ch = h;
404 } else {
405 ch = v->banshee.hwcursor.y - yc + 1;
406 }
407 py = 63 - (v->banshee.hwcursor.y - yc);
408 } else {
409 cy = v->banshee.hwcursor.y - 63;
410 ch = h - (v->banshee.hwcursor.y - 63 - yc);
411 py = 0;
412 }
413 tile_ptr += ((cy - yc) * info->pitch);
414 tile_ptr += ((cx - xc) * (info->bpp >> 3));
415 cpat0 = &v->fbi.ram[v->banshee.hwcursor.addr] + (py * 16);
416 for (y = cy; y < (cy + ch); y++) {
417 cpat1 = cpat0 + (px >> 3);
418 pbits = 8 - (px & 7);
419 tile_ptr2 = tile_ptr;
420 for (x = cx; x < (cx + cw); x++) {
421 pval0 = (*cpat1 >> (pbits - 1)) & 1;
422 pval1 = (*(cpat1 + 8) >> (pbits - 1)) & 1;
423 ccode = pval0 + (pval1 << 1) + (v->banshee.hwcursor.mode << 2);
424 if ((ccode == 0) || (ccode == 5)) {
425 colour = v->banshee.hwcursor.color[0];
426 } else if ((ccode == 2) || (ccode == 7)) {
427 colour = v->banshee.hwcursor.color[1];
428 } else {
429 vid_ptr = disp_ptr + y * pitch + x * (v->banshee.disp_bpp >> 3);
430 switch (v->banshee.disp_bpp) {
431 case 8:
432 if (info->is_indexed) {
433 colour = *vid_ptr;
434 } else {
435 colour = v->fbi.clut[*vid_ptr];
436 }
437 break;
438 case 16:
439 index = *(vid_ptr++);
440 index |= *(vid_ptr++) << 8;
441 colour = v->fbi.pen[index];
442 break;
443 case 24:
444 case 32:
445 colour = *vid_ptr;
446 colour |= (*(vid_ptr + 1)) << 8;
447 colour |= (*(vid_ptr + 2)) << 16;
448 break;
449 }
450 if (ccode == 3) colour ^= 0xffffff;
451 }
452 if (!info->is_indexed) {
453 colour = MAKE_COLOUR(
454 colour, 24, info->red_shift, info->red_mask,
455 colour, 16, info->green_shift, info->green_mask,
456 colour, 8, info->blue_shift, info->blue_mask);
457 if (info->is_little_endian) {
458 for (i=0; i<info->bpp; i+=8) {
459 *(tile_ptr2++) = (Bit8u)(colour >> i);
460 }
461 } else {
462 for (i=info->bpp-8; i>-8; i-=8) {
463 *(tile_ptr2++) = (Bit8u)(colour >> i);
464 }
465 }
466 } else {
467 *(tile_ptr2++) = (Bit8u)colour;
468 }
469 if (--pbits == 0) {
470 cpat1++;
471 pbits = 8;
472 }
473 }
474 cpat0 += 16;
475 tile_ptr += info->pitch;
476 }
477 }
478 }
479
get_retrace(bool hv)480 Bit32u bx_banshee_c::get_retrace(bool hv)
481 {
482 return theVoodooVga->get_retrace();
483 }
484
reg_write(Bit32u reg,Bit32u value)485 void bx_banshee_c::reg_write(Bit32u reg, Bit32u value)
486 {
487 if ((reg >> 11) & 1) {
488 blt_reg_write(reg & 0xff, value);
489 } else {
490 register_w(reg, value, 1);
491 }
492 }
493
494 // pci configuration space write handler
pci_write_handler(Bit8u address,Bit32u value,unsigned io_len)495 void bx_banshee_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len)
496 {
497 Bit8u value8, oldval;
498
499 if ((address >= 0x1c) && (address < 0x2c))
500 return;
501
502 BX_DEBUG_PCI_WRITE(address, value, io_len);
503 for (unsigned i=0; i<io_len; i++) {
504 value8 = (value >> (i*8)) & 0xFF;
505 oldval = pci_conf[address+i];
506 switch (address+i) {
507 case 0x04:
508 value8 &= 0x23;
509 break;
510 case 0x2c:
511 case 0x2d:
512 case 0x2e:
513 case 0x2f:
514 if ((v->banshee.io[io_miscInit1] & 0x08) == 0) {
515 value8 = oldval;
516 }
517 break;
518 case 0x06:
519 case 0x07:
520 value8 = oldval;
521 break;
522 default:
523 if (address >= 0x54) {
524 value8 = oldval;
525 }
526 }
527 pci_conf[address+i] = value8;
528 }
529 }
530
read_handler(void * this_ptr,Bit32u address,unsigned io_len)531 Bit32u bx_banshee_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
532 {
533 bx_banshee_c *class_ptr = (bx_banshee_c*)this_ptr;
534 return class_ptr->read(address, io_len);
535 }
536
read(Bit32u address,unsigned io_len)537 Bit32u bx_banshee_c::read(Bit32u address, unsigned io_len)
538 {
539 static Bit8u lastreg = 0xff;
540 Bit32u result;
541
542 Bit8u offset = (Bit8u)(address & 0xff);
543 Bit8u reg = (offset >> 2);
544 switch (reg) {
545 case io_status:
546 result = register_r(0);
547 break;
548
549 case io_dacData:
550 result = v->fbi.clut[v->banshee.io[io_dacAddr] & 0x1ff] = v->banshee.io[reg];
551 break;
552
553 case io_vgab0: case io_vgab4: case io_vgab8: case io_vgabc:
554 case io_vgac0: case io_vgac4: case io_vgac8: case io_vgacc:
555 case io_vgad0: case io_vgad4: case io_vgad8: case io_vgadc:
556 result = 0;
557 // i/o read only, not memory mapped
558 if ((theVoodooVga != NULL) && (address & 0xff00)) {
559 for (unsigned i=0; i<io_len; i++) {
560 result |= (theVoodooVga->banshee_vga_read_handler(theVoodooVga, 0x300+offset+i, 1) << (i*8));
561 }
562 }
563 break;
564
565 case io_vidSerialParallelPort:
566 result = v->banshee.io[reg] & 0xf387ffff;
567 if ((v->banshee.io[reg] >> 18) & 1) {
568 result |= ((Bit32u)ddc.read() << 19);
569 } else {
570 result |= 0x00780000;
571 }
572 if ((v->banshee.io[reg] >> 23) & 1) {
573 result |= ((v->banshee.io[reg] & 0x03000000) << 2);
574 } else {
575 result |= 0x0f000000;
576 }
577 break;
578
579 default:
580 result = v->banshee.io[reg];
581 break;
582 }
583 if ((reg < io_vgab0) || (reg > io_vgadc)) {
584 if ((offset & 3) != 0) {
585 result >>= ((offset & 3) * 8);
586 }
587 }
588 if ((reg != io_status) || (lastreg != io_status)) {
589 BX_DEBUG(("banshee read from offset 0x%02x (%s) result = 0x%08x", offset,
590 banshee_io_reg_name[reg], result));
591 }
592 lastreg = reg;
593 return result;
594 }
595
write_handler(void * this_ptr,Bit32u address,Bit32u value,unsigned io_len)596 void bx_banshee_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
597 {
598 bx_banshee_c *class_ptr = (bx_banshee_c*)this_ptr;
599 return class_ptr->write(address, value, io_len);
600 }
601
write(Bit32u address,Bit32u value,unsigned io_len)602 void bx_banshee_c::write(Bit32u address, Bit32u value, unsigned io_len)
603 {
604 Bit8u offset = (Bit8u)(address & 0xff);
605 Bit8u reg = (offset>>2), dac_idx, k, m, n, shift;
606 Bit32u old = v->banshee.io[reg], mask;
607 bool prev_hwce = v->banshee.hwcursor.enabled;
608 Bit16u prev_hwcx = v->banshee.hwcursor.x;
609 Bit16u prev_hwcy = v->banshee.hwcursor.y;
610 bool mode_change = 0;
611
612 BX_DEBUG(("banshee write to offset 0x%02x: value = 0x%08x len=%d (%s)", offset, value,
613 io_len, banshee_io_reg_name[reg]));
614 if ((reg < io_vgab0) || (reg > io_vgadc)) {
615 if (io_len == 1) {
616 shift = ((offset & 3) * 8);
617 mask = ~(0xff << shift);
618 value = (old & mask) | (value << shift);
619 } else if (io_len == 2) {
620 shift = ((offset & 2) * 8);
621 mask = ~(0xffff << shift);
622 value = (old & mask) | (value << shift);
623 }
624 }
625 switch (reg) {
626 case io_lfbMemoryConfig:
627 v->banshee.io[reg] = value;
628 v->fbi.lfb_base = (value & 0x1fff) << 12;
629 v->fbi.lfb_stride = ((value >> 13) & 7) + 10;
630 break;
631
632 case io_miscInit0:
633 v->banshee.io[reg] = value;
634 v->fbi.yorigin = (value >> 18) & 0xfff;
635 break;
636
637 case io_miscInit1:
638 v->banshee.io[reg] = value & 0xffffff;
639 v->banshee.io[reg] |= ((v->banshee.io[io_strapInfo] & 0x1f) << 24);
640 break;
641
642 case io_vgaInit0:
643 v->banshee.io[reg] = value;
644 if (theVoodooVga != NULL) {
645 theVoodooVga->banshee_set_dac_mode((v->banshee.io[reg] & 0x04) != 0);
646 }
647 break;
648
649 case io_dramCommand:
650 blt_reg_write(0x1c, value);
651 break;
652
653 case io_dramData:
654 blt_reg_write(0x19, value);
655 break;
656
657 case io_strapInfo:
658 break;
659
660 case io_pllCtrl0:
661 if (value != v->banshee.io[reg]) {
662 v->banshee.io[reg] = value;
663 k = (Bit8u)(value & 0x03);
664 m = (Bit8u)((value >> 2) & 0x3f);
665 n = (Bit8u)((value >> 8) & 0xff);
666 v->vidclk = (float)(14318180.0f * ((double)n + 2.0f) / ((double)m + 2.0f) / (double)(1 << k));
667 BX_INFO(("Setting VCLK #3 (pllCtrl0) = %.3f MHz", v->vidclk / 1000000.0f));
668 if (theVoodooVga != NULL) {
669 theVoodooVga->banshee_set_vclk3((Bit32u)v->vidclk);
670 }
671 }
672 break;
673
674 case io_dacData:
675 v->banshee.io[reg] = value;
676 if (v->banshee.io[reg] != v->fbi.clut[v->banshee.io[io_dacAddr] & 0x1ff]) {
677 v->fbi.clut[v->banshee.io[io_dacAddr] & 0x1ff] = v->banshee.io[reg];
678 v->fbi.clut_dirty = 1;
679 if (v->banshee.io[io_dacAddr] <= 0xff) {
680 dac_idx = v->banshee.io[io_dacAddr] & 0xff;
681 bx_gui->palette_change_common(dac_idx, (v->fbi.clut[dac_idx] >> 16) & 0xff,
682 (v->fbi.clut[dac_idx] >> 8) & 0xff,
683 v->fbi.clut[dac_idx] & 0xff);
684 }
685 }
686 break;
687
688 case io_vidProcCfg:
689 v->banshee.io[reg] = value;
690 if ((v->banshee.io[reg] ^ old) & 0x3c00)
691 v->fbi.clut_dirty = 1;
692 if ((v->banshee.io[reg] & 0x01) && ((old & 0x01) == 0x00)) {
693 update_timing();
694 if (theVoodooVga != NULL) {
695 theVoodooVga->banshee_update_mode();
696 }
697 mode_change = 1;
698 } else if (!(v->banshee.io[reg] & 0x01) && ((old & 0x01) == 0x01)) {
699 bx_virt_timer.deactivate_timer(s.vertical_timer_id);
700 v->vtimer_running = 0;
701 }
702 if ((v->banshee.io[reg] & 0x01) && ((v->banshee.io[reg] & 0x180) != (old & 0x180))) {
703 mode_change = 1;
704 }
705 if (mode_change) {
706 if ((v->banshee.io[reg] & 0x180) == 0x080) {
707 BX_INFO(("2D desktop mode enabled"));
708 } else if ((old & 0x100) == 0) {
709 BX_INFO(("3D overlay mode enabled"));
710 v->vtimer_running = 1;
711 }
712 }
713 v->banshee.hwcursor.enabled = ((v->banshee.io[reg] >> 27) & 1);
714 v->banshee.hwcursor.mode = ((v->banshee.io[reg] >> 1) & 1);
715 if (v->banshee.hwcursor.enabled != prev_hwce) {
716 theVoodooVga->redraw_area(v->banshee.hwcursor.x - 63, v->banshee.hwcursor.y - 63,
717 v->banshee.hwcursor.x, v->banshee.hwcursor.y);
718 }
719 if ((v->banshee.io[reg] >> 2) & 1) {
720 BX_ERROR(("vidProcCfg: overlay stereo mode not supported yet"));
721 }
722 if ((v->banshee.io[reg] >> 5) & 1) {
723 BX_ERROR(("vidProcCfg: chromaKey mode not supported yet"));
724 }
725 if ((v->banshee.io[reg] >> 16) & 3) {
726 BX_ERROR(("vidProcCfg: overlay filter mode not supported yet"));
727 }
728 v->banshee.desktop_tiled = ((v->banshee.io[reg] >> 24) & 1);
729 break;
730
731 case io_hwCurPatAddr:
732 v->banshee.io[reg] = value;
733 v->banshee.hwcursor.addr = v->banshee.io[reg] & 0xffffff;
734 if (v->banshee.hwcursor.enabled && (value != old)) {
735 theVoodooVga->redraw_area(v->banshee.hwcursor.x - 63, v->banshee.hwcursor.y - 63,
736 v->banshee.hwcursor.x, v->banshee.hwcursor.y);
737 }
738 break;
739
740 case io_hwCurLoc:
741 v->banshee.io[reg] = value;
742 v->banshee.hwcursor.x = v->banshee.io[reg] & 0x7ff;
743 v->banshee.hwcursor.y = (v->banshee.io[reg] >> 16) & 0x7ff;
744 if (v->banshee.hwcursor.enabled && (value != old)) {
745 theVoodooVga->redraw_area(prev_hwcx - 63, prev_hwcy - 63, prev_hwcx, prev_hwcy);
746 theVoodooVga->redraw_area(v->banshee.hwcursor.x - 63, v->banshee.hwcursor.y - 63,
747 v->banshee.hwcursor.x, v->banshee.hwcursor.y);
748 }
749 break;
750
751 case io_hwCurC0:
752 v->banshee.io[reg] = value;
753 v->banshee.hwcursor.color[0] = v->banshee.io[reg] & 0xffffff;
754 break;
755
756 case io_hwCurC1:
757 v->banshee.io[reg] = value;
758 v->banshee.hwcursor.color[1] = v->banshee.io[reg] & 0xffffff;
759 break;
760
761 case io_vidSerialParallelPort:
762 v->banshee.io[reg] = value;
763 if ((v->banshee.io[reg] >> 18) & 1) {
764 ddc.write((v->banshee.io[reg] >> 19) & 1, (v->banshee.io[reg] >> 20) & 1);
765 }
766 break;
767
768 case io_vidScreenSize:
769 v->banshee.io[reg] = value;
770 v->fbi.width = (value & 0xfff);
771 v->fbi.height = (value >> 12) & 0xfff;
772 break;
773
774 case io_vgab0: case io_vgab4: case io_vgab8: case io_vgabc:
775 case io_vgac0: case io_vgac4: case io_vgac8: case io_vgacc:
776 case io_vgad0: case io_vgad4: case io_vgad8: case io_vgadc:
777 // i/o write only, not memory mapped
778 if ((theVoodooVga != NULL) && (address & 0xff00)) {
779 for (unsigned i=0; i<io_len; i++) {
780 Bit8u value8 = (value >> (i*8)) & 0xff;
781 theVoodooVga->banshee_vga_write_handler(theVoodooVga, 0x300+offset+i, value8, 1);
782 }
783 }
784 break;
785
786 case io_vidDesktopStartAddr:
787 case io_vidDesktopOverlayStride:
788 if ((v->banshee.io[io_vidProcCfg] & 0x01) && (v->banshee.io[reg] != value)) {
789 v->fbi.video_changed = 1;
790 }
791 v->banshee.io[reg] = value;
792 break;
793
794 default:
795 v->banshee.io[reg] = value;
796 break;
797 }
798 }
799
mem_read_handler(bx_phy_address addr,unsigned len,void * data,void * param)800 bool bx_banshee_c::mem_read_handler(bx_phy_address addr, unsigned len,
801 void *data, void *param)
802 {
803 bx_banshee_c *class_ptr = (bx_banshee_c*)param;
804 class_ptr->mem_read(addr, len, data);
805 return 1;
806 }
807
mem_write_handler(bx_phy_address addr,unsigned len,void * data,void * param)808 bool bx_banshee_c::mem_write_handler(bx_phy_address addr, unsigned len,
809 void *data, void *param)
810 {
811 bx_banshee_c *class_ptr = (bx_banshee_c*)param;
812 class_ptr->mem_write(addr, len, data);
813 return 1;
814 }
815
mem_read(bx_phy_address addr,unsigned len,void * data)816 void bx_banshee_c::mem_read(bx_phy_address addr, unsigned len, void *data)
817 {
818 Bit64u value = BX_MAX_BIT64U;
819 Bit32u offset = (addr & 0x1ffffff);
820 Bit32u pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
821 unsigned i, x, y;
822
823 if (pci_rom_size > 0) {
824 Bit32u mask = (pci_rom_size - 1);
825 if (((Bit32u)addr & ~mask) == pci_rom_address) {
826 if (pci_conf[0x30] & 0x01) {
827 value = 0;
828 for (unsigned i = 0; i < len; i++) {
829 value |= (pci_rom[(addr & mask) + i] << (i * 8));
830 }
831 }
832 switch (len) {
833 case 1:
834 *((Bit8u*)data) = (Bit8u)value;
835 break;
836 case 2:
837 *((Bit16u*)data) = (Bit16u)value;
838 break;
839 default:
840 *((Bit32u*)data) = (Bit32u)value;
841 }
842 return;
843 }
844 }
845 if ((addr & ~0x1ffffff) == pci_bar[0].addr) {
846 if (offset < 0x80000) {
847 value = read(offset, len);
848 } else if (offset < 0x100000) {
849 value = agp_reg_read((offset >> 2) & 0x7f);
850 } else if (offset < 0x200000) {
851 value = blt_reg_read((offset >> 2) & 0x7f);
852 } else if (offset < 0x600000) {
853 value = register_r((offset - 0x200000) >> 2);
854 } else if (offset < 0xc00000) {
855 BX_DEBUG(("reserved read from offset 0x%08x", offset));
856 } else if (offset < 0x1000000) {
857 BX_ERROR(("TODO: YUV planar space read from offset 0x%08x", offset));
858 } else {
859 Bit8u temp = v->fbi.lfb_stride;
860 v->fbi.lfb_stride = 11;
861 value = lfb_r((offset & v->fbi.mask) >> 2);
862 v->fbi.lfb_stride = temp;
863 }
864 } else if ((addr & ~0x1ffffff) == pci_bar[1].addr) {
865 if (offset >= v->fbi.lfb_base) {
866 offset -= v->fbi.lfb_base;
867 pitch *= 128;
868 x = (offset << 0) & ((1 << v->fbi.lfb_stride) - 1);
869 y = (offset >> v->fbi.lfb_stride) & 0x1fff;
870 offset = (v->fbi.lfb_base + y * pitch + x) & v->fbi.mask;
871 } else {
872 offset &= v->fbi.mask;
873 }
874 value = 0;
875 for (i = 0; i < len; i++) {
876 value |= ((Bit64u)v->fbi.ram[offset + i] << (i*8));
877 }
878 }
879 switch (len) {
880 case 1:
881 *((Bit8u*)data) = (Bit8u)value;
882 break;
883 case 2:
884 *((Bit16u*)data) = (Bit16u)value;
885 break;
886 case 4:
887 *((Bit32u*)data) = (Bit32u)value;
888 break;
889 default:
890 *((Bit64u*)data) = value;
891 }
892 }
893
mem_write(bx_phy_address addr,unsigned len,void * data)894 void bx_banshee_c::mem_write(bx_phy_address addr, unsigned len, void *data)
895 {
896 Bit32u offset = (addr & 0x1ffffff);
897 Bit32u value;
898 Bit32u mask = 0xffffffff;
899
900 switch (len) {
901 case 1:
902 value = *(Bit8u*)data;
903 break;
904 case 2:
905 value = *(Bit16u*)data;
906 break;
907 default:
908 value = *(Bit32u*)data;
909 }
910 if ((addr & ~0x1ffffff) == pci_bar[0].addr) {
911 if (offset < 0x80000) {
912 write(offset, value, len);
913 } else if (offset < 0x100000) {
914 agp_reg_write((offset >> 2) & 0x7f, value);
915 } else if (offset < 0x200000) {
916 blt_reg_write((offset >> 2) & 0x7f, value);
917 } else if (offset < 0x600000) {
918 register_w_common((offset - 0x200000) >> 2, value);
919 } else if (offset < 0x800000) {
920 texture_w((offset & 0x1fffff) >> 2, value);
921 } else if ((offset < 0xa00000) && (s.model == VOODOO_3)) {
922 texture_w((1 << 19) | ((offset & 0x1fffff) >> 2), value);
923 } else if (offset < 0xc00000) {
924 BX_DEBUG(("reserved write to offset 0x%08x", offset));
925 } else if (offset < 0x1000000) {
926 BX_ERROR(("TODO: YUV planar space write to offset 0x%08x", offset));
927 } else {
928 Bit8u temp = v->fbi.lfb_stride;
929 v->fbi.lfb_stride = 11;
930 if (len == 2) {
931 if ((offset & 3) == 0) {
932 mask = 0x0000ffff;
933 } else {
934 mask = 0xffff0000;
935 }
936 }
937 lfb_w((offset & v->fbi.mask) >> 2, value, mask);
938 v->fbi.lfb_stride = temp;
939 }
940 } else if ((addr & ~0x1ffffff) == pci_bar[1].addr) {
941 if (v->fbi.cmdfifo[0].enabled && (offset >= v->fbi.cmdfifo[0].base) &&
942 (offset < v->fbi.cmdfifo[0].end)) {
943 if (len == 4) {
944 cmdfifo_w(&v->fbi.cmdfifo[0], offset, value);
945 } else {
946 BX_ERROR(("CMDFIFO #0 write with len = %d redirected to LFB", len));
947 mem_write_linear(offset, value, len);
948 }
949 } else if (v->fbi.cmdfifo[1].enabled && (offset >= v->fbi.cmdfifo[1].base) &&
950 (offset < v->fbi.cmdfifo[1].end)) {
951 if (len == 4) {
952 cmdfifo_w(&v->fbi.cmdfifo[1], offset, value);
953 } else {
954 BX_ERROR(("CMDFIFO #1 write with len = %d redirected to LFB", len));
955 mem_write_linear(offset, value, len);
956 }
957 } else {
958 mem_write_linear(offset, value, len);
959 }
960 }
961 }
962
mem_write_linear(Bit32u offset,Bit32u value,unsigned len)963 void bx_banshee_c::mem_write_linear(Bit32u offset, Bit32u value, unsigned len)
964 {
965 Bit8u value8;
966 Bit32u start = v->banshee.io[io_vidDesktopStartAddr];
967 Bit32u pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
968 unsigned i, w, x, y;
969
970 if (offset >= v->fbi.lfb_base) {
971 offset -= v->fbi.lfb_base;
972 pitch *= 128;
973 x = (offset << 0) & ((1 << v->fbi.lfb_stride) - 1);
974 y = (offset >> v->fbi.lfb_stride) & 0x1fff;
975 offset = (v->fbi.lfb_base + y * pitch + x) & v->fbi.mask;
976 } else {
977 offset &= v->fbi.mask;
978 }
979 BX_LOCK(render_mutex);
980 for (i = 0; i < len; i++) {
981 value8 = (value >> (i*8)) & 0xff;
982 v->fbi.ram[offset + i] = value8;
983 }
984 if (offset >= start) {
985 offset -= start;
986 x = (offset % pitch) / (v->banshee.disp_bpp >> 3);
987 y = offset / pitch;
988 w = len / (v->banshee.disp_bpp >> 3);
989 if (w == 0) w = 1;
990 theVoodooVga->redraw_area(x, y, w, 1);
991 }
992 BX_UNLOCK(render_mutex);
993 }
994
agp_reg_read(Bit8u reg)995 Bit32u bx_banshee_c::agp_reg_read(Bit8u reg)
996 {
997 Bit32u result = 0;
998 Bit8u fifo_idx = (reg >= cmdBaseAddr1);
999
1000 switch (reg) {
1001 case cmdBaseAddr0:
1002 case cmdBaseAddr1:
1003 result = (v->fbi.cmdfifo[fifo_idx].base >> 12);
1004 break;
1005 case cmdBump0:
1006 case cmdBump1:
1007 break;
1008 case cmdRdPtrL0:
1009 case cmdRdPtrL1:
1010 result = v->fbi.cmdfifo[fifo_idx].rdptr;
1011 break;
1012 case cmdFifoDepth0:
1013 case cmdFifoDepth1:
1014 result = v->fbi.cmdfifo[fifo_idx].depth;
1015 break;
1016 case cmdHoleCnt0:
1017 case cmdHoleCnt1:
1018 result = v->fbi.cmdfifo[fifo_idx].holes;
1019 break;
1020 case cmdStatus0:
1021 case cmdStatus1:
1022 BX_ERROR(("cmdStatus%d not implemented yet", fifo_idx));
1023 default:
1024 result = v->banshee.agp[reg];
1025 }
1026 BX_DEBUG(("AGP read register 0x%03x (%s) result = 0x%08x", reg<<2,
1027 banshee_agp_reg_name[reg], result));
1028 return result;
1029 }
1030
agp_reg_write(Bit8u reg,Bit32u value)1031 void bx_banshee_c::agp_reg_write(Bit8u reg, Bit32u value)
1032 {
1033 Bit8u fifo_idx = (reg >= cmdBaseAddr1);
1034
1035 BX_DEBUG(("AGP write register 0x%03x (%s) value = 0x%08x", reg<<2,
1036 banshee_agp_reg_name[reg], value));
1037 switch (reg) {
1038 case cmdBaseAddr0:
1039 case cmdBaseAddr1:
1040 BX_LOCK(cmdfifo_mutex);
1041 v->fbi.cmdfifo[fifo_idx].base = (value << 12);
1042 if (fifo_idx == 0) {
1043 v->fbi.cmdfifo[0].end = v->fbi.cmdfifo[0].base +
1044 (((v->banshee.agp[cmdBaseSize0] & 0xff) + 1) << 12);
1045 } else {
1046 v->fbi.cmdfifo[1].end = v->fbi.cmdfifo[1].base +
1047 (((v->banshee.agp[cmdBaseSize1] & 0xff) + 1) << 12);
1048 }
1049 BX_UNLOCK(cmdfifo_mutex);
1050 break;
1051 case cmdBaseSize0:
1052 case cmdBaseSize1:
1053 BX_LOCK(cmdfifo_mutex);
1054 if (fifo_idx == 0) {
1055 v->fbi.cmdfifo[0].end = v->fbi.cmdfifo[0].base + (((value & 0xff) + 1) << 12);
1056 } else {
1057 v->fbi.cmdfifo[1].end = v->fbi.cmdfifo[1].base + (((value & 0xff) + 1) << 12);
1058 }
1059 v->fbi.cmdfifo[fifo_idx].count_holes = (((value >> 10) & 1) == 0);
1060 if ((value >> 9) & 1) {
1061 BX_ERROR(("CMDFIFO in AGP memory not supported yet"));
1062 }
1063 if (v->fbi.cmdfifo[fifo_idx].enabled != ((value >> 8) & 1)) {
1064 v->fbi.cmdfifo[fifo_idx].enabled = ((value >> 8) & 1);
1065 BX_INFO(("CMDFIFO #%d now %sabled", fifo_idx,
1066 v->fbi.cmdfifo[fifo_idx].enabled ? "en" : "dis"));
1067 }
1068 BX_UNLOCK(cmdfifo_mutex);
1069 break;
1070 case cmdBump0:
1071 case cmdBump1:
1072 if (value > 0) {
1073 BX_ERROR(("cmdBump%d not implemented (value = 0x%04x)", fifo_idx, (Bit16u)value));
1074 }
1075 break;
1076 case cmdRdPtrL0:
1077 case cmdRdPtrL1:
1078 BX_LOCK(cmdfifo_mutex);
1079 v->fbi.cmdfifo[fifo_idx].rdptr = value;
1080 BX_UNLOCK(cmdfifo_mutex);
1081 break;
1082 case cmdRdPtrH0:
1083 case cmdRdPtrH1:
1084 if (value > 0) {
1085 BX_ERROR(("cmdRdPtrH%d not supported yet", fifo_idx));
1086 }
1087 break;
1088 case cmdAMin0:
1089 case cmdAMin1:
1090 BX_LOCK(cmdfifo_mutex);
1091 v->fbi.cmdfifo[fifo_idx].amin = value;
1092 BX_UNLOCK(cmdfifo_mutex);
1093 break;
1094 case cmdAMax0:
1095 case cmdAMax1:
1096 BX_LOCK(cmdfifo_mutex);
1097 v->fbi.cmdfifo[fifo_idx].amax = value;
1098 BX_UNLOCK(cmdfifo_mutex);
1099 break;
1100 case cmdFifoDepth0:
1101 case cmdFifoDepth1:
1102 BX_LOCK(cmdfifo_mutex);
1103 v->fbi.cmdfifo[fifo_idx].depth = value & 0xfffff;
1104 BX_UNLOCK(cmdfifo_mutex);
1105 break;
1106 case cmdHoleCnt0:
1107 case cmdHoleCnt1:
1108 if (value > 0) {
1109 BX_ERROR(("cmdHoleCnt%d not supported yet", fifo_idx));
1110 }
1111 break;
1112 }
1113 v->banshee.agp[reg] = value;
1114 }
1115
1116 #define BLT v->banshee.blt
1117
blt_reg_read(Bit8u reg)1118 Bit32u bx_banshee_c::blt_reg_read(Bit8u reg)
1119 {
1120 Bit32u result = 0;
1121
1122 switch (reg) {
1123 case blt_status:
1124 result = register_r(0);
1125 break;
1126 case blt_intrCtrl:
1127 result = register_r(1);
1128 break;
1129 default:
1130 if (reg < 0x20) {
1131 result = BLT.reg[reg];
1132 }
1133 }
1134 if (reg < 0x20) {
1135 BX_DEBUG(("2D read register 0x%03x (%s) result = 0x%08x", reg<<2,
1136 banshee_blt_reg_name[reg], result));
1137 }
1138 return result;
1139 }
1140
blt_reg_write(Bit8u reg,Bit32u value)1141 void bx_banshee_c::blt_reg_write(Bit8u reg, Bit32u value)
1142 {
1143 Bit8u old_cmd;
1144 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
1145
1146 if (reg < 0x20) {
1147 BLT.reg[reg] = value;
1148 BX_DEBUG(("2D write register 0x%03x (%s) value = 0x%08x", reg<<2,
1149 banshee_blt_reg_name[reg], value));
1150 }
1151 switch (reg) {
1152 case blt_intrCtrl:
1153 register_w_common(1, value);
1154 break;
1155 case blt_clip0Min:
1156 BLT.clipx0[0] = BLT.reg[reg] & 0xfff;
1157 BLT.clipy0[0] = (BLT.reg[reg] >> 16) & 0x1fff;
1158 break;
1159 case blt_clip0Max:
1160 BLT.clipx1[0] = BLT.reg[reg] & 0xfff;
1161 BLT.clipy1[0] = (BLT.reg[reg] >> 16) & 0x1fff;
1162 break;
1163 case blt_dstBaseAddr:
1164 BLT.dst_base = BLT.reg[reg] & v->fbi.mask;
1165 BLT.dst_tiled = BLT.reg[reg] >> 31;
1166 if (BLT.dst_tiled) {
1167 BLT.dst_pitch = (BLT.reg[blt_dstFormat] & 0x7f) << 7;
1168 } else {
1169 BLT.dst_pitch = BLT.reg[blt_dstFormat] & 0x3fff;
1170 }
1171 break;
1172 case blt_dstFormat:
1173 BLT.dst_fmt = (BLT.reg[reg] >> 16) & 0x07;
1174 if (BLT.dst_tiled) {
1175 BLT.dst_pitch = (BLT.reg[reg] & 0x7f) << 7;
1176 } else {
1177 BLT.dst_pitch = BLT.reg[reg] & 0x3fff;
1178 }
1179 break;
1180 case blt_srcBaseAddr:
1181 BLT.src_base = BLT.reg[reg] & v->fbi.mask;
1182 BLT.src_tiled = BLT.reg[reg] >> 31;
1183 if (BLT.src_tiled) {
1184 BLT.src_pitch = (BLT.reg[blt_srcFormat] & 0x7f) << 7;
1185 } else {
1186 BLT.src_pitch = BLT.reg[blt_srcFormat] & 0x3fff;
1187 }
1188 break;
1189 case blt_srcFormat:
1190 BLT.src_fmt = (BLT.reg[reg] >> 16) & 0x0f;
1191 BLT.src_swizzle = (BLT.reg[reg] >> 20) & 0x03;
1192 if (BLT.src_tiled) {
1193 BLT.src_pitch = (BLT.reg[reg] & 0x7f) << 7;
1194 } else {
1195 BLT.src_pitch = BLT.reg[reg] & 0x3fff;
1196 }
1197 break;
1198 case blt_pattern0Alias:
1199 BLT.cpat[0][0] = value & 0xff;
1200 BLT.cpat[0][1] = (value >> 8) & 0xff;
1201 BLT.cpat[0][2] = (value >> 16) & 0xff;
1202 BLT.cpat[0][3] = (value >> 24) & 0xff;
1203 break;
1204 case blt_pattern1Alias:
1205 BLT.cpat[1][0] = value & 0xff;
1206 BLT.cpat[1][1] = (value >> 8) & 0xff;
1207 BLT.cpat[1][2] = (value >> 16) & 0xff;
1208 BLT.cpat[1][3] = (value >> 24) & 0xff;
1209 break;
1210 case blt_clip1Min:
1211 BLT.clipx0[1] = BLT.reg[reg] & 0xfff;
1212 BLT.clipy0[1] = (BLT.reg[reg] >> 16) & 0x1fff;
1213 break;
1214 case blt_clip1Max:
1215 BLT.clipx1[1] = BLT.reg[reg] & 0xfff;
1216 BLT.clipy1[1] = (BLT.reg[reg] >> 16) & 0x1fff;
1217 break;
1218 case blt_srcSize:
1219 BLT.src_w = BLT.reg[reg] & 0x1fff;
1220 BLT.src_h = (BLT.reg[reg] >> 16) & 0x1fff;
1221 break;
1222 case blt_srcXY:
1223 BLT.src_x = BLT.reg[reg] & 0x1fff;
1224 BLT.src_y = (BLT.reg[reg] >> 16) & 0x1fff;
1225 break;
1226 case blt_colorBack:
1227 BLT.bgcolor[0] = BLT.reg[reg] & 0xff;
1228 BLT.bgcolor[1] = (BLT.reg[reg] >> 8) & 0xff;
1229 BLT.bgcolor[2] = (BLT.reg[reg] >> 16) & 0xff;
1230 BLT.bgcolor[3] = (BLT.reg[reg] >> 24) & 0xff;
1231 break;
1232 case blt_colorFore:
1233 BLT.fgcolor[0] = BLT.reg[reg] & 0xff;
1234 BLT.fgcolor[1] = (BLT.reg[reg] >> 8) & 0xff;
1235 BLT.fgcolor[2] = (BLT.reg[reg] >> 16) & 0xff;
1236 BLT.fgcolor[3] = (BLT.reg[reg] >> 24) & 0xff;
1237 break;
1238 case blt_dstSize:
1239 BLT.dst_w = BLT.reg[reg] & 0x1fff;
1240 BLT.dst_h = (BLT.reg[reg] >> 16) & 0x1fff;
1241 break;
1242 case blt_dstXY:
1243 if ((BLT.reg[reg] >> 15) & 1) {
1244 BLT.dst_x = (Bit16s)(BLT.reg[reg] & 0xffff);
1245 } else {
1246 BLT.dst_x = BLT.reg[reg] & 0x1fff;
1247 }
1248 if (BLT.reg[reg] >> 31) {
1249 BLT.dst_y = (Bit16s)(BLT.reg[reg] >> 16);
1250 } else {
1251 BLT.dst_y = (BLT.reg[reg] >> 16) & 0x1fff;
1252 }
1253 break;
1254 case blt_command:
1255 old_cmd = BLT.cmd;
1256 BLT.cmd = (value & 0x0f);
1257 BLT.immed = (value >> 8) & 1;
1258 BLT.x_dir = (value >> 14) & 1;
1259 BLT.y_dir = (value >> 15) & 1;
1260 BLT.transp = (value >> 16) & 1;
1261 BLT.patsx = (value >> 17) & 7;
1262 BLT.patsy = (value >> 20) & 7;
1263 BLT.clip_sel = (value >> 23) & 1;
1264 BLT.rop[0] = (value >> 24);
1265 BLT.rop[1] = BLT.reg[blt_rop] & 0xff;
1266 BLT.rop[2] = (BLT.reg[blt_rop] >> 8) & 0xff;
1267 BLT.rop[3] = (BLT.reg[blt_rop] >> 16) & 0xff;
1268 BLT.pattern_blt = (BLT.rop_flags[BLT.rop[0]] & BX_ROP_PATTERN);
1269 if (colorkey_en & 1) {
1270 BLT.pattern_blt |= (BLT.rop_flags[BLT.rop[2]] & BX_ROP_PATTERN);
1271 }
1272 if (colorkey_en & 2) {
1273 BLT.pattern_blt |= (BLT.rop_flags[BLT.rop[1]] & BX_ROP_PATTERN);
1274 }
1275 if (colorkey_en == 3) {
1276 BLT.pattern_blt |= (BLT.rop_flags[BLT.rop[3]] & BX_ROP_PATTERN);
1277 }
1278 if (BLT.x_dir) {
1279 BLT.rop_fn[0] = BLT.rop_handler[1][BLT.rop[0]];
1280 BLT.rop_fn[1] = BLT.rop_handler[1][BLT.rop[1]];
1281 BLT.rop_fn[2] = BLT.rop_handler[1][BLT.rop[2]];
1282 BLT.rop_fn[3] = BLT.rop_handler[1][BLT.rop[3]];
1283 } else {
1284 BLT.rop_fn[0] = BLT.rop_handler[0][BLT.rop[0]];
1285 BLT.rop_fn[1] = BLT.rop_handler[0][BLT.rop[1]];
1286 BLT.rop_fn[2] = BLT.rop_handler[0][BLT.rop[2]];
1287 BLT.rop_fn[3] = BLT.rop_handler[0][BLT.rop[3]];
1288 }
1289 if (BLT.lamem != NULL) {
1290 BX_ERROR(("Writing new command while another one is still pending"));
1291 delete [] BLT.lamem;
1292 BLT.lamem = NULL;
1293 }
1294 if (old_cmd == 8) {
1295 blt_polygon_fill(1);
1296 }
1297 if (BLT.cmd == 8) {
1298 BLT.pgn_init = 0;
1299 }
1300 if (BLT.immed) {
1301 blt_execute();
1302 } else {
1303 blt_launch_area_setup();
1304 }
1305 break;
1306 case blt_commandExtra:
1307 if ((value & 0x04) != 0) {
1308 BX_ERROR(("wait for vsync not supported yet"));
1309 }
1310 break;
1311 default:
1312 if ((reg >= 0x20) && (reg < 0x40)) {
1313 blt_launch_area_write(value);
1314 } else if ((reg >= 0x40) && (reg < 0x80)) {
1315 reg -= 0x40;
1316 BX_DEBUG(("colorPattern write reg 0x%02x: value = 0x%08x", reg, value));
1317 BLT.cpat[reg][0] = value & 0xff;
1318 BLT.cpat[reg][1] = (value >> 8) & 0xff;
1319 BLT.cpat[reg][2] = (value >> 16) & 0xff;
1320 BLT.cpat[reg][3] = (value >> 24) & 0xff;
1321 }
1322 }
1323 }
1324
blt_launch_area_setup()1325 void bx_banshee_c::blt_launch_area_setup()
1326 {
1327 Bit32u pbytes;
1328 Bit8u pxpack, pxsize = 0, pxstart;
1329
1330 BLT.lacnt = 0;
1331 BLT.laidx = 0;
1332 switch (BLT.cmd) {
1333 case 1:
1334 case 2:
1335 case 5:
1336 case 6:
1337 case 7:
1338 case 8:
1339 BLT.lacnt = 1;
1340 break;
1341 case 3:
1342 case 4:
1343 pxpack = (BLT.reg[blt_srcFormat] >> 22) & 3;
1344 if (BLT.src_fmt == 0) {
1345 BLT.h2s_pxstart = BLT.reg[blt_srcXY] & 0x1f;
1346 pbytes = (BLT.dst_w + BLT.h2s_pxstart + 7) >> 3;
1347 } else {
1348 BLT.h2s_pxstart = BLT.reg[blt_srcXY] & 0x03;
1349 if (BLT.src_fmt == 1) {
1350 pxsize = 1;
1351 } else if ((BLT.src_fmt >= 3) && (BLT.src_fmt <= 5)) {
1352 pxsize = BLT.src_fmt - 1;
1353 } else {
1354 BX_ERROR(("Source format %d not handled yet", BLT.src_fmt));
1355 }
1356 pbytes = BLT.dst_w * pxsize + BLT.h2s_pxstart;
1357 }
1358 switch (pxpack) {
1359 case 1:
1360 BLT.h2s_pitch = pbytes;
1361 break;
1362 case 2:
1363 BLT.h2s_pitch = (pbytes + 1) & ~1;
1364 break;
1365 case 3:
1366 BLT.h2s_pitch = (pbytes + 3) & ~3;
1367 break;
1368 default:
1369 BLT.h2s_pitch = (pbytes + 3) & ~3;
1370 pbytes = 0;
1371 pxstart = BLT.h2s_pxstart;
1372 if (BLT.src_fmt == 0) {
1373 for (int i = 0; i < BLT.dst_h; i++) {
1374 pbytes += ((((BLT.dst_w + pxstart + 7) >> 3) + 3) & ~3);
1375 pxstart += (Bit8u)(BLT.reg[blt_srcFormat] << 3);
1376 pxstart &= 0x1f;
1377 }
1378 } else {
1379 for (int i = 0; i < BLT.dst_h; i++) {
1380 pbytes += ((BLT.dst_w * pxsize + pxstart + 3) & ~3);
1381 pxstart += (Bit8u)BLT.reg[blt_srcFormat];
1382 pxstart &= 0x03;
1383 }
1384 }
1385 BLT.lacnt = pbytes >> 2;
1386 }
1387 if (pxpack != 0) {
1388 BLT.lacnt = (BLT.h2s_pitch * BLT.dst_h + 3) >> 2;
1389 }
1390 BLT.lamem = new Bit8u[BLT.lacnt * 4];
1391 break;
1392 default:
1393 BX_ERROR(("launchArea setup: command %d not handled yet", BLT.cmd));
1394 }
1395 }
1396
blt_launch_area_write(Bit32u value)1397 void bx_banshee_c::blt_launch_area_write(Bit32u value)
1398 {
1399 if (BLT.lacnt > 0) {
1400 BX_DEBUG(("launchArea write: value = 0x%08x", value));
1401 if (BLT.lamem != NULL) {
1402 if (BLT.src_swizzle & 1) {
1403 value = bx_bswap32(value);
1404 }
1405 if (BLT.src_swizzle & 2) {
1406 value = (value >> 16) | (value << 16);
1407 }
1408 BLT.lamem[BLT.laidx++] = (value & 0xff);
1409 BLT.lamem[BLT.laidx++] = ((value >> 8) & 0xff);
1410 BLT.lamem[BLT.laidx++] = ((value >> 16) & 0xff);
1411 BLT.lamem[BLT.laidx++] = ((value >> 24) & 0xff);
1412 } else if ((BLT.cmd == 1) || (BLT.cmd == 2)) {
1413 BLT.reg[blt_srcXY] = value;
1414 BLT.src_x = value & 0x1fff;
1415 BLT.src_y = (value >> 16) & 0x1fff;
1416 } if ((BLT.cmd >= 5) && (BLT.cmd <= 7)) {
1417 BLT.reg[blt_dstXY] = value;
1418 if ((value >> 15) & 1) {
1419 BLT.dst_x = (Bit16s)(value & 0xffff);
1420 } else {
1421 BLT.dst_x = value & 0x1fff;
1422 }
1423 if (value >> 31) {
1424 BLT.dst_y = (Bit16s)(value >> 16);
1425 } else {
1426 BLT.dst_y = (value >> 16) & 0x1fff;
1427 }
1428 } if (BLT.cmd == 8) {
1429 BLT.pgn_val = value;
1430 }
1431 if (--BLT.lacnt == 0) {
1432 blt_execute();
1433 }
1434 } else {
1435 BX_ERROR(("launchArea write: ignoring extra data"));
1436 }
1437 }
1438
blt_execute()1439 void bx_banshee_c::blt_execute()
1440 {
1441 Bit16u x, y;
1442
1443 switch (BLT.cmd) {
1444 case 0: // NOP
1445 break;
1446 case 1:
1447 BLT.busy = 1;
1448 if (BLT.pattern_blt) {
1449 blt_screen_to_screen_pattern();
1450 } else {
1451 blt_screen_to_screen();
1452 }
1453 if (!BLT.immed) {
1454 BLT.lacnt = 1;
1455 }
1456 break;
1457 case 2:
1458 if (BLT.pattern_blt) {
1459 BX_ERROR(("TODO: 2D Screen to screen stretch pattern blt"));
1460 } else {
1461 BLT.busy = 1;
1462 blt_screen_to_screen_stretch();
1463 }
1464 break;
1465 case 3:
1466 case 4:
1467 if (!BLT.immed) {
1468 if (BLT.cmd == 3) {
1469 BLT.busy = 1;
1470 if (BLT.pattern_blt) {
1471 blt_host_to_screen_pattern();
1472 } else {
1473 blt_host_to_screen();
1474 }
1475 } else {
1476 BX_ERROR(("TODO: 2D Host to screen stretch blt"));
1477 }
1478 delete [] BLT.lamem;
1479 BLT.lamem = NULL;
1480 } else {
1481 BX_ERROR(("Host to screen blt: immediate execution not supported"));
1482 }
1483 break;
1484 case 5:
1485 BLT.busy = 1;
1486 if (BLT.pattern_blt) {
1487 if ((BLT.reg[blt_command] >> 13) & 1) {
1488 blt_pattern_fill_mono();
1489 } else {
1490 blt_pattern_fill_color();
1491 }
1492 } else {
1493 blt_rectangle_fill();
1494 }
1495 if (!BLT.immed) {
1496 BLT.lacnt = 1;
1497 }
1498 break;
1499 case 6:
1500 case 7:
1501 BLT.busy = 1;
1502 blt_line(BLT.cmd == 7);
1503 if (!BLT.immed) {
1504 BLT.lacnt = 1;
1505 }
1506 break;
1507 case 8:
1508 if (!BLT.immed) {
1509 if (!BLT.pgn_init) {
1510 BLT.pgn_l0x = BLT.pgn_l1x = BLT.src_x;
1511 BLT.pgn_l0y = BLT.pgn_l1y = BLT.src_y;
1512 BLT.pgn_r0x = BLT.pgn_r1x = BLT.dst_x;
1513 BLT.pgn_r0y = BLT.pgn_r1y = BLT.dst_y;
1514 BLT.pgn_init = 1;
1515 }
1516 x = (Bit16u)BLT.pgn_val;
1517 y = (Bit16u)(BLT.pgn_val >> 16);
1518 if (BLT.pgn_r1y >= BLT.pgn_l1y) {
1519 BLT.pgn_l1x = x;
1520 BLT.pgn_l1y = y;
1521 if (y == BLT.pgn_l0y) {
1522 BLT.pgn_l0x = x;
1523 }
1524 } else {
1525 BLT.pgn_r1x = x;
1526 BLT.pgn_r1y = y;
1527 if (y == BLT.pgn_r0y) {
1528 BLT.pgn_r0x = x;
1529 }
1530 }
1531 blt_polygon_fill(0);
1532 } else {
1533 BLT.reg[blt_dstXY] = BLT.reg[blt_srcXY];
1534 BLT.immed = 0;
1535 }
1536 BLT.lacnt = 1;
1537 break;
1538 case 13:
1539 BX_ERROR(("TODO: 2D Write Sgram Mode register"));
1540 break;
1541 case 14:
1542 BX_ERROR(("TODO: 2D Write Sgram Mask register"));
1543 break;
1544 case 15:
1545 BX_ERROR(("TODO: 2D Write Sgram Color register"));
1546 break;
1547 default:
1548 BX_ERROR(("Unknown BitBlt command"));
1549 }
1550 }
1551
blt_complete()1552 void bx_banshee_c::blt_complete()
1553 {
1554 Bit32u vstart = v->banshee.io[io_vidDesktopStartAddr] & v->fbi.mask;
1555 Bit16u vpitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
1556 Bit8u vpxsize = (v->banshee.disp_bpp >> 3);
1557 Bit32u dstart = BLT.dst_base;
1558 Bit16u dpitch = BLT.dst_pitch;
1559 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
1560 Bit32u cmd = BLT.reg[blt_command];
1561 bool xinc = (cmd >> 10) & 1;
1562 bool yinc = (cmd >> 11) & 1;
1563 int x, y, w, h;
1564
1565 if (v->banshee.desktop_tiled) {
1566 vpitch *= 128;
1567 }
1568 if ((dstart == vstart) && (dpitch == vpitch) && (dpxsize == vpxsize)) {
1569 if (BLT.cmd < 6) {
1570 if (BLT.x_dir) {
1571 x = BLT.dst_x + 1 - BLT.dst_w;
1572 } else {
1573 x = BLT.dst_x;
1574 }
1575 if (BLT.y_dir) {
1576 y = BLT.dst_y + 1 - BLT.dst_h;
1577 } else {
1578 y = BLT.dst_y;
1579 }
1580 w = BLT.dst_w;
1581 h = BLT.dst_h;
1582 } else {
1583 if (BLT.src_x < BLT.dst_x) {
1584 x = BLT.src_x;
1585 w = BLT.dst_x - BLT.src_x + 1;
1586 } else {
1587 x = BLT.dst_x;
1588 w = BLT.src_x - BLT.dst_x + 1;
1589 }
1590 if (BLT.src_y < BLT.dst_y) {
1591 y = BLT.src_y;
1592 h = BLT.dst_y - BLT.src_y + 1;
1593 } else {
1594 y = BLT.dst_y;
1595 h = BLT.src_y - BLT.dst_y + 1;
1596 }
1597 }
1598 theVoodooVga->redraw_area(x, y, w, h);
1599 }
1600 if (xinc) {
1601 BLT.dst_x += BLT.dst_w;
1602 BLT.reg[blt_dstXY] &= ~0xffff;
1603 BLT.reg[blt_dstXY] |= BLT.dst_x;
1604 }
1605 if (yinc) {
1606 BLT.dst_y += BLT.dst_h;
1607 BLT.reg[blt_dstXY] &= 0xffff;
1608 BLT.reg[blt_dstXY] |= (BLT.dst_y << 16);
1609 }
1610 BLT.busy = 0;
1611 }
1612
blt_apply_clipwindow(int * x0,int * y0,int * x1,int * y1,int * w,int * h)1613 bool bx_banshee_c::blt_apply_clipwindow(int *x0, int *y0, int *x1, int *y1, int *w, int *h)
1614 {
1615 int cx0, cx1, cy0, cy1, xd, yd;
1616
1617 cx0 = BLT.clipx0[BLT.clip_sel];
1618 cy0 = BLT.clipy0[BLT.clip_sel];
1619 cx1 = BLT.clipx1[BLT.clip_sel];
1620 cy1 = BLT.clipy1[BLT.clip_sel];
1621 if (BLT.x_dir) {
1622 xd = *x1 - cx1 + 1;
1623 if (xd > 0) {
1624 *w -= xd;
1625 *x1 = cx1 - 1;
1626 if (x0 != NULL) *x0 -= xd;
1627 }
1628 xd = cx0 - (*x1 - *w + 1);
1629 if (xd > 0) {
1630 *w -= xd;
1631 }
1632 } else {
1633 xd = cx0 - *x1;
1634 if (xd > 0) {
1635 *w -= xd;
1636 *x1 = cx0;
1637 if (x0 != NULL) *x0 += xd;
1638 }
1639 xd = *x1 + *w - cx1;
1640 if (xd > 0) {
1641 *w -= xd;
1642 }
1643 }
1644 if (BLT.y_dir) {
1645 yd = *y1 - cy1 + 1;
1646 if (yd > 0) {
1647 *h -= yd;
1648 *y1 = cy1 - 1;
1649 if (y0 != NULL) *y0 -= xd;
1650 }
1651 yd = cy0 - (*y1 - *h + 1);
1652 if (yd > 0) {
1653 *h -= xd;
1654 }
1655 } else {
1656 yd = cy0 - *y1;
1657 if (yd > 0) {
1658 *h -= yd;
1659 *y1 = cy0;
1660 if (y0 != NULL) *y0 += yd;
1661 }
1662 yd = *y1 + *h - cy1;
1663 if (yd > 0) {
1664 *h -= yd;
1665 }
1666 }
1667 return ((*w > 0) && (*h > 0));
1668 }
1669
blt_clip_check(int x,int y)1670 bool bx_banshee_c::blt_clip_check(int x, int y)
1671 {
1672 if ((x >= BLT.clipx0[BLT.clip_sel]) && (x < BLT.clipx1[BLT.clip_sel]) &&
1673 (y >= BLT.clipy0[BLT.clip_sel]) && (y < BLT.clipy1[BLT.clip_sel])) {
1674 return true;
1675 }
1676 return false;
1677 }
1678
blt_colorkey_check(Bit8u * ptr,Bit8u pxsize,bool dst)1679 Bit8u bx_banshee_c::blt_colorkey_check(Bit8u *ptr, Bit8u pxsize, bool dst)
1680 {
1681 Bit8u pass = 0;
1682 Bit32u color, cmin, cmax;
1683 Bit8u r, g, b, rmin, rmax, gmin, gmax, bmin, bmax;
1684
1685 if (!dst) {
1686 cmin = BLT.reg[blt_srcColorkeyMin];
1687 cmax = BLT.reg[blt_srcColorkeyMax];
1688 } else {
1689 cmin = BLT.reg[blt_dstColorkeyMin];
1690 cmax = BLT.reg[blt_dstColorkeyMax];
1691 }
1692 if (pxsize == 1) {
1693 pass = ((*ptr >= (Bit8u)cmin) && (*ptr <= (Bit8u)cmax));
1694 } else {
1695 if (pxsize == 2) {
1696 color = *ptr;
1697 color |= *(ptr + 1) << 8;
1698 r = (color >> 11);
1699 g = (color >> 5) & 0x3f;
1700 b = color & 0x1f;
1701 rmin = (cmin >> 11) & 0x1f;
1702 rmax = (cmax >> 11) & 0x1f;
1703 gmin = (cmin >> 5) & 0x3f;
1704 gmax = (cmax >> 5) & 0x3f;
1705 bmin = cmin & 0x1f;
1706 bmax = cmax & 0x1f;
1707 } else {
1708 color = *ptr;
1709 color |= *(ptr + 1) << 8;
1710 color |= *(ptr + 2) << 16;
1711 r = (color >> 16);
1712 g = (color >> 8) & 0xff;
1713 b = color & 0xff;
1714 rmin = (cmin >> 16) & 0xff;
1715 rmax = (cmax >> 16) & 0xff;
1716 gmin = (cmin >> 8) & 0xff;
1717 gmax = (cmax >> 8) & 0xff;
1718 bmin = cmin & 0xff;
1719 bmax = cmax & 0xff;
1720 }
1721 pass = ((r >= rmin) && (r <= rmax) && (g >= gmin) && (g <= gmax) &&
1722 (b >= bmin) && (b <= bmax));
1723 }
1724 if (!dst) pass <<= 1;
1725 return pass;
1726 }
1727
blt_rectangle_fill()1728 void bx_banshee_c::blt_rectangle_fill()
1729 {
1730 Bit32u dpitch = BLT.dst_pitch;
1731 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
1732 Bit8u *dst_ptr, *dst_ptr1;
1733 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
1734 Bit8u rop = 0;
1735 int dx, dy, w, h, x, y;
1736
1737 dx = BLT.dst_x;
1738 dy = BLT.dst_y;
1739 w = BLT.dst_w;
1740 h = BLT.dst_h;
1741 BX_DEBUG(("Rectangle fill: %d x %d ROP0 %02X", w, h, BLT.rop[0]));
1742 if (!blt_apply_clipwindow(NULL, NULL, &dx, &dy, &w, &h)) {
1743 BLT.busy = 0;
1744 return;
1745 }
1746 BX_LOCK(render_mutex);
1747 dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + dx * dpxsize];
1748 for (y = 0; y < h; y++) {
1749 dst_ptr1 = dst_ptr;
1750 for (x = 0; x < w; x++) {
1751 if (colorkey_en & 2) {
1752 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
1753 }
1754 BLT.rop_fn[rop](dst_ptr1, BLT.fgcolor, dpitch, dpxsize, dpxsize, 1);
1755 dst_ptr1 += dpxsize;
1756 }
1757 dst_ptr += dpitch;
1758 }
1759 blt_complete();
1760 BX_UNLOCK(render_mutex);
1761 }
1762
blt_pattern_fill_mono()1763 void bx_banshee_c::blt_pattern_fill_mono()
1764 {
1765 Bit32u dpitch = BLT.dst_pitch;
1766 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
1767 Bit8u *pat_ptr = &BLT.cpat[0][0];
1768 Bit8u *dst_ptr, *dst_ptr1, *pat_ptr1;
1769 bool patrow0 = (BLT.reg[blt_commandExtra] & 0x08) > 0;
1770 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
1771 Bit8u rop = 0;
1772 Bit8u *color;
1773 int dx, dy, w, h, x, y;
1774 Bit8u mask;
1775 bool set;
1776
1777 dx = BLT.dst_x;
1778 dy = BLT.dst_y;
1779 w = BLT.dst_w;
1780 h = BLT.dst_h;
1781 BX_DEBUG(("Pattern fill mono: %d x %d ROP0 %02X", w, h, BLT.rop[0]));
1782 if (!blt_apply_clipwindow(NULL, NULL, &dx, &dy, &w, &h)) {
1783 BLT.busy = 0;
1784 return;
1785 }
1786 BX_LOCK(render_mutex);
1787 dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + dx * dpxsize];
1788 for (y = dy; y < (dy + h); y++) {
1789 dst_ptr1 = dst_ptr;
1790 if (!patrow0) {
1791 pat_ptr1 = pat_ptr + ((y + BLT.patsy) & 7);
1792 } else {
1793 pat_ptr1 = pat_ptr;
1794 }
1795 for (x = dx; x < (dx + w); x++) {
1796 mask = 0x80 >> ((x + BLT.patsx) & 7);
1797 set = (*pat_ptr1 & mask) > 0;
1798 if (set) {
1799 color = &BLT.fgcolor[0];
1800 } else {
1801 color = &BLT.bgcolor[0];
1802 }
1803 if ((set) || !BLT.transp) {
1804 if (colorkey_en & 2) {
1805 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
1806 }
1807 BLT.rop_fn[rop](dst_ptr1, color, dpitch, dpxsize, dpxsize, 1);
1808 }
1809 dst_ptr1 += dpxsize;
1810 }
1811 dst_ptr += dpitch;
1812 }
1813 blt_complete();
1814 BX_UNLOCK(render_mutex);
1815 }
1816
blt_pattern_fill_color()1817 void bx_banshee_c::blt_pattern_fill_color()
1818 {
1819 Bit32u dpitch = BLT.dst_pitch;
1820 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
1821 Bit8u *pat_ptr = &BLT.cpat[0][0];
1822 Bit8u *dst_ptr, *dst_ptr1, *pat_ptr1, *pat_ptr2;
1823 bool patrow0 = (BLT.reg[blt_commandExtra] & 0x08) > 0;
1824 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
1825 Bit8u rop = 0;
1826 int dx, dy, w, h, x, y;
1827
1828 dx = BLT.dst_x;
1829 dy = BLT.dst_y;
1830 w = BLT.dst_w;
1831 h = BLT.dst_h;
1832 BX_DEBUG(("Pattern fill color: %d x %d ROP0 %02X", w, h, BLT.rop[0]));
1833 if (!blt_apply_clipwindow(NULL, NULL, &dx, &dy, &w, &h)) {
1834 BLT.busy = 0;
1835 return;
1836 }
1837 BX_LOCK(render_mutex);
1838 dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + dx * dpxsize];
1839 for (y = dy; y < (dy + h); y++) {
1840 dst_ptr1 = dst_ptr;
1841 if (!patrow0) {
1842 pat_ptr1 = pat_ptr + ((y + BLT.patsy) & 7) * dpxsize * 8;
1843 } else {
1844 pat_ptr1 = pat_ptr;
1845 }
1846 for (x = dx; x < (dx + w); x++) {
1847 pat_ptr2 = pat_ptr1 + ((x + BLT.patsx) & 7) * dpxsize;
1848 if (colorkey_en & 2) {
1849 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
1850 }
1851 BLT.rop_fn[rop](dst_ptr1, pat_ptr2, dpitch, dpxsize, dpxsize, 1);
1852 dst_ptr1 += dpxsize;
1853 }
1854 dst_ptr += dpitch;
1855 }
1856 blt_complete();
1857 BX_UNLOCK(render_mutex);
1858 }
1859
blt_screen_to_screen()1860 void bx_banshee_c::blt_screen_to_screen()
1861 {
1862 Bit8u *src_ptr = &v->fbi.ram[BLT.src_base];
1863 Bit8u *dst_ptr, *dst_ptr1, *src_ptr1;
1864 Bit8u pxpack = (BLT.reg[blt_srcFormat] >> 22) & 3;
1865 int dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
1866 Bit8u *color;
1867 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
1868 int spitch;
1869 int dpitch = BLT.dst_pitch;
1870 int ncols, nrows, dx, dy, sx, sy, w, h;
1871 Bit8u smask, rop = 0;
1872 bool set;
1873
1874 sx = BLT.src_x;
1875 sy = BLT.src_y;
1876 dx = BLT.dst_x;
1877 dy = BLT.dst_y;
1878 w = BLT.dst_w;
1879 h = BLT.dst_h;
1880 BX_DEBUG(("Screen to screen blt: %d x %d ROP0 %02X", w, h, BLT.rop[0]));
1881 if ((BLT.src_fmt != 0) && (BLT.dst_fmt != BLT.src_fmt)) {
1882 BX_ERROR(("Pixel format conversion not supported yet"));
1883 }
1884 if (!blt_apply_clipwindow(&sx, &sy, &dx, &dy, &w, &h)) {
1885 BLT.busy = 0;
1886 return;
1887 }
1888 BX_LOCK(render_mutex);
1889 if ((BLT.src_fmt == 0) && (pxpack == 1)) {
1890 spitch = (BLT.dst_w + 7) / 8;
1891 } else {
1892 spitch = BLT.src_pitch;
1893 }
1894 dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + dx * dpxsize];
1895 if (BLT.x_dir) {
1896 dpxsize *= -1;
1897 }
1898 if (BLT.y_dir) {
1899 spitch *= -1;
1900 dpitch *= -1;
1901 }
1902 if ((BLT.src_fmt == 0) && (pxpack == 1)) {
1903 src_ptr += (sy * abs(spitch) + sx / 8);
1904 nrows = h;
1905 do {
1906 src_ptr1 = src_ptr;
1907 dst_ptr1 = dst_ptr;
1908 smask = 0x80 >> (sx & 7);
1909 ncols = w;
1910 do {
1911 set = (*src_ptr1 & smask) > 0;
1912 if (set) {
1913 color = &BLT.fgcolor[0];
1914 } else {
1915 color = &BLT.bgcolor[0];
1916 }
1917 if (set || !BLT.transp) {
1918 if (colorkey_en & 2) {
1919 rop = blt_colorkey_check(dst_ptr1, abs(dpxsize), 1);
1920 }
1921 BLT.rop_fn[rop](dst_ptr1, color, dpitch, dpxsize, abs(dpxsize), 1);
1922 }
1923 smask >>= 1;
1924 if (smask == 0) {
1925 src_ptr1++;
1926 smask = 0x80;
1927 }
1928 dst_ptr1 += dpxsize;
1929 } while (--ncols);
1930 src_ptr += spitch;
1931 dst_ptr += dpitch;
1932 } while (--nrows);
1933 } else if (colorkey_en > 0) {
1934 src_ptr += (sy * abs(spitch) + sx * abs(dpxsize));
1935 nrows = h;
1936 do {
1937 src_ptr1 = src_ptr;
1938 dst_ptr1 = dst_ptr;
1939 ncols = w;
1940 do {
1941 if (colorkey_en & 1) {
1942 rop = blt_colorkey_check(src_ptr1, abs(dpxsize), 0);
1943 }
1944 if (colorkey_en & 2) {
1945 rop |= blt_colorkey_check(dst_ptr1, abs(dpxsize), 1);
1946 }
1947 BLT.rop_fn[rop](dst_ptr1, src_ptr1, dpitch, spitch, abs(dpxsize), 1);
1948 src_ptr1 += dpxsize;
1949 dst_ptr1 += dpxsize;
1950 } while (--ncols);
1951 src_ptr += spitch;
1952 dst_ptr += dpitch;
1953 } while (--nrows);
1954 } else {
1955 src_ptr += (sy * abs(spitch) + sx * abs(dpxsize));
1956 BLT.rop_fn[0](dst_ptr, src_ptr, dpitch, spitch, w * abs(dpxsize), h);
1957 }
1958 blt_complete();
1959 BX_UNLOCK(render_mutex);
1960 }
1961
blt_screen_to_screen_pattern()1962 void bx_banshee_c::blt_screen_to_screen_pattern()
1963 {
1964 Bit8u *dst_ptr, *dst_ptr1, *src_ptr, *src_ptr1;
1965 Bit8u *pat_ptr = &BLT.cpat[0][0], *pat_ptr1, *pat_ptr2 = NULL;
1966 int dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
1967 int spitch = BLT.src_pitch;
1968 int dpitch = BLT.dst_pitch;
1969 bool patmono = (BLT.reg[blt_command] >> 13) & 1;
1970 bool patrow0 = (BLT.reg[blt_commandExtra] & 0x08) > 0;
1971 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
1972 Bit8u *patcolor;
1973 int ncols, nrows, dx, dy, x, sx, sy, w, h;
1974 Bit8u pmask = 0, rop = 0, patline;
1975 bool set;
1976
1977 sx = BLT.src_x;
1978 sy = BLT.src_y;
1979 dx = BLT.dst_x;
1980 dy = BLT.dst_y;
1981 w = BLT.dst_w;
1982 h = BLT.dst_h;
1983 BX_DEBUG(("Screen to screen pattern blt: %d x %d ROP0 %02X", w, h, BLT.rop[0]));
1984 if (BLT.dst_fmt != BLT.src_fmt) {
1985 BX_ERROR(("Pixel format conversion not supported yet"));
1986 }
1987 if (!blt_apply_clipwindow(&sx, &sy, &dx, &dy, &w, &h)) {
1988 BLT.busy = 0;
1989 return;
1990 }
1991 BX_LOCK(render_mutex);
1992 src_ptr = &v->fbi.ram[BLT.src_base + sy * spitch + sx * dpxsize];
1993 dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + dx * dpxsize];
1994 if (BLT.x_dir) {
1995 dpxsize *= -1;
1996 }
1997 if (BLT.y_dir) {
1998 spitch *= -1;
1999 dpitch *= -1;
2000 }
2001 nrows = h;
2002 do {
2003 src_ptr1 = src_ptr;
2004 dst_ptr1 = dst_ptr;
2005 if (!patrow0) {
2006 patline = (dy + BLT.patsy) & 7;
2007 if (patmono) {
2008 pat_ptr1 = pat_ptr + patline;
2009 } else {
2010 pat_ptr1 = pat_ptr + patline * dpxsize * 8;
2011 }
2012 } else {
2013 pat_ptr1 = pat_ptr;
2014 }
2015 x = dx;
2016 ncols = w;
2017 do {
2018 if (patmono) {
2019 pmask = 0x80 >> ((x + BLT.patsx) & 7);
2020 set = (*pat_ptr & pmask) > 0;
2021 if (set) {
2022 patcolor = &BLT.fgcolor[0];
2023 } else {
2024 patcolor = &BLT.bgcolor[0];
2025 }
2026 if (set || !BLT.transp) {
2027 if (colorkey_en & 2) {
2028 rop = blt_colorkey_check(dst_ptr1, abs(dpxsize), 1);
2029 }
2030 bx_ternary_rop(BLT.rop[rop], dst_ptr1, src_ptr1, patcolor, abs(dpxsize));
2031 }
2032 } else {
2033 pat_ptr2 = pat_ptr1 + ((x + BLT.patsx) & 7) * dpxsize;
2034 patcolor = pat_ptr2;
2035 if (colorkey_en & 1) {
2036 rop = blt_colorkey_check(src_ptr1, abs(dpxsize), 0);
2037 }
2038 if (colorkey_en & 2) {
2039 rop |= blt_colorkey_check(dst_ptr1, abs(dpxsize), 1);
2040 }
2041 bx_ternary_rop(BLT.rop[rop], dst_ptr1, src_ptr1, patcolor, abs(dpxsize));
2042 }
2043 src_ptr1 += dpxsize;
2044 dst_ptr1 += dpxsize;
2045 x++;
2046 } while (--ncols);
2047 src_ptr += spitch;
2048 dst_ptr += dpitch;
2049 if (BLT.y_dir) {
2050 dy--;
2051 } else {
2052 dy++;
2053 }
2054 } while (--nrows);
2055 blt_complete();
2056 BX_UNLOCK(render_mutex);
2057 }
2058
blt_screen_to_screen_stretch()2059 void bx_banshee_c::blt_screen_to_screen_stretch()
2060 {
2061 Bit8u *dst_ptr, *dst_ptr1, *src_ptr, *src_ptr1;
2062 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
2063 int spitch = BLT.src_pitch;
2064 int dpitch = BLT.dst_pitch;
2065 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
2066 Bit8u rop = 0;
2067 int nrows, stepy;
2068 int dx, dy, x2, x3, y2, y3, w0, h0, w1, h1;
2069 double fx, fy;
2070
2071 w0 = BLT.src_w;
2072 h0 = BLT.src_h;
2073 w1 = BLT.dst_w;
2074 h1 = BLT.dst_h;
2075 BX_DEBUG(("Screen to screen stretch blt: : %d x %d -> %d x %d ROP0 %02X",
2076 w0, h0, w1, h1, BLT.rop[0]));
2077 if (BLT.dst_fmt != BLT.src_fmt) {
2078 BX_ERROR(("Pixel format conversion not supported yet"));
2079 }
2080 BX_LOCK(render_mutex);
2081 dy = BLT.dst_y;
2082 dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + BLT.dst_x * dpxsize];
2083 src_ptr = &v->fbi.ram[BLT.src_base + BLT.src_y * spitch + BLT.src_x * dpxsize];
2084 if (BLT.y_dir) {
2085 spitch *= -1;
2086 dpitch *= -1;
2087 stepy = -1;
2088 } else {
2089 stepy = 1;
2090 }
2091 fx = (double)w1 / (double)w0;
2092 fy = (double)h1 / (double)h0;
2093 y2 = 0;
2094 nrows = h1;
2095 do {
2096 dst_ptr1 = dst_ptr;
2097 x2 = 0;
2098 for (dx = BLT.dst_x; dx < (BLT.dst_x + w1); dx++) {
2099 if (blt_clip_check(dx, dy)) {
2100 x3 = (int)((double)x2 / fx + 0.49f);
2101 y3 = (int)((double)y2 / fy + 0.49f);
2102 src_ptr1 = src_ptr + (y3 * spitch + x3 * dpxsize);
2103 if (colorkey_en & 1) {
2104 rop = blt_colorkey_check(src_ptr1, dpxsize, 0);
2105 }
2106 if (colorkey_en & 2) {
2107 rop |= blt_colorkey_check(dst_ptr1, dpxsize, 1);
2108 }
2109 BLT.rop_fn[rop](dst_ptr1, src_ptr1, dpitch, dpxsize, dpxsize, 1);
2110 }
2111 dst_ptr1 += dpxsize;
2112 x2++;
2113 }
2114 dst_ptr += dpitch;
2115 dy += stepy;
2116 y2++;
2117 } while (--nrows);
2118 blt_complete();
2119 BX_UNLOCK(render_mutex);
2120 }
2121
blt_host_to_screen()2122 void bx_banshee_c::blt_host_to_screen()
2123 {
2124 Bit32u dpitch = BLT.dst_pitch;
2125 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
2126 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
2127 Bit8u rop = 0;
2128 Bit8u *src_ptr = &BLT.lamem[0];
2129 Bit8u *dst_ptr, *dst_ptr1, *src_ptr1;
2130 Bit16u spitch = BLT.h2s_pitch;
2131 Bit8u srcfmt = BLT.src_fmt;
2132 Bit8u pxpack = (BLT.reg[blt_srcFormat] >> 22) & 3;
2133 Bit8u spxsize = 0, r = 0, g = 0, b = 0;
2134 Bit8u scolor[4];
2135 Bit8u *color;
2136 int nrows, x, y, w, h, xs;
2137 Bit8u smask = 0;
2138 bool set;
2139
2140 w = BLT.dst_w;
2141 h = BLT.dst_h;
2142 BX_DEBUG(("Host to screen blt: %d x %d ROP0 %02X", w, h, BLT.rop[0]));
2143 if ((pxconv_table[srcfmt] & (1 << BLT.dst_fmt)) == 0) {
2144 BX_ERROR(("Pixel format conversion not supported"));
2145 }
2146 BX_LOCK(render_mutex);
2147 if (srcfmt > 0) {
2148 if (srcfmt == 1) {
2149 spxsize = 1;
2150 } else if ((srcfmt >= 3) && (srcfmt <= 5)) {
2151 spxsize = srcfmt - 1;
2152 } else {
2153 spxsize = 4;
2154 }
2155 }
2156 y = BLT.dst_y;
2157 xs = BLT.h2s_pxstart;
2158 dst_ptr = &v->fbi.ram[BLT.dst_base + y * dpitch + BLT.dst_x * dpxsize];
2159 nrows = h;
2160 do {
2161 if (srcfmt == 0) {
2162 src_ptr1 = src_ptr + (xs >> 3);
2163 smask = 0x80 >> (xs & 7);
2164 } else {
2165 src_ptr1 = src_ptr + xs;
2166 }
2167 dst_ptr1 = dst_ptr;
2168 for (x = BLT.dst_x; x < (BLT.dst_x + w); x++) {
2169 if (blt_clip_check(x, y)) {
2170 if (srcfmt == 0) {
2171 set = (*src_ptr1 & smask) > 0;
2172 if (set) {
2173 color = &BLT.fgcolor[0];
2174 } else {
2175 color = &BLT.bgcolor[0];
2176 }
2177 if (set || !BLT.transp) {
2178 if (colorkey_en & 2) {
2179 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
2180 }
2181 BLT.rop_fn[rop](dst_ptr1, color, dpitch, dpxsize, dpxsize, 1);
2182 }
2183 } else {
2184 if (colorkey_en & 1) {
2185 rop = blt_colorkey_check(src_ptr1, spxsize, 0);
2186 }
2187 if (BLT.dst_fmt != srcfmt) {
2188 if ((srcfmt == 4) || (srcfmt == 5)) {
2189 b = src_ptr1[0];
2190 g = src_ptr1[1];
2191 r = src_ptr1[2];
2192 } else if (srcfmt == 3) {
2193 b = src_ptr1[0] << 3;
2194 g = ((src_ptr1[1] & 0x07) << 5) | ((src_ptr1[0] & 0xe0) >> 3);
2195 r = src_ptr1[1] & 0xf8;
2196 }
2197 if (dpxsize == 2) {
2198 scolor[0] = (b >> 3) | ((g & 0x1c) << 3);
2199 scolor[1] = (g >> 5) | (r & 0xf8);
2200 if (colorkey_en & 2) {
2201 rop |= blt_colorkey_check(dst_ptr1, dpxsize, 1);
2202 }
2203 BLT.rop_fn[rop](dst_ptr1, scolor, dpitch, dpxsize, dpxsize, 1);
2204 } else if ((dpxsize == 3) || (dpxsize == 4)) {
2205 scolor[0] = b;
2206 scolor[1] = g;
2207 scolor[2] = r;
2208 scolor[3] = 0;
2209 if (colorkey_en & 2) {
2210 rop |= blt_colorkey_check(dst_ptr1, dpxsize, 1);
2211 }
2212 BLT.rop_fn[rop](dst_ptr1, scolor, dpitch, dpxsize, dpxsize, 1);
2213 }
2214 } else {
2215 if (colorkey_en & 2) {
2216 rop |= blt_colorkey_check(dst_ptr1, dpxsize, 1);
2217 }
2218 BLT.rop_fn[rop](dst_ptr1, src_ptr1, dpitch, dpxsize, dpxsize, 1);
2219 }
2220 }
2221 }
2222 if (srcfmt == 0) {
2223 smask >>= 1;
2224 if (smask == 0) {
2225 src_ptr1++;
2226 smask = 0x80;
2227 }
2228 } else {
2229 src_ptr1 += spxsize;
2230 }
2231 dst_ptr1 += dpxsize;
2232 }
2233 src_ptr += spitch;
2234 if (pxpack == 0) {
2235 if (srcfmt == 0) {
2236 xs += (Bit8u)(BLT.reg[blt_srcFormat] << 3);
2237 xs &= 0x1f;
2238 spitch = ((((w + xs + 7) >> 3) + 3) & ~3);
2239 } else {
2240 xs += (Bit8u)BLT.reg[blt_srcFormat];
2241 xs &= 0x03;
2242 spitch = ((w * spxsize + xs + 3) & ~3);
2243 }
2244 }
2245 if (BLT.y_dir) {
2246 dst_ptr -= dpitch;
2247 y--;
2248 } else {
2249 dst_ptr += dpitch;
2250 y++;
2251 }
2252 } while (--nrows);
2253 blt_complete();
2254 BX_UNLOCK(render_mutex);
2255 }
2256
blt_host_to_screen_pattern()2257 void bx_banshee_c::blt_host_to_screen_pattern()
2258 {
2259 Bit32u dpitch = BLT.dst_pitch;
2260 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
2261 Bit8u *src_ptr = &BLT.lamem[0];
2262 Bit8u *dst_ptr, *dst_ptr1, *src_ptr1, *pat_ptr1, *pat_ptr2;
2263 Bit8u *pat_ptr = &BLT.cpat[0][0];
2264 Bit16u spitch = BLT.h2s_pitch;
2265 Bit8u srcfmt = BLT.src_fmt;
2266 Bit8u pxpack = (BLT.reg[blt_srcFormat] >> 22) & 3;
2267 bool patmono = (BLT.reg[blt_command] >> 13) & 1;
2268 bool patrow0 = (BLT.reg[blt_commandExtra] & 0x08) > 0;
2269 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
2270 Bit8u spxsize = 0;
2271 Bit8u *srccolor, *patcolor;
2272 int nrows, dx, dy, w, h, xs;
2273 Bit8u smask = 0, pmask = 0, rop = 0, patline;
2274 bool set;
2275
2276 w = BLT.dst_w;
2277 h = BLT.dst_h;
2278 BX_DEBUG(("Host to screen pattern blt: %d x %d ROP0 %02X", w, h, BLT.rop[0]));
2279 if ((srcfmt != 0) && (BLT.dst_fmt != srcfmt)) {
2280 BX_ERROR(("Pixel format conversion not supported yet"));
2281 }
2282 BX_LOCK(render_mutex);
2283 if (srcfmt > 0) {
2284 if (srcfmt == 1) {
2285 spxsize = 1;
2286 } else if ((srcfmt >= 3) && (srcfmt <= 5)) {
2287 spxsize = srcfmt - 1;
2288 } else {
2289 spxsize = 4;
2290 }
2291 }
2292 dy = BLT.dst_y;
2293 xs = BLT.h2s_pxstart;
2294 dst_ptr = &v->fbi.ram[BLT.dst_base + dy * dpitch + BLT.dst_x * dpxsize];
2295 nrows = h;
2296 do {
2297 if (srcfmt == 0) {
2298 src_ptr1 = src_ptr + (xs >> 3);
2299 smask = 0x80 >> (xs & 7);
2300 } else {
2301 src_ptr1 = src_ptr + xs;
2302 }
2303 if (!patrow0) {
2304 patline = (dy + BLT.patsy) & 7;
2305 if (patmono) {
2306 pat_ptr1 = pat_ptr + patline;
2307 } else {
2308 pat_ptr1 = pat_ptr + patline * dpxsize * 8;
2309 }
2310 } else {
2311 pat_ptr1 = pat_ptr;
2312 }
2313 dst_ptr1 = dst_ptr;
2314 for (dx = BLT.dst_x; dx < (BLT.dst_x + w); dx++) {
2315 if (blt_clip_check(dx, dy)) {
2316 if (srcfmt == 0) {
2317 set = (*src_ptr1 & smask) > 0;
2318 if (set) {
2319 srccolor = &BLT.fgcolor[0];
2320 } else {
2321 srccolor = &BLT.bgcolor[0];
2322 }
2323 } else {
2324 srccolor = src_ptr1;
2325 }
2326 if (patmono) {
2327 pmask = 0x80 >> ((dx + BLT.patsx) & 7);
2328 set = (*pat_ptr1 & pmask) > 0;
2329 if (set) {
2330 patcolor = &BLT.fgcolor[0];
2331 } else {
2332 patcolor = &BLT.bgcolor[0];
2333 }
2334 if (set || !BLT.transp) {
2335 if (colorkey_en & 1) {
2336 rop = blt_colorkey_check(srccolor, dpxsize, 0);
2337 }
2338 if (colorkey_en & 2) {
2339 rop |= blt_colorkey_check(dst_ptr1, dpxsize, 1);
2340 }
2341 bx_ternary_rop(BLT.rop[rop], dst_ptr1, srccolor, patcolor, dpxsize);
2342 }
2343 } else {
2344 pat_ptr2 = pat_ptr1 + ((dx + BLT.patsx) & 7) * dpxsize;
2345 patcolor = pat_ptr2;
2346 if (colorkey_en & 1) {
2347 rop = blt_colorkey_check(srccolor, dpxsize, 0);
2348 }
2349 if (colorkey_en & 2) {
2350 rop |= blt_colorkey_check(dst_ptr1, dpxsize, 1);
2351 }
2352 bx_ternary_rop(BLT.rop[rop], dst_ptr1, srccolor, patcolor, dpxsize);
2353 }
2354 }
2355 if (srcfmt == 0) {
2356 smask >>= 1;
2357 if (smask == 0) {
2358 src_ptr1++;
2359 smask = 0x80;
2360 }
2361 } else {
2362 src_ptr1 += spxsize;
2363 }
2364 dst_ptr1 += dpxsize;
2365 }
2366 src_ptr += spitch;
2367 if (pxpack == 0) {
2368 if (srcfmt == 0) {
2369 xs += (Bit8u)(BLT.reg[blt_srcFormat] << 3);
2370 xs &= 0x1f;
2371 spitch = ((((w + xs + 7) >> 3) + 3) & ~3);
2372 } else {
2373 xs += (Bit8u)BLT.reg[blt_srcFormat];
2374 xs &= 0x03;
2375 spitch = ((w * spxsize + xs + 3) & ~3);
2376 }
2377 }
2378 if (BLT.y_dir) {
2379 dst_ptr -= dpitch;
2380 dy--;
2381 } else {
2382 dst_ptr += dpitch;
2383 dy++;
2384 }
2385 } while (--nrows);
2386 blt_complete();
2387 BX_UNLOCK(render_mutex);
2388 }
2389
blt_line(bool pline)2390 void bx_banshee_c::blt_line(bool pline)
2391 {
2392 Bit32u dpitch = BLT.dst_pitch;
2393 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
2394 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
2395 Bit8u rop = 0;
2396 Bit8u *dst_ptr = &v->fbi.ram[BLT.dst_base];
2397 Bit8u *dst_ptr1;
2398 int i, deltax, deltay, numpixels, d, dinc1, dinc2;
2399 int x, xinc1, xinc2, y, yinc1, yinc2;
2400 int x0, y0, x1, y1;
2401 bool lstipple = ((BLT.reg[blt_command] >> 12) & 1);
2402 Bit8u lpattern = BLT.reg[blt_lineStipple];
2403 Bit8u lrepeat = (BLT.reg[blt_lineStyle] & 0xff);
2404 Bit8u lpat_max = ((BLT.reg[blt_lineStyle] >> 8) & 0x1f);
2405 Bit8u lrep_cnt = lrepeat - ((BLT.reg[blt_lineStyle] >> 16) & 0xff);
2406 Bit8u lpat_idx = ((BLT.reg[blt_lineStyle] >> 24) & 0x1f);
2407
2408 BX_LOCK(render_mutex);
2409 x0 = BLT.src_x;
2410 y0 = BLT.src_y;
2411 x1 = BLT.dst_x;
2412 y1 = BLT.dst_y;
2413 if (pline) {
2414 BX_DEBUG(("Polyline: %d/%d -> %d/%d ROP0 %02X", x0, y0, x1, y1, BLT.rop[0]));
2415 } else {
2416 BX_DEBUG(("Line: %d/%d -> %d/%d ROP0 %02X", x0, y0, x1, y1, BLT.rop[0]));
2417 }
2418 deltax = abs(x1 - x0);
2419 deltay = abs(y1 - y0);
2420 if (deltax >= deltay) {
2421 numpixels = deltax + 1;
2422 d = (deltay << 1) - deltax;
2423 dinc1 = deltay << 1;
2424 dinc2 = (deltay - deltax) << 1;
2425 xinc1 = 1;
2426 xinc2 = 1;
2427 yinc1 = 0;
2428 yinc2 = 1;
2429 } else {
2430 numpixels = deltay + 1;
2431 d = (deltax << 1) - deltay;
2432 dinc1 = deltax << 1;
2433 dinc2 = (deltax - deltay) << 1;
2434 xinc1 = 0;
2435 xinc2 = 1;
2436 yinc1 = 1;
2437 yinc2 = 1;
2438 }
2439
2440 if (x0 > x1) {
2441 xinc1 = -xinc1;
2442 xinc2 = -xinc2;
2443 }
2444 if (y0 > y1) {
2445 yinc1 = -yinc1;
2446 yinc2 = -yinc2;
2447 }
2448 x = x0;
2449 y = y0;
2450
2451 for (i = 0; i < (numpixels - 1); i++) {
2452 if (blt_clip_check(x, y)) {
2453 dst_ptr1 = dst_ptr + y * dpitch + x * dpxsize;
2454 if (colorkey_en & 2) {
2455 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
2456 }
2457 if (!lstipple) {
2458 BLT.rop_fn[rop](dst_ptr1, BLT.fgcolor, dpitch, dpxsize, dpxsize, 1);
2459 } else {
2460 if ((lpattern & (1 << lpat_idx)) != 0) {
2461 BLT.rop_fn[rop](dst_ptr1, BLT.fgcolor, dpitch, dpxsize, dpxsize, 1);
2462 } else if (!BLT.transp) {
2463 BLT.rop_fn[rop](dst_ptr1, BLT.bgcolor, dpitch, dpxsize, dpxsize, 1);
2464 }
2465 }
2466 }
2467 if (lrep_cnt == 0) {
2468 if (++lpat_idx > lpat_max) {
2469 lpat_idx = 0;
2470 }
2471 lrep_cnt = lrepeat;
2472 } else {
2473 lrep_cnt--;
2474 }
2475 if (d < 0) {
2476 d = d + dinc1;
2477 x = x + xinc1;
2478 y = y + yinc1;
2479 } else {
2480 d = d + dinc2;
2481 x = x + xinc2;
2482 y = y + yinc2;
2483 }
2484 }
2485
2486 if (!pline) {
2487 dst_ptr1 = dst_ptr + y1 * dpitch + x1 * dpxsize;
2488 if (colorkey_en & 2) {
2489 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
2490 }
2491 BLT.rop_fn[rop](dst_ptr1, BLT.fgcolor, dpitch, dpxsize, dpxsize, 1);
2492 }
2493 blt_complete();
2494 BLT.reg[blt_srcXY] = BLT.reg[blt_dstXY];
2495 BLT.src_x = BLT.dst_x;
2496 BLT.src_y = BLT.dst_y;
2497 BX_UNLOCK(render_mutex);
2498 }
2499
calc_line_xpos(int x1,int y1,int x2,int y2,int yc,bool r)2500 int calc_line_xpos(int x1, int y1, int x2, int y2, int yc, bool r)
2501 {
2502 int i, deltax, deltay, numpixels,
2503 d, dinc1, dinc2,
2504 x, xinc1, xinc2,
2505 y, yinc1, yinc2;
2506 int xl = -1, xr = -1;
2507
2508 if (x1 == x2) {
2509 xl = xr = x1;
2510 } else {
2511 deltax = abs(x2 - x1);
2512 deltay = abs(y2 - y1);
2513 if (deltax >= deltay) {
2514 numpixels = deltax + 1;
2515 d = (deltay << 1) - deltax;
2516 dinc1 = deltay << 1;
2517 dinc2 = (deltay - deltax) << 1;
2518 xinc1 = 1;
2519 xinc2 = 1;
2520 yinc1 = 0;
2521 yinc2 = 1;
2522 } else {
2523 numpixels = deltay + 1;
2524 d = (deltax << 1) - deltay;
2525 dinc1 = deltax << 1;
2526 dinc2 = (deltax - deltay) << 1;
2527 xinc1 = 0;
2528 xinc2 = 1;
2529 yinc1 = 1;
2530 yinc2 = 1;
2531 }
2532
2533 if (x1 > x2) {
2534 xinc1 = - xinc1;
2535 xinc2 = - xinc2;
2536 }
2537 if (y1 > y2) {
2538 yinc1 = - yinc1;
2539 yinc2 = - yinc2;
2540 }
2541 x = x1;
2542 y = y1;
2543
2544 for (i = 0; i < numpixels; i++) {
2545 if (y == yc) {
2546 if (xl == -1) {
2547 xl = xr = x;
2548 } else {
2549 if (x < xl) xl = x;
2550 if (x > xr) xr = x;
2551 }
2552 }
2553 if (d < 0) {
2554 d = d + dinc1;
2555 x = x + xinc1;
2556 y = y + yinc1;
2557 } else {
2558 d = d + dinc2;
2559 x = x + xinc2;
2560 y = y + yinc2;
2561 }
2562 }
2563 }
2564 return (r ? xr : xl);
2565 }
2566
blt_polygon_fill(bool force)2567 void bx_banshee_c::blt_polygon_fill(bool force)
2568 {
2569 Bit32u dpitch = BLT.dst_pitch;
2570 Bit8u dpxsize = (BLT.dst_fmt > 1) ? (BLT.dst_fmt - 1) : 1;
2571 Bit8u *dst_ptr = &v->fbi.ram[BLT.dst_base];
2572 Bit8u *pat_ptr = &BLT.cpat[0][0];
2573 Bit8u *dst_ptr1, *pat_ptr1 = NULL;
2574 bool patmono = (BLT.reg[blt_command] >> 13) & 1;
2575 bool patrow0 = (BLT.reg[blt_commandExtra] & 0x08) > 0;
2576 bool set;
2577 Bit8u colorkey_en = BLT.reg[blt_commandExtra] & 3;
2578 Bit8u rop = 0, mask, patline;
2579 Bit8u *color;
2580 Bit16u x, y, x0, x1, y0, y1;
2581
2582 if (force) {
2583 if (BLT.pgn_l1y == BLT.pgn_r1y) {
2584 return;
2585 } else if (BLT.pgn_l1y < BLT.pgn_r1y) {
2586 BLT.pgn_l1x = BLT.pgn_r1x;
2587 BLT.pgn_l1y = BLT.pgn_r1y;
2588 } else {
2589 BLT.pgn_r1x = BLT.pgn_l1x;
2590 BLT.pgn_r1y = BLT.pgn_l1y;
2591 }
2592 }
2593 if ((BLT.pgn_l1y > BLT.pgn_l0y) && (BLT.pgn_r1y > BLT.pgn_r0y)) {
2594 BLT.busy = 1;
2595 BX_LOCK(render_mutex);
2596 y0 = BLT.pgn_l0y;
2597 if (BLT.pgn_l1y < BLT.pgn_r1y) {
2598 y1 = BLT.pgn_l1y;
2599 } else {
2600 y1 = BLT.pgn_r1y;
2601 }
2602 for (y = y0; y < y1; y++) {
2603 x0 = calc_line_xpos(BLT.pgn_l0x, BLT.pgn_l0y, BLT.pgn_l1x, BLT.pgn_l1y, y, 0);
2604 if (y <= BLT.pgn_r0y) {
2605 x1 = calc_line_xpos(BLT.pgn_l0x, BLT.pgn_l0y, BLT.pgn_r0x, BLT.pgn_r0y, y, 1);
2606 } else {
2607 x1 = calc_line_xpos(BLT.pgn_r0x, BLT.pgn_r0y, BLT.pgn_r1x, BLT.pgn_r1y, y, 1);
2608 }
2609 if (BLT.pattern_blt) {
2610 if (!patrow0) {
2611 patline = (y + BLT.patsy) & 7;
2612 if (patmono) {
2613 pat_ptr1 = pat_ptr + patline;
2614 } else {
2615 pat_ptr1 = pat_ptr + patline * dpxsize * 8;
2616 }
2617 } else {
2618 pat_ptr1 = pat_ptr;
2619 }
2620 }
2621 dst_ptr1 = dst_ptr + y * dpitch + x0 * dpxsize;
2622 if (blt_clip_check(x0, y)) {
2623 if (colorkey_en & 2) {
2624 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
2625 }
2626 if (BLT.pattern_blt) {
2627 if (patmono) {
2628 mask = 0x80 >> ((x0 + BLT.patsx) & 7);
2629 set = (*pat_ptr1 & mask) > 0;
2630 if (set) {
2631 color = &BLT.fgcolor[0];
2632 } else {
2633 color = &BLT.bgcolor[0];
2634 }
2635 if ((set) || !BLT.transp) {
2636 BLT.rop_fn[rop](dst_ptr1, color, dpitch, dpxsize, dpxsize, 1);
2637 }
2638 } else {
2639 color = (pat_ptr1 + ((x0 + BLT.patsx) & 7) * dpxsize);
2640 BLT.rop_fn[rop](dst_ptr1, color, dpitch, dpxsize, dpxsize, 1);
2641 }
2642 } else {
2643 BLT.rop_fn[rop](dst_ptr1, BLT.fgcolor, dpitch, dpxsize, dpxsize, 1);
2644 }
2645 }
2646 dst_ptr1 += dpxsize;
2647 for (x = x0 + 1; x < x1; x++) {
2648 if (blt_clip_check(x, y)) {
2649 if (colorkey_en & 2) {
2650 rop = blt_colorkey_check(dst_ptr1, dpxsize, 1);
2651 }
2652 if (BLT.pattern_blt) {
2653 if (patmono) {
2654 mask = 0x80 >> ((x + BLT.patsx) & 7);
2655 set = (*pat_ptr1 & mask) > 0;
2656 if (set) {
2657 color = &BLT.fgcolor[0];
2658 } else {
2659 color = &BLT.bgcolor[0];
2660 }
2661 if ((set) || !BLT.transp) {
2662 BLT.rop_fn[rop](dst_ptr1, color, dpitch, dpxsize, dpxsize, 1);
2663 }
2664 } else {
2665 color = (pat_ptr1 + ((x + BLT.patsx) & 7) * dpxsize);
2666 BLT.rop_fn[rop](dst_ptr1, color, dpitch, dpxsize, dpxsize, 1);
2667 }
2668 } else {
2669 BLT.rop_fn[rop](dst_ptr1, BLT.fgcolor, dpitch, dpxsize, dpxsize, 1);
2670 }
2671 }
2672 dst_ptr1 += dpxsize;
2673 }
2674 }
2675 BX_DEBUG(("Polygon fill: L0=(%d,%d) L1=(%d,%d) R0=(%d,%d) R1=(%d,%d) ROP0 %02X",
2676 BLT.pgn_l0x, BLT.pgn_l0y, BLT.pgn_l1x, BLT.pgn_l1y,
2677 BLT.pgn_r0x, BLT.pgn_r0y, BLT.pgn_r1x, BLT.pgn_r1y, BLT.rop[0]));
2678 if (y1 == BLT.pgn_l1y) {
2679 BLT.pgn_l0x = BLT.pgn_l1x;
2680 BLT.pgn_l0y = BLT.pgn_l1y;
2681 }
2682 if (y1 == BLT.pgn_r1y) {
2683 BLT.pgn_r0x = BLT.pgn_r1x;
2684 BLT.pgn_r0y = BLT.pgn_r1y;
2685 }
2686 blt_complete();
2687 BX_UNLOCK(render_mutex);
2688 }
2689 }
2690
2691 #if BX_DEBUGGER
debug_dump(int argc,char ** argv)2692 void bx_banshee_c::debug_dump(int argc, char **argv)
2693 {
2694 bool is_agp = SIM->is_agp_device(BX_PLUGIN_VOODOO);
2695 if (v->banshee.io[io_vidProcCfg] & 0x01) {
2696 if (s.model == VOODOO_BANSHEE) {
2697 dbg_printf("Voodoo Banshee %s adapter\n\n", is_agp ? "AGP":"PCI");
2698 } else {
2699 dbg_printf("Voodoo3 %s adapter\n\n", is_agp ? "AGP":"PCI");
2700 }
2701 dbg_printf("current mode : %u x %u x %u ", v->fbi.width,
2702 v->fbi.height, v->banshee.disp_bpp);
2703 if ((v->banshee.io[io_vidProcCfg] & 0x180) == 0x080) {
2704 dbg_printf("(2D desktop mode)\n");
2705 } else if ((v->banshee.io[io_vidProcCfg] & 0x180) == 0x100) {
2706 dbg_printf("(3D overlay mode)\n");
2707 } else {
2708 dbg_printf("\n");
2709 }
2710 if (argc > 0) {
2711 dbg_printf("\nAdditional options not supported\n");
2712 }
2713 } else {
2714 theVoodooVga->debug_dump(argc, argv);
2715 }
2716 }
2717 #endif
2718
2719 #undef BLT
2720
2721 #undef LOG_THIS
2722 #define LOG_THIS theVoodooVga->
2723
bx_voodoo_vga_c()2724 bx_voodoo_vga_c::bx_voodoo_vga_c() : bx_vgacore_c()
2725 {
2726 put("VVGA");
2727 }
2728
~bx_voodoo_vga_c()2729 bx_voodoo_vga_c::~bx_voodoo_vga_c()
2730 {
2731 s.memory = NULL;
2732 }
2733
init_vga_extension(void)2734 bool bx_voodoo_vga_c::init_vga_extension(void)
2735 {
2736 bool ret = 0;
2737
2738 Bit8u model = (Bit8u)SIM->get_param_enum("model", (bx_list_c*)SIM->get_param(BXPN_VOODOO))->get();
2739 if (model < VOODOO_BANSHEE) {
2740 theVoodooDevice = new bx_voodoo_1_2_c();
2741 theVoodooDevice->init();
2742 init_iohandlers(read_handler, write_handler);
2743 } else {
2744 theVoodooDevice = new bx_banshee_c();
2745 theVoodooDevice->init();
2746 BX_VVGA_THIS s.memory = v->fbi.ram;
2747 BX_VVGA_THIS s.memsize = v->fbi.mask + 1;
2748 init_iohandlers(banshee_vga_read_handler, banshee_vga_write_handler);
2749 DEV_register_iowrite_handler(this, banshee_vga_write_handler, 0x0102, "banshee", 1);
2750 DEV_register_iowrite_handler(this, banshee_vga_write_handler, 0x46e8, "banshee", 1);
2751 BX_VVGA_THIS s.max_xres = 1600;
2752 BX_VVGA_THIS s.max_yres = 1280;
2753 v->banshee.disp_bpp = 8;
2754 BX_VVGA_THIS s.vclk[0] = 25175000;
2755 BX_VVGA_THIS s.vclk[1] = 28322000;
2756 BX_VVGA_THIS s.vclk[2] = 50000000;
2757 BX_VVGA_THIS s.vclk[3] = 25175000;
2758 BX_VVGA_THIS pci_enabled = 1;
2759 ret = 1;
2760 }
2761 #if BX_DEBUGGER
2762 // register device for the 'info device' command (calls debug_dump())
2763 bx_dbg_register_debug_info("voodoo", theVoodooDevice);
2764 #endif
2765 return ret;
2766 }
2767
reset(unsigned type)2768 void bx_voodoo_vga_c::reset(unsigned type)
2769 {
2770 theVoodooDevice->reset(type);
2771 }
2772
register_state(void)2773 void bx_voodoo_vga_c::register_state(void)
2774 {
2775 bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "voodoo_vga", "Voodoo VGA State");
2776 BX_VVGA_THIS vgacore_register_state(list);
2777 theVoodooDevice->register_state();
2778 }
2779
after_restore_state(void)2780 void bx_voodoo_vga_c::after_restore_state(void)
2781 {
2782 bx_vgacore_c::after_restore_state();
2783 theVoodooDevice->after_restore_state();
2784 }
2785
redraw_area(unsigned x0,unsigned y0,unsigned width,unsigned height)2786 void bx_voodoo_vga_c::redraw_area(unsigned x0, unsigned y0, unsigned width,
2787 unsigned height)
2788 {
2789 if (v->banshee.io[io_vidProcCfg] & 0x01) {
2790 theVoodooDevice->redraw_area(x0, y0, width, height);
2791 } else {
2792 bx_vgacore_c::redraw_area(x0, y0, width, height);
2793 }
2794 }
2795
banshee_update_mode(void)2796 void bx_voodoo_vga_c::banshee_update_mode(void)
2797 {
2798 Bit8u format = (v->banshee.io[io_vidProcCfg] >> 18) & 0x07;
2799
2800 if (format < 4) {
2801 v->banshee.disp_bpp = (format + 1) << 3;
2802 } else {
2803 BX_ERROR(("Ignoring reserved pixel format"));
2804 return;
2805 }
2806 v->banshee.half_mode = (v->banshee.io[io_vidProcCfg] >> 4) & 1;
2807 BX_INFO(("switched to %d x %d x %d @ %d Hz", v->fbi.width, v->fbi.height,
2808 v->banshee.disp_bpp, (unsigned)v->vertfreq));
2809 bx_gui->dimension_update(v->fbi.width, v->fbi.height, 0, 0, v->banshee.disp_bpp);
2810 // compatibilty settings for VGA core
2811 BX_VVGA_THIS s.last_xres = v->fbi.width;
2812 BX_VVGA_THIS s.last_yres = v->fbi.height;
2813 BX_VVGA_THIS s.last_bpp = v->banshee.disp_bpp;
2814 BX_VVGA_THIS s.last_fh = 0;
2815 }
2816
banshee_set_dac_mode(bool mode)2817 void bx_voodoo_vga_c::banshee_set_dac_mode(bool mode)
2818 {
2819 unsigned i;
2820
2821 if (mode != v->banshee.dac_8bit) {
2822 if (mode) {
2823 for (i=0; i<256; i++) {
2824 s.pel.data[i].red <<= 2;
2825 s.pel.data[i].green <<= 2;
2826 s.pel.data[i].blue <<= 2;
2827 }
2828 BX_INFO(("DAC in 8 bit mode"));
2829 } else {
2830 for (i=0; i<256; i++) {
2831 s.pel.data[i].red >>= 2;
2832 s.pel.data[i].green >>= 2;
2833 s.pel.data[i].blue >>= 2;
2834 }
2835 BX_INFO(("DAC in standard mode"));
2836 }
2837 v->banshee.dac_8bit = mode;
2838 s.dac_shift = mode ? 0 : 2;
2839 }
2840 }
2841
banshee_set_vclk3(Bit32u value)2842 void bx_voodoo_vga_c::banshee_set_vclk3(Bit32u value)
2843 {
2844 BX_VVGA_THIS s.vclk[3] = value;
2845 if (BX_VVGA_THIS s.misc_output.clock_select == 3) {
2846 calculate_retrace_timing();
2847 }
2848 }
2849
get_retrace()2850 Bit32u bx_voodoo_vga_c::get_retrace()
2851 {
2852 Bit32u retval = 1;
2853 Bit64u display_usec =
2854 bx_virt_timer.time_usec(BX_VVGA_THIS vsync_realtime) % BX_VVGA_THIS s.vtotal_usec;
2855 if ((display_usec >= BX_VVGA_THIS s.vrstart_usec) &&
2856 (display_usec <= BX_VVGA_THIS s.vrend_usec)) {
2857 retval = 0;
2858 }
2859 return retval;
2860 }
2861
get_crtc_params(bx_crtc_params_t * crtcp,Bit32u * vclock)2862 void bx_voodoo_vga_c::get_crtc_params(bx_crtc_params_t *crtcp, Bit32u *vclock)
2863 {
2864 *vclock = BX_VVGA_THIS s.vclk[BX_VVGA_THIS s.misc_output.clock_select];
2865 crtcp->htotal = BX_VVGA_THIS s.CRTC.reg[0] + ((v->banshee.crtc[0x1a] & 0x01) << 8) + 5;
2866 crtcp->vtotal = BX_VVGA_THIS s.CRTC.reg[6] + ((BX_VVGA_THIS s.CRTC.reg[7] & 0x01) << 8) +
2867 ((BX_VVGA_THIS s.CRTC.reg[7] & 0x20) << 4) +
2868 ((v->banshee.crtc[0x1b] & 0x01) << 10) + 2;
2869 crtcp->vrstart = BX_VVGA_THIS s.CRTC.reg[16] +
2870 ((BX_VVGA_THIS s.CRTC.reg[7] & 0x04) << 6) +
2871 ((BX_VVGA_THIS s.CRTC.reg[7] & 0x80) << 2) +
2872 ((v->banshee.crtc[0x1b] & 0x40) << 4);
2873 }
2874
update(void)2875 void bx_voodoo_vga_c::update(void)
2876 {
2877 if (v->banshee.io[io_vidProcCfg] & 0x01) {
2878 theVoodooDevice->update();
2879 } else if (!((v->banshee.io[io_vgaInit0] >> 12) & 1)) {
2880 BX_VVGA_THIS bx_vgacore_c::update();
2881 }
2882 }
2883
banshee_vga_read_handler(void * this_ptr,Bit32u address,unsigned io_len)2884 Bit32u bx_voodoo_vga_c::banshee_vga_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
2885 {
2886 UNUSED(this_ptr);
2887 Bit32u value;
2888
2889 if ((io_len == 2) && ((address & 1) == 0)) {
2890 value = banshee_vga_read_handler(theVoodooVga,address,1);
2891 value |= (banshee_vga_read_handler(theVoodooVga,address+1,1) << 8);
2892 return value;
2893 }
2894
2895 if (BX_VVGA_THIS s.misc_output.color_emulation && (address == 0x03b5))
2896 return 0xff;
2897 if (!BX_VVGA_THIS s.misc_output.color_emulation && (address == 0x03d5))
2898 return 0xff;
2899
2900 switch (address) {
2901 case 0x03b5:
2902 case 0x03d5:
2903 if (BX_VVGA_THIS s.CRTC.address > 0x18) {
2904 if (BX_VVGA_THIS s.CRTC.address == 0x22) {
2905 value = bx_vgacore_c::read_handler(BX_VVGA_THIS_PTR, address, io_len);
2906 } else if (BX_VVGA_THIS s.CRTC.address <= 0x26) {
2907 if ((v->banshee.io[io_vgaInit0] & 0x440) == 0x040) {
2908 value = v->banshee.crtc[BX_VVGA_THIS s.CRTC.address];
2909 BX_DEBUG(("read from banshee CRTC address 0x%02x value 0x%02x",
2910 BX_VVGA_THIS s.CRTC.address, value));
2911 } else {
2912 value = 0xff;
2913 }
2914 } else {
2915 value = 0xff;
2916 }
2917 break;
2918 }
2919 default:
2920 value = bx_vgacore_c::read_handler(BX_VVGA_THIS_PTR, address, io_len);
2921 }
2922 return value;
2923
2924 }
2925
banshee_vga_write_handler(void * this_ptr,Bit32u address,Bit32u value,unsigned io_len)2926 void bx_voodoo_vga_c::banshee_vga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
2927 {
2928 UNUSED(this_ptr);
2929 Bit8u value8;
2930
2931 if ((io_len == 2) && ((address & 1) == 0)) {
2932 banshee_vga_write_handler(theVoodooVga,address,value & 0xff,1);
2933 banshee_vga_write_handler(theVoodooVga,address+1,value >> 8,1);
2934 return;
2935 }
2936
2937 if (BX_VVGA_THIS s.misc_output.color_emulation && (address == 0x03b5))
2938 return;
2939 if (!BX_VVGA_THIS s.misc_output.color_emulation && (address == 0x03d5))
2940 return;
2941
2942 switch (address) {
2943 case 0x0102:
2944 case 0x46e8:
2945 // TODO
2946 return;
2947
2948 case 0x03c9:
2949 value8 = (Bit8u)value;
2950 if (!v->banshee.dac_8bit) value8 <<= 2;
2951 switch (BX_VVGA_THIS s.pel.write_data_cycle) {
2952 case 0:
2953 v->fbi.clut[BX_VVGA_THIS s.pel.write_data_register] &= 0x00ffff;
2954 v->fbi.clut[BX_VVGA_THIS s.pel.write_data_register] |= (value8 << 16);
2955 break;
2956 case 1:
2957 v->fbi.clut[BX_VVGA_THIS s.pel.write_data_register] &= 0xff00ff;
2958 v->fbi.clut[BX_VVGA_THIS s.pel.write_data_register] |= (value8 << 8);
2959 break;
2960 case 2:
2961 v->fbi.clut[BX_VVGA_THIS s.pel.write_data_register] &= 0xffff00;
2962 v->fbi.clut[BX_VVGA_THIS s.pel.write_data_register] |= value8;
2963 break;
2964 }
2965 break;
2966
2967 case 0x03b5:
2968 case 0x03d5:
2969 if (BX_VVGA_THIS s.CRTC.address > 0x18) {
2970 if (BX_VVGA_THIS s.CRTC.address <= 0x26) {
2971 if ((v->banshee.io[io_vgaInit0] & 0x440) == 0x040) {
2972 BX_DEBUG(("write to banshee CRTC address 0x%02x value 0x%02x",
2973 BX_VVGA_THIS s.CRTC.address, value));
2974 v->banshee.crtc[BX_VVGA_THIS s.CRTC.address] = (Bit8u)value;
2975 }
2976 }
2977 return;
2978 }
2979 break;
2980 }
2981 bx_vgacore_c::write_handler(theVoodooVga, address, value, io_len);
2982 }
2983
mem_read(bx_phy_address addr)2984 Bit8u bx_voodoo_vga_c::mem_read(bx_phy_address addr)
2985 {
2986 Bit32u offset = ((v->banshee.io[io_vgaInit1] & 0xffc00) << 5) + (addr & 0x1ffff);
2987 bool chain4 = ((v->banshee.io[io_vgaInit1] >> 20) & 1);
2988
2989 if (chain4) {
2990 return v->fbi.ram[offset & v->fbi.mask];
2991 } else {
2992 return bx_vgacore_c::mem_read(addr);
2993 }
2994 }
2995
mem_write(bx_phy_address addr,Bit8u value)2996 void bx_voodoo_vga_c::mem_write(bx_phy_address addr, Bit8u value)
2997 {
2998 bool chain4 = ((v->banshee.io[io_vgaInit1] >> 20) & 1);
2999 Bit32u offset, start, end, pitch;
3000 unsigned xti, yti;
3001
3002 if (chain4) {
3003 offset = (((v->banshee.io[io_vgaInit1] & 0x3ff) << 15) + (addr & 0x1ffff)) & v->fbi.mask;
3004 v->fbi.ram[offset] = value;
3005 start = v->banshee.io[io_vidDesktopStartAddr] & v->fbi.mask;
3006 pitch = v->banshee.io[io_vidDesktopOverlayStride] & 0x7fff;
3007 end = start + pitch * v->fbi.height;
3008 if ((offset >= start) && (offset < end)) {
3009 offset -= start;
3010 if (v->banshee.half_mode) {
3011 yti = (offset / pitch) / (Y_TILESIZE / 2);
3012 } else {
3013 yti = (offset / pitch) / Y_TILESIZE;
3014 }
3015 xti = ((offset % pitch) / (v->banshee.disp_bpp >> 3)) / X_TILESIZE;
3016 theVoodooDevice->set_tile_updated(xti, yti, 1);
3017 }
3018 } else {
3019 bx_vgacore_c::mem_write(addr, value);
3020 }
3021 }
3022
3023 #endif // BX_SUPPORT_PCI && BX_SUPPORT_VOODOO
3024