1 |
/* |
2 |
* Copyright (C) 2003-2006 Anders Gavare. All rights reserved. |
3 |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
6 |
* |
7 |
* 1. Redistributions of source code must retain the above copyright |
8 |
* notice, this list of conditions and the following disclaimer. |
9 |
* 2. Redistributions in binary form must reproduce the above copyright |
10 |
* notice, this list of conditions and the following disclaimer in the |
11 |
* documentation and/or other materials provided with the distribution. |
12 |
* 3. The name of the author may not be used to endorse or promote products |
13 |
* derived from this software without specific prior written permission. |
14 |
* |
15 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
19 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 |
* SUCH DAMAGE. |
26 |
* |
27 |
* |
28 |
* $Id: dev_bt459.c,v 1.63 2006/01/01 13:17:16 debug Exp $ |
29 |
* |
30 |
* Brooktree 459 vdac, used by TURBOchannel graphics cards. |
31 |
*/ |
32 |
|
33 |
#include <stdio.h> |
34 |
#include <stdlib.h> |
35 |
#include <string.h> |
36 |
|
37 |
#include "cpu.h" |
38 |
#include "devices.h" |
39 |
#include "machine.h" |
40 |
#include "memory.h" |
41 |
#include "misc.h" |
42 |
#include "x11.h" |
43 |
|
44 |
#include "bt459.h" |
45 |
|
46 |
|
47 |
#ifdef WITH_X11 |
48 |
#include <X11/Xlib.h> |
49 |
#include <X11/Xutil.h> |
50 |
#endif |
51 |
|
52 |
extern int quiet_mode; |
53 |
|
54 |
|
55 |
/* #define BT459_DEBUG */ |
56 |
/* #define WITH_CURSOR_DEBUG */ |
57 |
#define BT459_TICK_SHIFT 14 |
58 |
|
59 |
struct bt459_data { |
60 |
uint32_t bt459_reg[DEV_BT459_NREGS]; |
61 |
|
62 |
unsigned char cur_addr_hi; |
63 |
unsigned char cur_addr_lo; |
64 |
|
65 |
int planes; |
66 |
int type; |
67 |
|
68 |
int irq_nr; |
69 |
int interrupts_enable; |
70 |
int interrupt_time; |
71 |
int interrupt_time_reset_value; |
72 |
|
73 |
int cursor_x_add; |
74 |
int cursor_y_add; |
75 |
|
76 |
int need_to_redraw_whole_screen; |
77 |
|
78 |
int need_to_update_cursor_shape; |
79 |
int cursor_on; |
80 |
int cursor_x; |
81 |
int cursor_y; |
82 |
int cursor_xsize; |
83 |
int cursor_ysize; |
84 |
|
85 |
int palette_sub_offset; /* 0, 1, or 2 */ |
86 |
|
87 |
struct vfb_data *vfb_data; |
88 |
|
89 |
/* |
90 |
* There is one pointer to the framebuffer's RGB palette, |
91 |
* and then a local copy of the palette. 256 * 3 bytes (r,g,b). |
92 |
* The reason for this is that when we need to blank the screen |
93 |
* (ie video_on = 0), we can set the framebuffer's palette to all |
94 |
* zeroes, but keep our own copy intact, to be reused later again |
95 |
* when the screen is unblanked. |
96 |
*/ |
97 |
int video_on; |
98 |
unsigned char *rgb_palette; /* 256 * 3 (r,g,b) */ |
99 |
unsigned char local_rgb_palette[256 * 3]; |
100 |
}; |
101 |
|
102 |
|
103 |
/* |
104 |
* bt459_update_X_cursor(): |
105 |
* |
106 |
* This routine takes the color values in the cursor RAM area, and put them |
107 |
* in the framebuffer window's cursor_pixels. |
108 |
* |
109 |
* d->cursor_xsize and ysize are also updated. |
110 |
*/ |
111 |
static void bt459_update_X_cursor(struct cpu *cpu, struct bt459_data *d) |
112 |
{ |
113 |
int i, x,y, xmax=0, ymax=0; |
114 |
int bw_only = 1; |
115 |
|
116 |
/* First, let's calculate the size of the cursor: */ |
117 |
for (y=0; y<64; y++) |
118 |
for (x=0; x<64; x+=4) { |
119 |
int reg = BT459_REG_CRAM_BASE + y*16 + x/4; |
120 |
unsigned char data = d->bt459_reg[reg]; |
121 |
|
122 |
if (data) |
123 |
ymax = y; |
124 |
|
125 |
for (i=0; i<4; i++) { |
126 |
int color = (data >> (6-2*i)) & 3; |
127 |
if (color != 0) |
128 |
xmax = x + i; |
129 |
if (color != 0 && color != 3) |
130 |
bw_only = 0; |
131 |
} |
132 |
} |
133 |
|
134 |
d->cursor_xsize = xmax + 1; |
135 |
d->cursor_ysize = ymax + 1; |
136 |
|
137 |
/* |
138 |
* The 'bw_only' hack is because it is nicer to have the b/w |
139 |
* text cursor invert whatever it is standing on, not just overwrite |
140 |
* it with a big white box. |
141 |
* |
142 |
* The following seems to work with NetBSD/OpenBSD/Ultrix/Sprite: |
143 |
* 0 = transparent, 1 and 2 = use the color specified by |
144 |
* BT459_REG_CCOLOR_2, 3 = reverse of color 1/2. |
145 |
*/ |
146 |
|
147 |
#ifdef WITH_X11 |
148 |
if (cpu->machine->use_x11 && d->vfb_data->fb_window != NULL) { |
149 |
for (y=0; y<=ymax; y++) { |
150 |
for (x=0; x<=xmax; x+=4) { |
151 |
struct fb_window *win = d->vfb_data->fb_window; |
152 |
int reg = BT459_REG_CRAM_BASE + y*16 + x/4; |
153 |
unsigned char data = d->bt459_reg[reg]; |
154 |
|
155 |
for (i=0; i<4; i++) { |
156 |
int color = (data >> (6-2*i)) & 3; |
157 |
int pixelvalue; |
158 |
|
159 |
if (bw_only) { |
160 |
if (color) |
161 |
pixelvalue = |
162 |
CURSOR_COLOR_INVERT; |
163 |
else |
164 |
pixelvalue = 0; |
165 |
} else { |
166 |
pixelvalue = |
167 |
CURSOR_COLOR_TRANSPARENT; |
168 |
switch (color) { |
169 |
case 1: |
170 |
case 2: pixelvalue = (d-> |
171 |
bt459_reg[ |
172 |
BT459_REG_CCOLOR_2] |
173 |
>> 4) & 0xf; |
174 |
break; |
175 |
case 3: pixelvalue = 15 - |
176 |
((d->bt459_reg[ |
177 |
BT459_REG_CCOLOR_2] |
178 |
>> 4) & 0xf); |
179 |
break; |
180 |
} |
181 |
} |
182 |
|
183 |
win->cursor_pixels[y][x+i] = |
184 |
pixelvalue; |
185 |
#ifdef WITH_CURSOR_DEBUG |
186 |
printf("%i", color); |
187 |
#endif |
188 |
} |
189 |
} |
190 |
#ifdef WITH_CURSOR_DEBUG |
191 |
printf("\n"); |
192 |
#endif |
193 |
} |
194 |
#ifdef WITH_CURSOR_DEBUG |
195 |
printf("color 1,2,3 = 0x%02x, 0x%02x, 0x%02x\n", |
196 |
d->bt459_reg[BT459_REG_CCOLOR_1], |
197 |
d->bt459_reg[BT459_REG_CCOLOR_2], |
198 |
d->bt459_reg[BT459_REG_CCOLOR_3]); |
199 |
printf("\n"); |
200 |
#endif |
201 |
/* |
202 |
* Make sure the cursor is redrawn, if it is on: |
203 |
* |
204 |
* How does this work? Well, 0 is off, and non-zero is on, |
205 |
* but if the old and new differ, the cursor is redrawn. |
206 |
* (Hopefully this will "never" overflow.) |
207 |
*/ |
208 |
if (d->cursor_on) |
209 |
d->cursor_on ++; |
210 |
} |
211 |
#endif |
212 |
} |
213 |
|
214 |
|
215 |
/* |
216 |
* bt459_update_cursor_position(): |
217 |
*/ |
218 |
static void bt459_update_cursor_position(struct bt459_data *d, |
219 |
int old_cursor_on) |
220 |
{ |
221 |
int new_cursor_x = (d->bt459_reg[BT459_REG_CXLO] & 255) + |
222 |
((d->bt459_reg[BT459_REG_CXHI] & 255) << 8) - d->cursor_x_add; |
223 |
int new_cursor_y = (d->bt459_reg[BT459_REG_CYLO] & 255) + |
224 |
((d->bt459_reg[BT459_REG_CYHI] & 255) << 8) - d->cursor_y_add; |
225 |
|
226 |
if (new_cursor_x != d->cursor_x || new_cursor_y != d->cursor_y || |
227 |
d->cursor_on != old_cursor_on) { |
228 |
int on; |
229 |
|
230 |
d->cursor_x = new_cursor_x; |
231 |
d->cursor_y = new_cursor_y; |
232 |
|
233 |
if (!quiet_mode) |
234 |
debug("[ bt459: cursor = %03i,%03i ]\n", |
235 |
d->cursor_x, d->cursor_y); |
236 |
|
237 |
on = d->cursor_on; |
238 |
if (d->cursor_xsize == 0 || d->cursor_ysize == 0) |
239 |
on = 0; |
240 |
|
241 |
dev_fb_setcursor(d->vfb_data, d->cursor_x, d->cursor_y, |
242 |
on, d->cursor_xsize, d->cursor_ysize); |
243 |
} |
244 |
} |
245 |
|
246 |
|
247 |
/* |
248 |
* dev_bt459_tick(): |
249 |
*/ |
250 |
void dev_bt459_tick(struct cpu *cpu, void *extra) |
251 |
{ |
252 |
struct bt459_data *d = extra; |
253 |
int old_cursor_on = d->cursor_on; |
254 |
|
255 |
if (d->need_to_update_cursor_shape) { |
256 |
d->need_to_update_cursor_shape = 0; |
257 |
bt459_update_X_cursor(cpu, d); |
258 |
bt459_update_cursor_position(d, old_cursor_on); |
259 |
} |
260 |
|
261 |
if (d->need_to_redraw_whole_screen) { |
262 |
d->vfb_data->update_x1 = 0; |
263 |
d->vfb_data->update_x2 = d->vfb_data->xsize - 1; |
264 |
d->vfb_data->update_y1 = 0; |
265 |
d->vfb_data->update_y2 = d->vfb_data->ysize - 1; |
266 |
d->need_to_redraw_whole_screen = 0; |
267 |
} |
268 |
|
269 |
/* |
270 |
* Vertical retrace interrupts. (This hack is kind of ugly.) |
271 |
* Once every 'interrupt_time_reset_value', the interrupt is |
272 |
* asserted. It is acked either manually (by someone reading |
273 |
* a normal BT459 register or the Interrupt ack register), |
274 |
* or after another tick has passed. (This is to prevent |
275 |
* lockups from unhandled interrupts.) |
276 |
*/ |
277 |
if (d->type != BT459_PX && d->interrupts_enable && d->irq_nr > 0) { |
278 |
d->interrupt_time --; |
279 |
if (d->interrupt_time < 0) { |
280 |
d->interrupt_time = d->interrupt_time_reset_value; |
281 |
cpu_interrupt(cpu, d->irq_nr); |
282 |
} else |
283 |
cpu_interrupt_ack(cpu, d->irq_nr); |
284 |
} |
285 |
} |
286 |
|
287 |
|
288 |
/* |
289 |
* dev_bt459_irq_access(): |
290 |
*/ |
291 |
DEVICE_ACCESS(bt459_irq) |
292 |
{ |
293 |
struct bt459_data *d = (struct bt459_data *) extra; |
294 |
uint64_t idata = 0, odata = 0; |
295 |
|
296 |
if (writeflag == MEM_WRITE) |
297 |
idata = memory_readmax64(cpu, data, len); |
298 |
|
299 |
#ifdef BT459_DEBUG |
300 |
fatal("[ bt459: IRQ ack ]\n"); |
301 |
#endif |
302 |
|
303 |
d->interrupts_enable = 1; |
304 |
if (d->irq_nr > 0) |
305 |
cpu_interrupt_ack(cpu, d->irq_nr); |
306 |
|
307 |
if (writeflag == MEM_READ) |
308 |
memory_writemax64(cpu, data, len, odata); |
309 |
|
310 |
return 1; |
311 |
} |
312 |
|
313 |
|
314 |
/* |
315 |
* dev_bt459_access(): |
316 |
*/ |
317 |
DEVICE_ACCESS(bt459) |
318 |
{ |
319 |
struct bt459_data *d = (struct bt459_data *) extra; |
320 |
uint64_t idata = 0, odata = 0; |
321 |
int btaddr, old_cursor_on = d->cursor_on, modified; |
322 |
|
323 |
idata = memory_readmax64(cpu, data, len); |
324 |
|
325 |
#ifdef BT459_DEBUG |
326 |
if (writeflag == MEM_WRITE) |
327 |
fatal("[ bt459: write to addr 0x%02x: %08x ]\n", |
328 |
(int)relative_addr, (int)idata); |
329 |
#endif |
330 |
|
331 |
/* |
332 |
* Vertical retrace interrupts are acked either by |
333 |
* accessing a normal BT459 register, or the irq register, |
334 |
* or by simply "missing" it. |
335 |
*/ |
336 |
if (d->irq_nr > 0) |
337 |
cpu_interrupt_ack(cpu, d->irq_nr); |
338 |
|
339 |
/* ID register is read-only, should always be 0x4a or 0x4a4a4a: */ |
340 |
if (d->planes == 24) |
341 |
d->bt459_reg[BT459_REG_ID] = 0x4a4a4a; |
342 |
else { |
343 |
/* |
344 |
* TODO: Is it really 0x4a, or 0x4a0000? |
345 |
* Ultrix panics with a "bad VDAC ID" message if 0x4a |
346 |
* is returned. |
347 |
*/ |
348 |
d->bt459_reg[BT459_REG_ID] = 0x4a0000; |
349 |
} |
350 |
|
351 |
btaddr = ((d->cur_addr_hi << 8) + d->cur_addr_lo) % DEV_BT459_NREGS; |
352 |
|
353 |
/* Read from/write to the bt459: */ |
354 |
switch (relative_addr) { |
355 |
case 0x00: /* Low byte of address: */ |
356 |
if (writeflag == MEM_WRITE) { |
357 |
if (!quiet_mode) |
358 |
debug("[ bt459: write to Low Address Byte, " |
359 |
"0x%02x ]\n", (int)idata); |
360 |
d->cur_addr_lo = idata; |
361 |
d->palette_sub_offset = 0; |
362 |
} else { |
363 |
odata = d->cur_addr_lo; |
364 |
if (!quiet_mode) |
365 |
debug("[ bt459: read from Low Address Byte: " |
366 |
"0x%0x ]\n", (int)odata); |
367 |
} |
368 |
break; |
369 |
case 0x04: /* High byte of address: */ |
370 |
if (writeflag == MEM_WRITE) { |
371 |
if (!quiet_mode) |
372 |
debug("[ bt459: write to High Address Byte, " |
373 |
"0x%02x ]\n", (int)idata); |
374 |
d->cur_addr_hi = idata; |
375 |
d->palette_sub_offset = 0; |
376 |
} else { |
377 |
odata = d->cur_addr_hi; |
378 |
if (!quiet_mode) |
379 |
debug("[ bt459: read from High Address Byte: " |
380 |
"0x%0x ]\n", (int)odata); |
381 |
} |
382 |
break; |
383 |
case 0x08: /* Register access: */ |
384 |
if (writeflag == MEM_WRITE) { |
385 |
if (!quiet_mode) |
386 |
debug("[ bt459: write to BT459 register " |
387 |
"0x%04x, value 0x%02x ]\n", btaddr, |
388 |
(int)idata); |
389 |
modified = (d->bt459_reg[btaddr] != idata); |
390 |
d->bt459_reg[btaddr] = idata; |
391 |
|
392 |
switch (btaddr) { |
393 |
case BT459_REG_CCOLOR_1: |
394 |
case BT459_REG_CCOLOR_2: |
395 |
case BT459_REG_CCOLOR_3: |
396 |
if (modified) |
397 |
d->need_to_update_cursor_shape = 1; |
398 |
break; |
399 |
case BT459_REG_PRM: |
400 |
/* |
401 |
* NetBSD writes 0x00 to this register to |
402 |
* blank the screen (video off), and 0xff |
403 |
* to turn the screen on. |
404 |
*/ |
405 |
switch (idata & 0xff) { |
406 |
case 0: d->video_on = 0; |
407 |
memset(d->rgb_palette, 0, 256*3); |
408 |
d->need_to_redraw_whole_screen = 1; |
409 |
debug("[ bt459: video OFF ]\n"); |
410 |
break; |
411 |
default:d->video_on = 1; |
412 |
memcpy(d->rgb_palette, |
413 |
d->local_rgb_palette, 256*3); |
414 |
d->need_to_redraw_whole_screen = 1; |
415 |
debug("[ bt459: video ON ]\n"); |
416 |
} |
417 |
break; |
418 |
case BT459_REG_CCR: |
419 |
/* Cursor control register: */ |
420 |
switch (idata & 0xff) { |
421 |
case 0x00: d->cursor_on = 0; break; |
422 |
case 0xc0: |
423 |
case 0xc1: d->cursor_on = 1; break; |
424 |
default: |
425 |
fatal("[ bt459: unimplemented CCR " |
426 |
"value 0x%08x ]\n", (int)idata); |
427 |
} |
428 |
if (modified) |
429 |
d->need_to_update_cursor_shape = 1; |
430 |
break; |
431 |
default: |
432 |
if (btaddr < 0x100) |
433 |
fatal("[ bt459: write to BT459 " |
434 |
"register 0x%04x, value 0x%02x ]\n", |
435 |
btaddr, (int)idata); |
436 |
} |
437 |
|
438 |
/* Write to cursor bitmap: */ |
439 |
if (btaddr >= BT459_REG_CRAM_BASE && modified) |
440 |
d->need_to_update_cursor_shape = 1; |
441 |
} else { |
442 |
odata = d->bt459_reg[btaddr]; |
443 |
|
444 |
/* Perhaps this hack is not necessary: */ |
445 |
if (btaddr == BT459_REG_ID && len==1) |
446 |
odata = (odata >> 16) & 255; |
447 |
|
448 |
if (!quiet_mode) |
449 |
debug("[ bt459: read from BT459 register " |
450 |
"0x%04x, value 0x%02x ]\n", btaddr, |
451 |
(int)odata); |
452 |
} |
453 |
|
454 |
/* Go to next register: */ |
455 |
d->cur_addr_lo ++; |
456 |
if (d->cur_addr_lo == 0) |
457 |
d->cur_addr_hi ++; |
458 |
break; |
459 |
case 0xc: /* Color map: */ |
460 |
if (writeflag == MEM_WRITE) { |
461 |
idata &= 255; |
462 |
if (!quiet_mode) |
463 |
debug("[ bt459: write to BT459 colormap " |
464 |
"0x%04x subaddr %i, value 0x%02x ]\n", |
465 |
btaddr, d->palette_sub_offset, (int)idata); |
466 |
|
467 |
if (btaddr < 0x100) { |
468 |
if (d->video_on && |
469 |
d->local_rgb_palette[(btaddr & 0xff) * 3 |
470 |
+ d->palette_sub_offset] != idata) |
471 |
d->need_to_redraw_whole_screen = 1; |
472 |
|
473 |
/* |
474 |
* Actually, the palette should only be |
475 |
* updated after the third write, |
476 |
* but this should probably work fine too: |
477 |
*/ |
478 |
d->local_rgb_palette[(btaddr & 0xff) * 3 |
479 |
+ d->palette_sub_offset] = idata; |
480 |
|
481 |
if (d->video_on) |
482 |
d->rgb_palette[(btaddr & 0xff) * 3 |
483 |
+ d->palette_sub_offset] = idata; |
484 |
} |
485 |
} else { |
486 |
if (btaddr < 0x100) |
487 |
odata = d->local_rgb_palette[(btaddr & 0xff) |
488 |
* 3 + d->palette_sub_offset]; |
489 |
if (!quiet_mode) |
490 |
debug("[ bt459: read from BT459 colormap " |
491 |
"0x%04x subaddr %i, value 0x%02x ]\n", |
492 |
btaddr, d->palette_sub_offset, (int)odata); |
493 |
} |
494 |
|
495 |
d->palette_sub_offset ++; |
496 |
if (d->palette_sub_offset >= 3) { |
497 |
d->palette_sub_offset = 0; |
498 |
|
499 |
d->cur_addr_lo ++; |
500 |
if (d->cur_addr_lo == 0) |
501 |
d->cur_addr_hi ++; |
502 |
} |
503 |
|
504 |
break; |
505 |
default: |
506 |
if (writeflag == MEM_WRITE) { |
507 |
debug("[ bt459: unimplemented write to address 0x%x, " |
508 |
"data=0x%02x ]\n", (int)relative_addr, (int)idata); |
509 |
} else { |
510 |
debug("[ bt459: unimplemented read from address " |
511 |
"0x%x ]\n", (int)relative_addr); |
512 |
} |
513 |
} |
514 |
|
515 |
|
516 |
bt459_update_cursor_position(d, old_cursor_on); |
517 |
|
518 |
if (writeflag == MEM_READ) |
519 |
memory_writemax64(cpu, data, len, odata); |
520 |
|
521 |
#ifdef BT459_DEBUG |
522 |
if (writeflag == MEM_READ) |
523 |
fatal("[ bt459: read from addr 0x%02x: %08x ]\n", |
524 |
(int)relative_addr, (int)idata); |
525 |
#endif |
526 |
|
527 |
return 1; |
528 |
} |
529 |
|
530 |
|
531 |
/* |
532 |
* dev_bt459_init(): |
533 |
*/ |
534 |
void dev_bt459_init(struct machine *machine, struct memory *mem, |
535 |
uint64_t baseaddr, uint64_t baseaddr_irq, struct vfb_data *vfb_data, |
536 |
int planes, int irq_nr, int type) |
537 |
{ |
538 |
struct bt459_data *d = malloc(sizeof(struct bt459_data)); |
539 |
if (d == NULL) { |
540 |
fprintf(stderr, "out of memory\n"); |
541 |
exit(1); |
542 |
} |
543 |
|
544 |
memset(d, 0, sizeof(struct bt459_data)); |
545 |
|
546 |
d->vfb_data = vfb_data; |
547 |
d->rgb_palette = vfb_data->rgb_palette; |
548 |
d->planes = planes; |
549 |
d->irq_nr = irq_nr; |
550 |
d->type = type; |
551 |
d->cursor_x = -1; |
552 |
d->cursor_y = -1; |
553 |
d->cursor_xsize = d->cursor_ysize = 0; /* anything */ |
554 |
d->video_on = 1; |
555 |
|
556 |
/* |
557 |
* These offsets are based on those mentioned in NetBSD, |
558 |
* and then adjusted to look good with both NetBSD and |
559 |
* Ultrix: |
560 |
*/ |
561 |
switch (d->type) { |
562 |
case BT459_PX: |
563 |
d->cursor_x_add = 370; |
564 |
d->cursor_y_add = 37; |
565 |
break; |
566 |
case BT459_BA: |
567 |
d->cursor_x_add = 220; |
568 |
d->cursor_y_add = 35; |
569 |
break; |
570 |
case BT459_BBA: |
571 |
if (vfb_data->xsize == 1280) { |
572 |
/* 1280x1024: */ |
573 |
d->cursor_x_add = 368; |
574 |
d->cursor_y_add = 38; |
575 |
} else { |
576 |
/* 1024x864: */ |
577 |
d->cursor_x_add = 220; |
578 |
d->cursor_y_add = 35; |
579 |
} |
580 |
break; |
581 |
} |
582 |
|
583 |
d->interrupt_time_reset_value = 500; |
584 |
|
585 |
memory_device_register(mem, "bt459", baseaddr, DEV_BT459_LENGTH, |
586 |
dev_bt459_access, (void *)d, DM_DEFAULT, NULL); |
587 |
|
588 |
if (baseaddr_irq != 0) |
589 |
memory_device_register(mem, "bt459_irq", baseaddr_irq, 0x10000, |
590 |
dev_bt459_irq_access, (void *)d, DM_DEFAULT, NULL); |
591 |
|
592 |
machine_add_tickfunction(machine, dev_bt459_tick, d, BT459_TICK_SHIFT); |
593 |
} |
594 |
|